--- a/.hgtags Thu Nov 03 13:26:57 2011 -0700
+++ b/.hgtags Sat Nov 05 00:00:43 2011 -0700
@@ -132,3 +132,4 @@
24ee504f80412770c6874836cd9e55b536427b1d jdk8-b08
fbf3cabc9e3bb1fcf710941d777cb0400505fbe6 jdk8-b09
f651ce87127980c58e3599daba964eba2f3b4026 jdk8-b10
+cc1f5ce8e504d350e0b0c28c5f84333f8d540132 jdk8-b11
--- a/.hgtags-top-repo Thu Nov 03 13:26:57 2011 -0700
+++ b/.hgtags-top-repo Sat Nov 05 00:00:43 2011 -0700
@@ -132,3 +132,4 @@
fb1bc13260d76447e269e843859eb593fe2a8ab2 jdk8-b08
8adb70647b5af5273dfe6a540f07be667cd50216 jdk8-b09
a6c4c248e8fa350c35014fa94bab5ac1a1ac3299 jdk8-b10
+1defbc57940a56f0aa41e9dee87b71e8c8b71103 jdk8-b11
--- a/corba/.hgtags Thu Nov 03 13:26:57 2011 -0700
+++ b/corba/.hgtags Sat Nov 05 00:00:43 2011 -0700
@@ -132,3 +132,4 @@
0d52b1c87aa8fdea7fdc9c4126ea58f95ca6b351 jdk8-b08
a891732c1a83082177ff7a4cf1506068d9cc0a47 jdk8-b09
cda87f7fefcee3b89742a57ce5ad9b03a54c210d jdk8-b10
+0199e4fef5cc2bd234c65b93220459ef7a3bb3b1 jdk8-b11
--- a/hotspot/.hgtags Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/.hgtags Sat Nov 05 00:00:43 2011 -0700
@@ -193,3 +193,5 @@
e4f412d2b75d2c797acff965aa2c420e3d358f09 hs23-b02
d815de2e85e511b7deab2a83cf80c0224d011da9 jdk8-b10
4d3850d9d326ac3a9bee2d867727e954322d014e hs23-b03
+4538caeef7b6cbd4302bebced805d65e68ccf301 jdk8-b11
+6534482ff68ad79066dfe15dfb6d8905f09681bd hs23-b04
--- a/hotspot/make/hotspot_version Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/make/hotspot_version Sat Nov 05 00:00:43 2011 -0700
@@ -35,7 +35,7 @@
HS_MAJOR_VER=23
HS_MINOR_VER=0
-HS_BUILD_NUMBER=03
+HS_BUILD_NUMBER=04
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -62,7 +62,7 @@
MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment;
assert(IndexSetStart == 0 && IndexSetStride == 0, "already set");
- IndexSetStart = MinObjAlignment;
+ IndexSetStart = (int) MinChunkSize;
IndexSetStride = MinObjAlignment;
}
@@ -138,7 +138,7 @@
} else {
_fitStrategy = FreeBlockStrategyNone;
}
- checkFreeListConsistency();
+ check_free_list_consistency();
// Initialize locks for parallel case.
@@ -1358,17 +1358,29 @@
ShouldNotReachHere();
}
-bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc)
- const {
+bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const {
assert(fc->size() < IndexSetSize, "Size of chunk is too large");
return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc);
}
+bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const {
+ assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) ||
+ (_smallLinearAllocBlock._word_size == fc->size()),
+ "Linear allocation block shows incorrect size");
+ return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) &&
+ (_smallLinearAllocBlock._word_size == fc->size()));
+}
+
+// Check if the purported free chunk is present either as a linear
+// allocation block, the size-indexed table of (smaller) free blocks,
+// or the larger free blocks kept in the binary tree dictionary.
bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const {
- if (fc->size() >= IndexSetSize) {
+ if (verify_chunk_is_linear_alloc_block(fc)) {
+ return true;
+ } else if (fc->size() < IndexSetSize) {
+ return verifyChunkInIndexedFreeLists(fc);
+ } else {
return dictionary()->verifyChunkInFreeLists(fc);
- } else {
- return verifyChunkInIndexedFreeLists(fc);
}
}
@@ -2495,7 +2507,8 @@
FreeChunk* tail = _indexedFreeList[size].tail();
size_t num = _indexedFreeList[size].count();
size_t n = 0;
- guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty");
+ guarantee(((size >= MinChunkSize) && (size % IndexSetStride == 0)) || fc == NULL,
+ "Slot should have been empty");
for (; fc != NULL; fc = fc->next(), n++) {
guarantee(fc->size() == size, "Size inconsistency");
guarantee(fc->isFree(), "!free?");
@@ -2506,14 +2519,14 @@
}
#ifndef PRODUCT
-void CompactibleFreeListSpace::checkFreeListConsistency() const {
+void CompactibleFreeListSpace::check_free_list_consistency() const {
assert(_dictionary->minSize() <= IndexSetSize,
"Some sizes can't be allocated without recourse to"
" linear allocation buffers");
assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk),
"else MIN_TREE_CHUNK_SIZE is wrong");
- assert((IndexSetStride == 2 && IndexSetStart == 2) ||
- (IndexSetStride == 1 && IndexSetStart == 1), "just checking");
+ assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit
+ (IndexSetStride == 1 && IndexSetStart == 3), "just checking"); // 64-bit
assert((IndexSetStride != 2) || (MinChunkSize % 2 == 0),
"Some for-loops may be incorrectly initialized");
assert((IndexSetStride != 2) || (IndexSetSize % 2 == 1),
@@ -2688,33 +2701,27 @@
}
}
+// If this is changed in the future to allow parallel
+// access, one would need to take the FL locks and,
+// depending on how it is used, stagger access from
+// parallel threads to reduce contention.
void CFLS_LAB::retire(int tid) {
// We run this single threaded with the world stopped;
// so no need for locks and such.
-#define CFLS_LAB_PARALLEL_ACCESS 0
NOT_PRODUCT(Thread* t = Thread::current();)
assert(Thread::current()->is_VM_thread(), "Error");
- assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride,
- "Will access to uninitialized slot below");
-#if CFLS_LAB_PARALLEL_ACCESS
- for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1;
- i > 0;
- i -= CompactibleFreeListSpace::IndexSetStride) {
-#else // CFLS_LAB_PARALLEL_ACCESS
for (size_t i = CompactibleFreeListSpace::IndexSetStart;
i < CompactibleFreeListSpace::IndexSetSize;
i += CompactibleFreeListSpace::IndexSetStride) {
-#endif // !CFLS_LAB_PARALLEL_ACCESS
assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(),
"Can't retire more than what we obtained");
if (_num_blocks[i] > 0) {
size_t num_retire = _indexedFreeList[i].count();
assert(_num_blocks[i] > num_retire, "Should have used at least one");
{
-#if CFLS_LAB_PARALLEL_ACCESS
- MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
- Mutex::_no_safepoint_check_flag);
-#endif // CFLS_LAB_PARALLEL_ACCESS
+ // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
+ // Mutex::_no_safepoint_check_flag);
+
// Update globals stats for num_blocks used
_global_num_blocks[i] += (_num_blocks[i] - num_retire);
_global_num_workers[i]++;
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Sat Nov 05 00:00:43 2011 -0700
@@ -502,10 +502,14 @@
void verifyFreeLists() const PRODUCT_RETURN;
void verifyIndexedFreeLists() const;
void verifyIndexedFreeList(size_t size) const;
- // verify that the given chunk is in the free lists.
+ // Verify that the given chunk is in the free lists:
+ // i.e. either the binary tree dictionary, the indexed free lists
+ // or the linear allocation block.
bool verifyChunkInFreeLists(FreeChunk* fc) const;
+ // Verify that the given chunk is the linear allocation block
+ bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const;
// Do some basic checks on the the free lists.
- void checkFreeListConsistency() const PRODUCT_RETURN;
+ void check_free_list_consistency() const PRODUCT_RETURN;
// Printing support
void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -147,12 +147,8 @@
}
}
} while (cm()->restart_for_overflow());
+
double counting_start_time = os::elapsedVTime();
-
- // YSR: These look dubious (i.e. redundant) !!! FIX ME
- slt()->manipulatePLL(SurrogateLockerThread::acquirePLL);
- slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
-
if (!cm()->has_aborted()) {
double count_start_sec = os::elapsedTime();
if (PrintGC) {
@@ -175,6 +171,7 @@
}
}
}
+
double end_time = os::elapsedVTime();
_vtime_count_accum += (end_time - counting_start_time);
// Update the total virtual time before doing this, since it will try
@@ -335,13 +332,15 @@
clear_started();
}
-// Note: this method, although exported by the ConcurrentMarkSweepThread,
-// which is a non-JavaThread, can only be called by a JavaThread.
-// Currently this is done at vm creation time (post-vm-init) by the
-// main/Primordial (Java)Thread.
-// XXX Consider changing this in the future to allow the CMS thread
+// Note: As is the case with CMS - this method, although exported
+// by the ConcurrentMarkThread, which is a non-JavaThread, can only
+// be called by a JavaThread. Currently this is done at vm creation
+// time (post-vm-init) by the main/Primordial (Java)Thread.
+// XXX Consider changing this in the future to allow the CM thread
// itself to create this thread?
void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
+ assert(UseG1GC, "SLT thread needed only for concurrent GC");
+ assert(THREAD->is_Java_thread(), "must be a Java thread");
assert(_slt == NULL, "SLT already created");
_slt = SurrogateLockerThread::make(THREAD);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -5502,34 +5502,36 @@
CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set());
double start = os::elapsedTime();
- // Iterate over the dirty cards region list.
- G1ParCleanupCTTask cleanup_task(ct_bs, this);
-
- if (ParallelGCThreads > 0) {
- set_par_threads(workers()->total_workers());
- workers()->run_task(&cleanup_task);
- set_par_threads(0);
- } else {
- while (_dirty_cards_region_list) {
- HeapRegion* r = _dirty_cards_region_list;
- cleanup_task.clear_cards(r);
- _dirty_cards_region_list = r->get_next_dirty_cards_region();
- if (_dirty_cards_region_list == r) {
- // The last region.
- _dirty_cards_region_list = NULL;
+ {
+ // Iterate over the dirty cards region list.
+ G1ParCleanupCTTask cleanup_task(ct_bs, this);
+
+ if (ParallelGCThreads > 0) {
+ set_par_threads(workers()->total_workers());
+ workers()->run_task(&cleanup_task);
+ set_par_threads(0);
+ } else {
+ while (_dirty_cards_region_list) {
+ HeapRegion* r = _dirty_cards_region_list;
+ cleanup_task.clear_cards(r);
+ _dirty_cards_region_list = r->get_next_dirty_cards_region();
+ if (_dirty_cards_region_list == r) {
+ // The last region.
+ _dirty_cards_region_list = NULL;
+ }
+ r->set_next_dirty_cards_region(NULL);
}
- r->set_next_dirty_cards_region(NULL);
}
+#ifndef PRODUCT
+ if (G1VerifyCTCleanup || VerifyAfterGC) {
+ G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs);
+ heap_region_iterate(&cleanup_verifier);
+ }
+#endif
}
double elapsed = os::elapsedTime() - start;
g1_policy()->record_clear_ct_time(elapsed * 1000.0);
-#ifndef PRODUCT
- if (G1VerifyCTCleanup || VerifyAfterGC) {
- G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs);
- heap_region_iterate(&cleanup_verifier);
- }
-#endif
}
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -320,6 +320,7 @@
_par_last_termination_attempts = new double[_parallel_gc_threads];
_par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
_par_last_gc_worker_times_ms = new double[_parallel_gc_threads];
+ _par_last_gc_worker_other_times_ms = new double[_parallel_gc_threads];
// start conservatively
_expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
@@ -497,7 +498,6 @@
initialize_gc_policy_counters();
G1YoungGenSizer sizer;
- size_t initial_region_num = sizer.initial_young_region_num();
_min_desired_young_length = sizer.min_young_region_num();
_max_desired_young_length = sizer.max_young_region_num();
@@ -511,17 +511,14 @@
}
}
- // GenCollectorPolicy guarantees that min <= initial <= max.
- // Asserting here just to state that we rely on this property.
assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");
- assert(initial_region_num <= _max_desired_young_length, "Initial young gen size too large");
- assert(_min_desired_young_length <= initial_region_num, "Initial young gen size too small");
set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length);
if (adaptive_young_list_length()) {
_young_list_fixed_length = 0;
} else {
- _young_list_fixed_length = initial_region_num;
+ assert(_min_desired_young_length == _max_desired_young_length, "Min and max young size differ");
+ _young_list_fixed_length = _min_desired_young_length;
}
_free_regions_at_end_of_collection = _g1->free_regions();
update_young_list_target_length();
@@ -976,6 +973,7 @@
_par_last_termination_attempts[i] = -1234.0;
_par_last_gc_worker_end_times_ms[i] = -1234.0;
_par_last_gc_worker_times_ms[i] = -1234.0;
+ _par_last_gc_worker_other_times_ms[i] = -1234.0;
}
#endif
@@ -984,8 +982,10 @@
_cur_aux_times_set[i] = false;
}
- _satb_drain_time_set = false;
- _last_satb_drain_processed_buffers = -1;
+ // These are initialized to zero here and they are set during
+ // the evacuation pause if marking is in progress.
+ _cur_satb_drain_time_ms = 0.0;
+ _last_satb_drain_processed_buffers = 0;
_last_young_gc_full = false;
@@ -1097,61 +1097,65 @@
(int)total, (int)avg, (int)min, (int)max, (int)max - (int)min);
}
-void G1CollectorPolicy::print_stats (int level,
- const char* str,
- double value) {
+void G1CollectorPolicy::print_stats(int level,
+ const char* str,
+ double value) {
LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value);
}
-void G1CollectorPolicy::print_stats (int level,
- const char* str,
- int value) {
+void G1CollectorPolicy::print_stats(int level,
+ const char* str,
+ int value) {
LineBuffer(level).append_and_print_cr("[%s: %d]", str, value);
}
-double G1CollectorPolicy::avg_value (double* data) {
+double G1CollectorPolicy::avg_value(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double ret = 0.0;
- for (uint i = 0; i < ParallelGCThreads; ++i)
+ for (uint i = 0; i < ParallelGCThreads; ++i) {
ret += data[i];
+ }
return ret / (double) ParallelGCThreads;
} else {
return data[0];
}
}
-double G1CollectorPolicy::max_value (double* data) {
+double G1CollectorPolicy::max_value(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double ret = data[0];
- for (uint i = 1; i < ParallelGCThreads; ++i)
- if (data[i] > ret)
+ for (uint i = 1; i < ParallelGCThreads; ++i) {
+ if (data[i] > ret) {
ret = data[i];
+ }
+ }
return ret;
} else {
return data[0];
}
}
-double G1CollectorPolicy::sum_of_values (double* data) {
+double G1CollectorPolicy::sum_of_values(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double sum = 0.0;
- for (uint i = 0; i < ParallelGCThreads; i++)
+ for (uint i = 0; i < ParallelGCThreads; i++) {
sum += data[i];
+ }
return sum;
} else {
return data[0];
}
}
-double G1CollectorPolicy::max_sum (double* data1,
- double* data2) {
+double G1CollectorPolicy::max_sum(double* data1, double* data2) {
double ret = data1[0] + data2[0];
if (G1CollectedHeap::use_parallel_gc_threads()) {
for (uint i = 1; i < ParallelGCThreads; ++i) {
double data = data1[i] + data2[i];
- if (data > ret)
+ if (data > ret) {
ret = data;
+ }
}
}
return ret;
@@ -1251,6 +1255,10 @@
_n_pauses++;
+ // These values are used to update the summary information that is
+ // displayed when TraceGen0Time is enabled, and are output as part
+ // of the PrintGCDetails output, in the non-parallel case.
+
double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
double mark_stack_scan_time = avg_value(_par_last_mark_stack_scan_times_ms);
double update_rs_time = avg_value(_par_last_update_rs_times_ms);
@@ -1260,42 +1268,68 @@
double obj_copy_time = avg_value(_par_last_obj_copy_times_ms);
double termination_time = avg_value(_par_last_termination_times_ms);
- double parallel_known_time = update_rs_time +
- ext_root_scan_time +
- mark_stack_scan_time +
- scan_rs_time +
- obj_copy_time +
- termination_time;
-
- double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time;
-
- PauseSummary* summary = _summary;
+ double known_time = ext_root_scan_time +
+ mark_stack_scan_time +
+ update_rs_time +
+ scan_rs_time +
+ obj_copy_time;
+
+ double other_time_ms = elapsed_ms;
+
+ // Subtract the SATB drain time. It's initialized to zero at the
+ // start of the pause and is updated during the pause if marking
+ // is in progress.
+ other_time_ms -= _cur_satb_drain_time_ms;
+
+ if (parallel) {
+ other_time_ms -= _cur_collection_par_time_ms;
+ } else {
+ other_time_ms -= known_time;
+ }
+
+ // Subtract the time taken to clean the card table from the
+ // current value of "other time"
+ other_time_ms -= _cur_clear_ct_time_ms;
+
+ // TraceGen0Time and TraceGen1Time summary info updating.
+ _all_pause_times_ms->add(elapsed_ms);
if (update_stats) {
_recent_rs_scan_times_ms->add(scan_rs_time);
_recent_pause_times_ms->add(elapsed_ms);
_recent_rs_sizes->add(rs_size);
- MainBodySummary* body_summary = summary->main_body_summary();
- guarantee(body_summary != NULL, "should not be null!");
-
- if (_satb_drain_time_set)
- body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
- else
- body_summary->record_satb_drain_time_ms(0.0);
+ _summary->record_total_time_ms(elapsed_ms);
+ _summary->record_other_time_ms(other_time_ms);
+
+ MainBodySummary* body_summary = _summary->main_body_summary();
+ assert(body_summary != NULL, "should not be null!");
+
+ // This will be non-zero iff marking is currently in progress (i.e.
+ // _g1->mark_in_progress() == true) and the currrent pause was not
+ // an initial mark pause. Since the body_summary items are NumberSeqs,
+ // however, they have to be consistent and updated in lock-step with
+ // each other. Therefore we unconditionally record the SATB drain
+ // time - even if it's zero.
+ body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
body_summary->record_ext_root_scan_time_ms(ext_root_scan_time);
body_summary->record_mark_stack_scan_time_ms(mark_stack_scan_time);
body_summary->record_update_rs_time_ms(update_rs_time);
body_summary->record_scan_rs_time_ms(scan_rs_time);
body_summary->record_obj_copy_time_ms(obj_copy_time);
+
if (parallel) {
body_summary->record_parallel_time_ms(_cur_collection_par_time_ms);
- body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
body_summary->record_termination_time_ms(termination_time);
+
+ double parallel_known_time = known_time + termination_time;
+ double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time;
body_summary->record_parallel_other_time_ms(parallel_other_time);
}
+
body_summary->record_mark_closure_time_ms(_mark_closure_time_ms);
+ body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
// We exempt parallel collection from this check because Alloc Buffer
// fragmentation can produce negative collections. Same with evac
@@ -1307,6 +1341,7 @@
|| _g1->evacuation_failed()
|| surviving_bytes <= _collection_set_bytes_used_before,
"Or else negative collection!");
+
_recent_CS_bytes_used_before->add(_collection_set_bytes_used_before);
_recent_CS_bytes_surviving->add(surviving_bytes);
@@ -1357,6 +1392,13 @@
}
}
+ for (int i = 0; i < _aux_num; ++i) {
+ if (_cur_aux_times_set[i]) {
+ _all_aux_times_ms[i].add(_cur_aux_times_ms[i]);
+ }
+ }
+
+
if (G1PolicyVerbose > 1) {
gclog_or_tty->print_cr(" Recording collection pause(%d)", _n_pauses);
}
@@ -1383,61 +1425,60 @@
recent_avg_pause_time_ratio() * 100.0);
}
- double other_time_ms = elapsed_ms;
-
- if (_satb_drain_time_set) {
- other_time_ms -= _cur_satb_drain_time_ms;
- }
-
- if (parallel) {
- other_time_ms -= _cur_collection_par_time_ms + _cur_clear_ct_time_ms;
- } else {
- other_time_ms -=
- update_rs_time +
- ext_root_scan_time + mark_stack_scan_time +
- scan_rs_time + obj_copy_time;
- }
-
+ // PrintGCDetails output
if (PrintGCDetails) {
+ bool print_marking_info =
+ _g1->mark_in_progress() && !last_pause_included_initial_mark;
+
gclog_or_tty->print_cr("%s, %1.8lf secs]",
(last_pause_included_initial_mark) ? " (initial-mark)" : "",
elapsed_ms / 1000.0);
- if (_satb_drain_time_set) {
+ if (print_marking_info) {
print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms);
- }
- if (_last_satb_drain_processed_buffers >= 0) {
print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers);
}
+
if (parallel) {
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
- print_par_stats(2, "GC Worker Start Time", _par_last_gc_worker_start_times_ms);
+ print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms);
+ print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
+ if (print_marking_info) {
+ print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
+ }
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers);
- print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
- print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
print_par_stats(2, "Termination", _par_last_termination_times_ms);
print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
- print_par_stats(2, "GC Worker End Time", _par_last_gc_worker_end_times_ms);
+ print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
for (int i = 0; i < _parallel_gc_threads; i++) {
_par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - _par_last_gc_worker_start_times_ms[i];
+
+ double worker_known_time = _par_last_ext_root_scan_times_ms[i] +
+ _par_last_mark_stack_scan_times_ms[i] +
+ _par_last_update_rs_times_ms[i] +
+ _par_last_scan_rs_times_ms[i] +
+ _par_last_obj_copy_times_ms[i] +
+ _par_last_termination_times_ms[i];
+
+ _par_last_gc_worker_other_times_ms[i] = _cur_collection_par_time_ms - worker_known_time;
}
- print_par_stats(2, "GC Worker Times", _par_last_gc_worker_times_ms);
-
- print_stats(2, "Parallel Other", parallel_other_time);
- print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
+ print_par_stats(2, "GC Worker", _par_last_gc_worker_times_ms);
+ print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms);
} else {
+ print_stats(1, "Ext Root Scanning", ext_root_scan_time);
+ if (print_marking_info) {
+ print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
+ }
print_stats(1, "Update RS", update_rs_time);
- print_stats(2, "Processed Buffers",
- (int)update_rs_processed_buffers);
- print_stats(1, "Ext Root Scanning", ext_root_scan_time);
- print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
+ print_stats(2, "Processed Buffers", (int)update_rs_processed_buffers);
print_stats(1, "Scan RS", scan_rs_time);
print_stats(1, "Object Copying", obj_copy_time);
}
+ print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
#ifndef PRODUCT
print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
print_stats(1, "Cum Clear CC", _cum_clear_cc_time_ms);
@@ -1461,16 +1502,6 @@
}
}
- _all_pause_times_ms->add(elapsed_ms);
- if (update_stats) {
- summary->record_total_time_ms(elapsed_ms);
- summary->record_other_time_ms(other_time_ms);
- }
- for (int i = 0; i < _aux_num; ++i)
- if (_cur_aux_times_set[i]) {
- _all_aux_times_ms[i].add(_cur_aux_times_ms[i]);
- }
-
// Update the efficiency-since-mark vars.
double proc_ms = elapsed_ms * (double) _parallel_gc_threads;
if (elapsed_ms < MIN_TIMER_GRANULARITY) {
@@ -2138,17 +2169,17 @@
_g1->collection_set_iterate(&cs_closure);
}
-void G1CollectorPolicy::print_summary (int level,
- const char* str,
- NumberSeq* seq) const {
+void G1CollectorPolicy::print_summary(int level,
+ const char* str,
+ NumberSeq* seq) const {
double sum = seq->sum();
LineBuffer(level + 1).append_and_print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)",
str, sum / 1000.0, seq->avg());
}
-void G1CollectorPolicy::print_summary_sd (int level,
- const char* str,
- NumberSeq* seq) const {
+void G1CollectorPolicy::print_summary_sd(int level,
+ const char* str,
+ NumberSeq* seq) const {
print_summary(level, str, seq);
LineBuffer(level + 6).append_and_print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)",
seq->num(), seq->sd(), seq->maximum());
@@ -2211,20 +2242,18 @@
print_summary(1, "SATB Drain", body_summary->get_satb_drain_seq());
if (parallel) {
print_summary(1, "Parallel Time", body_summary->get_parallel_seq());
+ print_summary(2, "Ext Root Scanning", body_summary->get_ext_root_scan_seq());
+ print_summary(2, "Mark Stack Scanning", body_summary->get_mark_stack_scan_seq());
print_summary(2, "Update RS", body_summary->get_update_rs_seq());
- print_summary(2, "Ext Root Scanning",
- body_summary->get_ext_root_scan_seq());
- print_summary(2, "Mark Stack Scanning",
- body_summary->get_mark_stack_scan_seq());
print_summary(2, "Scan RS", body_summary->get_scan_rs_seq());
print_summary(2, "Object Copy", body_summary->get_obj_copy_seq());
print_summary(2, "Termination", body_summary->get_termination_seq());
- print_summary(2, "Other", body_summary->get_parallel_other_seq());
+ print_summary(2, "Parallel Other", body_summary->get_parallel_other_seq());
{
NumberSeq* other_parts[] = {
- body_summary->get_update_rs_seq(),
body_summary->get_ext_root_scan_seq(),
body_summary->get_mark_stack_scan_seq(),
+ body_summary->get_update_rs_seq(),
body_summary->get_scan_rs_seq(),
body_summary->get_obj_copy_seq(),
body_summary->get_termination_seq()
@@ -2234,18 +2263,16 @@
check_other_times(2, body_summary->get_parallel_other_seq(),
&calc_other_times_ms);
}
- print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq());
- print_summary(1, "Clear CT", body_summary->get_clear_ct_seq());
} else {
+ print_summary(1, "Ext Root Scanning", body_summary->get_ext_root_scan_seq());
+ print_summary(1, "Mark Stack Scanning", body_summary->get_mark_stack_scan_seq());
print_summary(1, "Update RS", body_summary->get_update_rs_seq());
- print_summary(1, "Ext Root Scanning",
- body_summary->get_ext_root_scan_seq());
- print_summary(1, "Mark Stack Scanning",
- body_summary->get_mark_stack_scan_seq());
print_summary(1, "Scan RS", body_summary->get_scan_rs_seq());
print_summary(1, "Object Copy", body_summary->get_obj_copy_seq());
}
}
+ print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq());
+ print_summary(1, "Clear CT", body_summary->get_clear_ct_seq());
print_summary(1, "Other", summary->get_other_seq());
{
if (body_summary != NULL) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Sat Nov 05 00:00:43 2011 -0700
@@ -74,7 +74,7 @@
define_num_seq(termination) // parallel only
define_num_seq(parallel_other) // parallel only
define_num_seq(mark_closure)
- define_num_seq(clear_ct) // parallel only
+ define_num_seq(clear_ct)
};
class Summary: public PauseSummary,
@@ -115,7 +115,6 @@
double _cur_collection_par_time_ms;
double _cur_satb_drain_time_ms;
double _cur_clear_ct_time_ms;
- bool _satb_drain_time_set;
double _cur_ref_proc_time_ms;
double _cur_ref_enq_time_ms;
@@ -176,6 +175,11 @@
double* _par_last_gc_worker_end_times_ms;
double* _par_last_gc_worker_times_ms;
+ // Each workers 'other' time i.e. the elapsed time of the parallel
+ // phase of the pause minus the sum of the individual sub-phase
+ // times for a given worker thread.
+ double* _par_last_gc_worker_other_times_ms;
+
// indicates whether we are in full young or partially young GC mode
bool _full_young_gcs;
@@ -892,11 +896,12 @@
}
void record_satb_drain_time(double ms) {
+ assert(_g1->mark_in_progress(), "shouldn't be here otherwise");
_cur_satb_drain_time_ms = ms;
- _satb_drain_time_set = true;
}
- void record_satb_drain_processed_buffers (int processed_buffers) {
+ void record_satb_drain_processed_buffers(int processed_buffers) {
+ assert(_g1->mark_in_progress(), "shouldn't be here otherwise");
_last_satb_drain_processed_buffers = processed_buffers;
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -122,10 +122,10 @@
void set_try_claimed() { _try_claimed = true; }
void scanCard(size_t index, HeapRegion *r) {
- DirtyCardToOopClosure* cl =
- r->new_dcto_closure(_oc,
- CardTableModRefBS::Precise,
- HeapRegionDCTOC::IntoCSFilterKind);
+ // Stack allocate the DirtyCardToOopClosure instance
+ HeapRegionDCTOC cl(_g1h, r, _oc,
+ CardTableModRefBS::Precise,
+ HeapRegionDCTOC::IntoCSFilterKind);
// Set the "from" region in the closure.
_oc->set_region(r);
@@ -140,7 +140,7 @@
// scans (the rsets of the regions in the cset can intersect).
_ct_bs->set_card_claimed(index);
_cards_done++;
- cl->do_MemRegion(mr);
+ cl.do_MemRegion(mr);
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -340,14 +340,6 @@
init_top_at_mark_start();
}
-DirtyCardToOopClosure*
-HeapRegion::new_dcto_closure(OopClosure* cl,
- CardTableModRefBS::PrecisionStyle precision,
- HeapRegionDCTOC::FilterKind fk) {
- return new HeapRegionDCTOC(G1CollectedHeap::heap(),
- this, cl, precision, fk);
-}
-
void HeapRegion::hr_clear(bool par, bool clear_space) {
assert(_humongous_type == NotHumongous,
"we should have already filtered out humongous regions");
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Sat Nov 05 00:00:43 2011 -0700
@@ -431,6 +431,14 @@
return _humongous_start_region;
}
+ // Same as Space::is_in_reserved, but will use the original size of the region.
+ // The original size is different only for start humongous regions. They get
+ // their _end set up to be the end of the last continues region of the
+ // corresponding humongous object.
+ bool is_in_reserved_raw(const void* p) const {
+ return _bottom <= p && p < _orig_end;
+ }
+
// Makes the current region be a "starts humongous" region, i.e.,
// the first region in a series of one or more contiguous regions
// that will contain a single "humongous" object. The two parameters
@@ -569,11 +577,6 @@
// allocated in the current region before the last call to "save_mark".
void oop_before_save_marks_iterate(OopClosure* cl);
- DirtyCardToOopClosure*
- new_dcto_closure(OopClosure* cl,
- CardTableModRefBS::PrecisionStyle precision,
- HeapRegionDCTOC::FilterKind fk);
-
// Note the start or end of marking. This tells the heap region
// that the collector is about to start or has finished (concurrently)
// marking the heap.
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -143,7 +143,11 @@
// If the test below fails, then this table was reused concurrently
// with this operation. This is OK, since the old table was coarsened,
// and adding a bit to the new table is never incorrect.
- if (loc_hr->is_in_reserved(from)) {
+ // If the table used to belong to a continues humongous region and is
+ // now reused for the corresponding start humongous region, we need to
+ // make sure that we detect this. Thus, we call is_in_reserved_raw()
+ // instead of just is_in_reserved() here.
+ if (loc_hr->is_in_reserved_raw(from)) {
size_t hw_offset = pointer_delta((HeapWord*)from, loc_hr->bottom());
CardIdx_t from_card = (CardIdx_t)
hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize);
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/vm_operations_g1.hpp"
@@ -165,6 +166,20 @@
}
}
+void VM_CGC_Operation::acquire_pending_list_lock() {
+ // The caller may block while communicating
+ // with the SLT thread in order to acquire/release the PLL.
+ ConcurrentMarkThread::slt()->
+ manipulatePLL(SurrogateLockerThread::acquirePLL);
+}
+
+void VM_CGC_Operation::release_and_notify_pending_list_lock() {
+ // The caller may block while communicating
+ // with the SLT thread in order to acquire/release the PLL.
+ ConcurrentMarkThread::slt()->
+ manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
+}
+
void VM_CGC_Operation::doit() {
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
@@ -180,12 +195,19 @@
}
bool VM_CGC_Operation::doit_prologue() {
+ // Note the relative order of the locks must match that in
+ // VM_GC_Operation::doit_prologue() or deadlocks can occur
+ acquire_pending_list_lock();
+
Heap_lock->lock();
SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true;
return true;
}
void VM_CGC_Operation::doit_epilogue() {
+ // Note the relative order of the unlocks must match that in
+ // VM_GC_Operation::doit_epilogue()
SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false;
Heap_lock->unlock();
+ release_and_notify_pending_list_lock();
}
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Sat Nov 05 00:00:43 2011 -0700
@@ -93,11 +93,17 @@
}
};
-// Concurrent GC stop-the-world operations such as initial and final mark;
+// Concurrent GC stop-the-world operations such as remark and cleanup;
// consider sharing these with CMS's counterparts.
class VM_CGC_Operation: public VM_Operation {
VoidClosure* _cl;
const char* _printGCMessage;
+
+protected:
+ // java.lang.ref.Reference support
+ void acquire_pending_list_lock();
+ void release_and_notify_pending_list_lock();
+
public:
VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg)
: _cl(cl), _printGCMessage(printGCMsg) { }
--- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp Thu Nov 03 13:26:57 2011 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp Sat Nov 05 00:00:43 2011 -0700
@@ -224,6 +224,8 @@
MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
assert(_buffer == empty, "Should be empty");
assert(msg != empty, "empty message");
+ assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
+
_buffer = msg;
while (_buffer != empty) {
_monitor.notify();
--- a/jaxp/.hgtags Thu Nov 03 13:26:57 2011 -0700
+++ b/jaxp/.hgtags Sat Nov 05 00:00:43 2011 -0700
@@ -132,3 +132,4 @@
de4794dd69c48b08029d158a972993ff9d5627df jdk8-b08
93554324c014282571aeeb48552ad00d3fedb089 jdk8-b09
d21a4d5141c04bc9e88f2c0253121d449b66d667 jdk8-b10
+d1b7a4f6dd2065fdeafbcdfd9dcc0072da8c6881 jdk8-b11
--- a/jaxws/.hgtags Thu Nov 03 13:26:57 2011 -0700
+++ b/jaxws/.hgtags Sat Nov 05 00:00:43 2011 -0700
@@ -132,3 +132,4 @@
1c9d4f59acf8f71477473c170239b43b2c9dee24 jdk8-b08
70172e57cf29efe271b068987eefb601c2a77780 jdk8-b09
8e7fdc8e3c758644ca6d0fd70bb255e9d2e64cda jdk8-b10
+a12ab897a249feb7859a6e6cd84b49411f4c06ac jdk8-b11
--- a/jdk/.hgtags Thu Nov 03 13:26:57 2011 -0700
+++ b/jdk/.hgtags Sat Nov 05 00:00:43 2011 -0700
@@ -132,3 +132,5 @@
1c023bcd0c5a01ac07bc7eea728aafbb0d8991e9 jdk8-b08
f1ec21b8142168ff40f3278d2f6b5fe4bd5f3b26 jdk8-b09
4788745572ef2bde34924ef34e7e4d55ba07e979 jdk8-b10
+7ab0d613cd1a271a9763ffb894dc1f0a5b95a7e4 jdk8-b11
+09fd2067f715e4505c44b01c301258a4e8f8964e jdk8-b12
--- a/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Thu Nov 03 13:26:57 2011 -0700
+++ b/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Sat Nov 05 00:00:43 2011 -0700
@@ -189,7 +189,7 @@
if (printServices == null) {
return new PrintService[0];
} else {
- return printServices;
+ return (PrintService[])printServices.clone();
}
}
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Thu Nov 03 13:26:57 2011 -0700
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Sat Nov 05 00:00:43 2011 -0700
@@ -486,7 +486,7 @@
int dataType = 0;
int scanStride = width;
- if (dcm.getPixelSize() == 24 || dcm.getPixelSize() == 32) {
+ if (dcm.getPixelSize() > 16) {
dataType = DataBuffer.TYPE_INT;
} else {
// 15, 16
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/DirectX/DrawBitmaskToSurfaceTest.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6997116
+ * @summary Test verifies that rendering of images with bitmap transparency
+ * to a D3D surface does not cause an ClassCastException.
+ *
+ * @run main/othervm -Dsun.java2d.d3d=True DrawBitmaskToSurfaceTest
+ */
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.IndexColorModel;
+import java.util.concurrent.CountDownLatch;
+import javax.swing.JFrame;
+
+public class DrawBitmaskToSurfaceTest extends JFrame {
+
+ private final Image src;
+ private static java.util.concurrent.CountDownLatch latch = null;
+ private static Throwable theError = null;
+
+ public DrawBitmaskToSurfaceTest() {
+ src = createTestImage();
+ }
+
+ private static Image createTestImage() {
+ byte[] r = new byte[]{(byte)0x00, (byte)0x80, (byte)0xff, (byte)0xff};
+ byte[] g = new byte[]{(byte)0x00, (byte)0x80, (byte)0xff, (byte)0x00};
+ byte[] b = new byte[]{(byte)0x00, (byte)0x80, (byte)0xff, (byte)0x00};
+
+ IndexColorModel icm = new IndexColorModel(2, 4, r, g, b, 3);
+
+ BufferedImage img = new BufferedImage(100, 100,
+ BufferedImage.TYPE_BYTE_INDEXED,
+ icm);
+ return img;
+ }
+
+ @Override
+ public void paint(final Graphics g) {
+ try {
+ System.err.println("paint frame....");
+ g.drawImage(src, 30, 30, this);
+ } catch (Throwable e) {
+ theError = e;
+ } finally {
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final JFrame frame = new DrawBitmaskToSurfaceTest();
+ frame.setBounds(10, 350, 200, 200);
+ frame.setVisible(true);
+
+ Thread.sleep(2000);
+
+ System.err.println("Change frame bounds...");
+ latch = new CountDownLatch(1);
+ frame.setBounds(10, 350, 90, 90);
+ frame.repaint();
+
+ try {
+ if (latch.getCount() > 0) {
+ latch.await();
+ }
+ } catch (InterruptedException e) {
+ }
+
+ frame.dispose();
+
+ if (theError != null) {
+ throw new RuntimeException("Test failed.", theError);
+ }
+
+ System.err.println("Test passed");
+ }
+}
--- a/langtools/.hgtags Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/.hgtags Sat Nov 05 00:00:43 2011 -0700
@@ -132,3 +132,4 @@
e8acc2d6c32f0c8321e642e1a86672a2e196a056 jdk8-b08
b7a7e47c8d3daf7822abf7c37e5179ccbbf53008 jdk8-b09
f6c783e18bdf4d46a0ab273868afebbf32600ff7 jdk8-b10
+4bf01f1c4e3464f378959d10f3983a0469181d94 jdk8-b11
--- a/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java Sat Nov 05 00:00:43 2011 -0700
@@ -42,7 +42,6 @@
import com.sun.tools.apt.comp.*;
import com.sun.tools.apt.util.Bark;
import com.sun.mirror.apt.AnnotationProcessorFactory;
-import com.sun.tools.javac.parser.DocCommentScanner;
/**
* <p><b>This is NOT part of any supported API.
--- a/langtools/src/share/classes/com/sun/tools/apt/main/Main.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/Main.java Sat Nov 05 00:00:43 2011 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
import com.sun.tools.apt.util.Bark;
import com.sun.mirror.apt.AnnotationProcessorFactory;
-import static com.sun.tools.javac.file.Paths.pathToURLs;
+import static com.sun.tools.javac.file.Locations.pathToURLs;
/** This class provides a commandline interface to the apt build-time
* tool.
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java Sat Nov 05 00:00:43 2011 -0700
@@ -258,7 +258,7 @@
ClassType norm = (ClassType) t.tsym.type;
if (norm == null) {
s = localize(locale, "compiler.misc.anonymous.class", (Object) null);
- } else if (norm.interfaces_field.nonEmpty()) {
+ } else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) {
s = localize(locale, "compiler.misc.anonymous.class",
visit(norm.interfaces_field.head, locale));
} else {
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Sat Nov 05 00:00:43 2011 -0700
@@ -278,7 +278,6 @@
boolean tPrimitive = t.isPrimitive();
boolean sPrimitive = s.isPrimitive();
if (tPrimitive == sPrimitive) {
- checkUnsafeVarargsConversion(t, s, warn);
return isSubtypeUnchecked(t, s, warn);
}
if (!allowBoxing) return false;
@@ -286,27 +285,6 @@
? isSubtype(boxedClass(t).type, s)
: isSubtype(unboxedType(t), s);
}
- //where
- private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
- if (t.tag != ARRAY || isReifiable(t)) return;
- ArrayType from = (ArrayType)t;
- boolean shouldWarn = false;
- switch (s.tag) {
- case ARRAY:
- ArrayType to = (ArrayType)s;
- shouldWarn = from.isVarargs() &&
- !to.isVarargs() &&
- !isReifiable(from);
- break;
- case CLASS:
- shouldWarn = from.isVarargs() &&
- isSubtype(from, s);
- break;
- }
- if (shouldWarn) {
- warn.warn(LintCategory.VARARGS);
- }
- }
/**
* Is t a subtype of or convertiable via boxing/unboxing
@@ -328,42 +306,63 @@
* Is t an unchecked subtype of s?
*/
public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) {
- if (t.tag == ARRAY && s.tag == ARRAY) {
- if (((ArrayType)t).elemtype.tag <= lastBaseTag) {
- return isSameType(elemtype(t), elemtype(s));
- } else {
- ArrayType from = (ArrayType)t;
- ArrayType to = (ArrayType)s;
- if (from.isVarargs() &&
- !to.isVarargs() &&
- !isReifiable(from)) {
- warn.warn(LintCategory.VARARGS);
- }
- return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
- }
- } else if (isSubtype(t, s)) {
- return true;
+ boolean result = isSubtypeUncheckedInternal(t, s, warn);
+ if (result) {
+ checkUnsafeVarargsConversion(t, s, warn);
}
- else if (t.tag == TYPEVAR) {
- return isSubtypeUnchecked(t.getUpperBound(), s, warn);
- }
- else if (s.tag == UNDETVAR) {
- UndetVar uv = (UndetVar)s;
- if (uv.inst != null)
- return isSubtypeUnchecked(t, uv.inst, warn);
- }
- else if (!s.isRaw()) {
- Type t2 = asSuper(t, s.tsym);
- if (t2 != null && t2.isRaw()) {
- if (isReifiable(s))
- warn.silentWarn(LintCategory.UNCHECKED);
- else
- warn.warn(LintCategory.UNCHECKED);
+ return result;
+ }
+ //where
+ private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) {
+ if (t.tag == ARRAY && s.tag == ARRAY) {
+ if (((ArrayType)t).elemtype.tag <= lastBaseTag) {
+ return isSameType(elemtype(t), elemtype(s));
+ } else {
+ return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
+ }
+ } else if (isSubtype(t, s)) {
return true;
}
+ else if (t.tag == TYPEVAR) {
+ return isSubtypeUnchecked(t.getUpperBound(), s, warn);
+ }
+ else if (s.tag == UNDETVAR) {
+ UndetVar uv = (UndetVar)s;
+ if (uv.inst != null)
+ return isSubtypeUnchecked(t, uv.inst, warn);
+ }
+ else if (!s.isRaw()) {
+ Type t2 = asSuper(t, s.tsym);
+ if (t2 != null && t2.isRaw()) {
+ if (isReifiable(s))
+ warn.silentWarn(LintCategory.UNCHECKED);
+ else
+ warn.warn(LintCategory.UNCHECKED);
+ return true;
+ }
+ }
+ return false;
}
- return false;
- }
+
+ private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
+ if (t.tag != ARRAY || isReifiable(t)) return;
+ ArrayType from = (ArrayType)t;
+ boolean shouldWarn = false;
+ switch (s.tag) {
+ case ARRAY:
+ ArrayType to = (ArrayType)s;
+ shouldWarn = from.isVarargs() &&
+ !to.isVarargs() &&
+ !isReifiable(from);
+ break;
+ case CLASS:
+ shouldWarn = from.isVarargs();
+ break;
+ }
+ if (shouldWarn) {
+ warn.warn(LintCategory.VARARGS);
+ }
+ }
/**
* Is t a subtype of s?<br>
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Sat Nov 05 00:00:43 2011 -0700
@@ -34,7 +34,8 @@
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Type.ForAll.ConstraintKind;
import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import static com.sun.tools.javac.code.TypeTags.*;
@@ -56,6 +57,7 @@
Types types;
Check chk;
Resolve rs;
+ Log log;
JCDiagnostic.Factory diags;
public static Infer instance(Context context) {
@@ -70,6 +72,7 @@
syms = Symtab.instance(context);
types = Types.instance(context);
rs = Resolve.instance(context);
+ log = Log.instance(context);
chk = Check.instance(context);
diags = JCDiagnostic.Factory.instance(context);
ambiguousNoInstanceException =
@@ -460,7 +463,7 @@
// quantify result type with them
final List<Type> inferredTypes = insttypes.toList();
final List<Type> all_tvars = tvars; //this is the wrong tvars
- return new UninferredMethodType(mt, restvars.toList()) {
+ return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) {
@Override
List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
for (Type t : restundet.toList()) {
@@ -502,13 +505,17 @@
* type - when the return type is instantiated (see Infer.instantiateExpr)
* the underlying method type is also updated.
*/
- static abstract class UninferredMethodType extends DelegatedType {
+ abstract class UninferredMethodType extends DelegatedType {
final List<Type> tvars;
+ final Symbol msym;
+ final DiagnosticPosition pos;
- public UninferredMethodType(MethodType mtype, List<Type> tvars) {
+ public UninferredMethodType(DiagnosticPosition pos, Symbol msym, MethodType mtype, List<Type> tvars) {
super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym));
this.tvars = tvars;
+ this.msym = msym;
+ this.pos = pos;
asMethodType().restype = new UninferredReturnType(tvars, mtype.restype);
}
@@ -543,6 +550,9 @@
public Type inst(List<Type> actuals, Types types) {
Type newRestype = super.inst(actuals, types);
instantiateReturnType(newRestype, actuals, types);
+ if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
+ log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype);
+ }
return newRestype;
}
@Override
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Sat Nov 05 00:00:43 2011 -0700
@@ -25,29 +25,33 @@
package com.sun.tools.javac.comp;
-import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.api.Formattable.LocalizedString;
import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.api.Formattable.LocalizedString;
-import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
-import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.tree.JCTree.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.ElementVisitor;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.TypeTags.*;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
-import javax.lang.model.element.ElementVisitor;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.HashMap;
-import java.util.HashSet;
+import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
/** Helper class for name resolution, used mostly by the attribution phase.
*
@@ -73,9 +77,45 @@
public final boolean varargsEnabled; // = source.allowVarargs();
public final boolean allowMethodHandles;
private final boolean debugResolve;
+ final EnumSet<VerboseResolutionMode> verboseResolutionMode;
Scope polymorphicSignatureScope;
+ enum VerboseResolutionMode {
+ SUCCESS("success"),
+ FAILURE("failure"),
+ APPLICABLE("applicable"),
+ INAPPLICABLE("inapplicable"),
+ DEFERRED_INST("deferred-inference"),
+ PREDEF("predef"),
+ OBJECT_INIT("object-init"),
+ INTERNAL("internal");
+
+ String opt;
+
+ private VerboseResolutionMode(String opt) {
+ this.opt = opt;
+ }
+
+ static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) {
+ String s = opts.get("verboseResolution");
+ EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class);
+ if (s == null) return res;
+ if (s.contains("all")) {
+ res = EnumSet.allOf(VerboseResolutionMode.class);
+ }
+ Collection<String> args = Arrays.asList(s.split(","));
+ for (VerboseResolutionMode mode : values()) {
+ if (args.contains(mode.opt)) {
+ res.add(mode);
+ } else if (args.contains("-" + mode.opt)) {
+ res.remove(mode);
+ }
+ }
+ return res;
+ }
+ }
+
public static Resolve instance(Context context) {
Resolve instance = context.get(resolveKey);
if (instance == null)
@@ -111,6 +151,7 @@
varargsEnabled = source.allowVarargs();
Options options = Options.instance(context);
debugResolve = options.isSet("debugresolve");
+ verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
Target target = Target.instance(context);
allowMethodHandles = target.hasMethodHandles();
polymorphicSignatureScope = new Scope(syms.noSymbol);
@@ -684,13 +725,16 @@
if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
Assert.check(sym.kind < AMBIGUOUS);
try {
- rawInstantiate(env, site, sym, argtypes, typeargtypes,
+ Type mt = rawInstantiate(env, site, sym, argtypes, typeargtypes,
allowBoxing, useVarargs, Warner.noWarnings);
+ if (!operator) addVerboseApplicableCandidateDiag(sym ,mt);
} catch (InapplicableMethodException ex) {
+ if (!operator) addVerboseInapplicableCandidateDiag(sym, ex.getDiagnostic());
switch (bestSoFar.kind) {
case ABSENT_MTH:
return wrongMethod.setWrongSym(sym, ex.getDiagnostic());
case WRONG_MTH:
+ if (operator) return bestSoFar;
wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation);
case WRONG_MTHS:
return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic());
@@ -708,6 +752,34 @@
: mostSpecific(sym, bestSoFar, env, site,
allowBoxing && operator, useVarargs);
}
+ //where
+ void addVerboseApplicableCandidateDiag(Symbol sym, Type inst) {
+ if (!verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE))
+ return;
+
+ JCDiagnostic subDiag = null;
+ if (inst.getReturnType().tag == FORALL) {
+ Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(),
+ ((ForAll)inst.getReturnType()).qtype);
+ subDiag = diags.fragment("partial.inst.sig", diagType);
+ } else if (sym.type.tag == FORALL) {
+ subDiag = diags.fragment("full.inst.sig", inst.asMethodType());
+ }
+
+ String key = subDiag == null ?
+ "applicable.method.found" :
+ "applicable.method.found.1";
+
+ verboseResolutionCandidateDiags.put(sym,
+ diags.fragment(key, verboseResolutionCandidateDiags.size(), sym, subDiag));
+ }
+
+ void addVerboseInapplicableCandidateDiag(Symbol sym, JCDiagnostic subDiag) {
+ if (!verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))
+ return;
+ verboseResolutionCandidateDiags.put(sym,
+ diags.fragment("not.applicable.method.found", verboseResolutionCandidateDiags.size(), sym, subDiag));
+ }
/* Return the most specific of the two methods for a call,
* given that both are accessible and applicable.
@@ -905,8 +977,9 @@
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
+ verboseResolutionCandidateDiags.clear();
Symbol bestSoFar = methodNotFound;
- return findMethod(env,
+ bestSoFar = findMethod(env,
site,
name,
argtypes,
@@ -918,6 +991,8 @@
useVarargs,
operator,
new HashSet<TypeSymbol>());
+ reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar);
+ return bestSoFar;
}
// where
private Symbol findMethod(Env<AttrContext> env,
@@ -975,6 +1050,37 @@
}
return bestSoFar;
}
+ //where
+ void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) {
+ boolean success = bestSoFar.kind < ERRONEOUS;
+
+ if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) {
+ return;
+ } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) {
+ return;
+ }
+
+ if (bestSoFar.name == names.init &&
+ bestSoFar.owner == syms.objectType.tsym &&
+ !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) {
+ return; //skip diags for Object constructor resolution
+ } else if (site == syms.predefClass.type && !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) {
+ return; //skip spurious diags for predef symbols (i.e. operators)
+ } else if (internalResolution && !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) {
+ return;
+ }
+
+ int pos = 0;
+ for (Symbol s : verboseResolutionCandidateDiags.keySet()) {
+ if (s == bestSoFar) break;
+ pos++;
+ }
+ String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
+ JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, pos, currentStep,
+ methodArguments(argtypes), methodArguments(typeargtypes));
+ JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, List.from(verboseResolutionCandidateDiags.values().toArray(new JCDiagnostic[verboseResolutionCandidateDiags.size()])));
+ log.report(d);
+ }
/** Find unqualified method matching given name, type and value arguments.
* @param env The current environment.
@@ -1543,12 +1649,19 @@
Type site, Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
- Symbol sym = resolveQualifiedMethod(
- pos, env, site.tsym, site, name, argtypes, typeargtypes);
- if (sym.kind == MTH) return (MethodSymbol)sym;
- else throw new FatalError(
- diags.fragment("fatal.err.cant.locate.meth",
- name));
+ boolean prevInternal = internalResolution;
+ try {
+ internalResolution = true;
+ Symbol sym = resolveQualifiedMethod(
+ pos, env, site.tsym, site, name, argtypes, typeargtypes);
+ if (sym.kind == MTH) return (MethodSymbol)sym;
+ else throw new FatalError(
+ diags.fragment("fatal.err.cant.locate.meth",
+ name));
+ }
+ finally {
+ internalResolution = prevInternal;
+ }
}
/** Resolve constructor.
@@ -1685,6 +1798,7 @@
*/
Symbol resolveOperator(DiagnosticPosition pos, int optag,
Env<AttrContext> env, List<Type> argtypes) {
+ startResolution();
Name name = treeinfo.operatorName(optag);
Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
null, false, false, true);
@@ -1828,7 +1942,7 @@
private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args");
public Object methodArguments(List<Type> argtypes) {
- return argtypes.isEmpty() ? noArgs : argtypes;
+ return argtypes == null || argtypes.isEmpty() ? noArgs : argtypes;
}
/**
@@ -2375,10 +2489,15 @@
private Map<MethodResolutionPhase, Symbol> methodResolutionCache =
new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length);
+ private Map<Symbol, JCDiagnostic> verboseResolutionCandidateDiags =
+ new LinkedHashMap<Symbol, JCDiagnostic>();
+
final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
private MethodResolutionPhase currentStep = null;
+ private boolean internalResolution = false;
+
private MethodResolutionPhase firstErroneousResolutionPhase() {
MethodResolutionPhase bestSoFar = BASIC;
Symbol sym = methodNotFound;
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Sat Nov 05 00:00:43 2011 -0700
@@ -25,7 +25,6 @@
package com.sun.tools.javac.file;
-import java.util.Comparator;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
@@ -41,6 +40,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
@@ -56,14 +56,12 @@
import com.sun.tools.javac.file.RelativePath.RelativeFile;
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.main.OptionName;
import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import static javax.tools.StandardLocation.*;
-import static com.sun.tools.javac.main.OptionName.*;
/**
* This class provides access to the source, class and other files
@@ -83,32 +81,14 @@
return buffer.toString().toCharArray();
}
- /** Encapsulates knowledge of paths
- */
- private Paths paths;
-
private FSInfo fsInfo;
private boolean contextUseOptimizedZip;
private ZipFileIndexCache zipFileIndexCache;
- private final File uninited = new File("U N I N I T E D");
-
private final Set<JavaFileObject.Kind> sourceOrClass =
EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
- /** The standard output directory, primarily used for classes.
- * Initialized by the "-d" option.
- * If classOutDir = null, files are written into same directory as the sources
- * they were generated from.
- */
- private File classOutDir = uninited;
-
- /** The output directory, used when generating sources while processing annotations.
- * Initialized by the "-s" option.
- */
- private File sourceOutDir = uninited;
-
protected boolean mmappedIO;
protected boolean ignoreSymbolFile;
@@ -154,13 +134,6 @@
@Override
public void setContext(Context context) {
super.setContext(context);
- if (paths == null) {
- paths = Paths.instance(context);
- } else {
- // Reuse the Paths object as it stores the locations that
- // have been set with setLocation, etc.
- paths.setContext(context);
- }
fsInfo = FSInfo.instance(context);
@@ -179,7 +152,7 @@
@Override
public boolean isDefaultBootClassPath() {
- return paths.isDefaultBootClassPath();
+ return locations.isDefaultBootClassPath();
}
public JavaFileObject getFileForInput(String name) {
@@ -493,7 +466,7 @@
*/
private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException {
File origZipFileName = zipFileName;
- if (!ignoreSymbolFile && paths.isDefaultBootClassPathRtJar(zipFileName)) {
+ if (!ignoreSymbolFile && locations.isDefaultBootClassPathRtJar(zipFileName)) {
File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
if (new File(file.getName()).equals(new File("jre")))
file = file.getParentFile();
@@ -780,7 +753,7 @@
} else if (location == SOURCE_OUTPUT) {
dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
} else {
- Iterable<? extends File> path = paths.getPathForLocation(location);
+ Iterable<? extends File> path = locations.getLocation(location);
dir = null;
for (File f: path) {
dir = f;
@@ -815,64 +788,20 @@
throws IOException
{
nullCheck(location);
- paths.lazy();
-
- final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
-
- if (location == CLASS_OUTPUT)
- classOutDir = getOutputLocation(dir, D);
- else if (location == SOURCE_OUTPUT)
- sourceOutDir = getOutputLocation(dir, S);
- else
- paths.setPathForLocation(location, path);
- }
- // where
- private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
- if (path == null)
- return null;
- Iterator<? extends File> pathIter = path.iterator();
- if (!pathIter.hasNext())
- throw new IllegalArgumentException("empty path for directory");
- File dir = pathIter.next();
- if (pathIter.hasNext())
- throw new IllegalArgumentException("path too long for directory");
- if (!dir.exists())
- throw new FileNotFoundException(dir + ": does not exist");
- else if (!dir.isDirectory())
- throw new IOException(dir + ": not a directory");
- return dir;
- }
-
- private File getOutputLocation(File dir, OptionName defaultOptionName) {
- if (dir != null)
- return dir;
- String arg = options.get(defaultOptionName);
- if (arg == null)
- return null;
- return new File(arg);
+ locations.setLocation(location, path);
}
public Iterable<? extends File> getLocation(Location location) {
nullCheck(location);
- paths.lazy();
- if (location == CLASS_OUTPUT) {
- return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
- } else if (location == SOURCE_OUTPUT) {
- return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
- } else
- return paths.getPathForLocation(location);
+ return locations.getLocation(location);
}
private File getClassOutDir() {
- if (classOutDir == uninited)
- classOutDir = getOutputLocation(null, D);
- return classOutDir;
+ return locations.getOutputLocation(CLASS_OUTPUT);
}
private File getSourceOutDir() {
- if (sourceOutDir == uninited)
- sourceOutDir = getOutputLocation(null, S);
- return sourceOutDir;
+ return locations.getOutputLocation(SOURCE_OUTPUT);
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.FileNotFoundException;
+import java.util.Iterator;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.zip.ZipFile;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import javax.tools.JavaFileManager;
+import static javax.tools.StandardLocation.*;
+import static com.sun.tools.javac.main.OptionName.*;
+
+/** This class converts command line arguments, environment variables
+ * and system properties (in File.pathSeparator-separated String form)
+ * into a boot class path, user class path, and source path (in
+ * Collection<String> form).
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class Locations {
+
+ /** The log to use for warning output */
+ private Log log;
+
+ /** Collection of command-line options */
+ private Options options;
+
+ /** Handler for -Xlint options */
+ private Lint lint;
+
+ /** Access to (possibly cached) file info */
+ private FSInfo fsInfo;
+
+ /** Whether to warn about non-existent path elements */
+ private boolean warn;
+
+ // TODO: remove need for this
+ private boolean inited = false; // TODO? caching bad?
+
+ public Locations() {
+ initHandlers();
+ }
+
+ public void update(Log log, Options options, Lint lint, FSInfo fsInfo) {
+ this.log = log;
+ this.options = options;
+ this.lint = lint;
+ this.fsInfo = fsInfo;
+ }
+
+ public Collection<File> bootClassPath() {
+ return getLocation(PLATFORM_CLASS_PATH);
+ }
+
+ public boolean isDefaultBootClassPath() {
+ BootClassPathLocationHandler h =
+ (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
+ return h.isDefault();
+ }
+
+ boolean isDefaultBootClassPathRtJar(File file) {
+ BootClassPathLocationHandler h =
+ (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
+ return h.isDefaultRtJar(file);
+ }
+
+ public Collection<File> userClassPath() {
+ return getLocation(CLASS_PATH);
+ }
+
+ public Collection<File> sourcePath() {
+ Collection<File> p = getLocation(SOURCE_PATH);
+ // TODO: this should be handled by the LocationHandler
+ return p == null || p.isEmpty() ? null : p;
+ }
+
+ /**
+ * Split a path into its elements. Empty path elements will be ignored.
+ * @param path The path to be split
+ * @return The elements of the path
+ */
+ private static Iterable<File> getPathEntries(String path) {
+ return getPathEntries(path, null);
+ }
+
+ /**
+ * Split a path into its elements. If emptyPathDefault is not null, all
+ * empty elements in the path, including empty elements at either end of
+ * the path, will be replaced with the value of emptyPathDefault.
+ * @param path The path to be split
+ * @param emptyPathDefault The value to substitute for empty path elements,
+ * or null, to ignore empty path elements
+ * @return The elements of the path
+ */
+ private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
+ ListBuffer<File> entries = new ListBuffer<File>();
+ int start = 0;
+ while (start <= path.length()) {
+ int sep = path.indexOf(File.pathSeparatorChar, start);
+ if (sep == -1)
+ sep = path.length();
+ if (start < sep)
+ entries.add(new File(path.substring(start, sep)));
+ else if (emptyPathDefault != null)
+ entries.add(emptyPathDefault);
+ start = sep + 1;
+ }
+ return entries;
+ }
+
+ /**
+ * Utility class to help evaluate a path option.
+ * Duplicate entries are ignored, jar class paths can be expanded.
+ */
+ private class Path extends LinkedHashSet<File> {
+ private static final long serialVersionUID = 0;
+
+ private boolean expandJarClassPaths = false;
+ private Set<File> canonicalValues = new HashSet<File>();
+
+ public Path expandJarClassPaths(boolean x) {
+ expandJarClassPaths = x;
+ return this;
+ }
+
+ /** What to use when path element is the empty string */
+ private File emptyPathDefault = null;
+
+ public Path emptyPathDefault(File x) {
+ emptyPathDefault = x;
+ return this;
+ }
+
+ public Path() { super(); }
+
+ public Path addDirectories(String dirs, boolean warn) {
+ boolean prev = expandJarClassPaths;
+ expandJarClassPaths = true;
+ try {
+ if (dirs != null)
+ for (File dir : getPathEntries(dirs))
+ addDirectory(dir, warn);
+ return this;
+ } finally {
+ expandJarClassPaths = prev;
+ }
+ }
+
+ public Path addDirectories(String dirs) {
+ return addDirectories(dirs, warn);
+ }
+
+ private void addDirectory(File dir, boolean warn) {
+ if (!dir.isDirectory()) {
+ if (warn)
+ log.warning(Lint.LintCategory.PATH,
+ "dir.path.element.not.found", dir);
+ return;
+ }
+
+ File[] files = dir.listFiles();
+ if (files == null)
+ return;
+
+ for (File direntry : files) {
+ if (isArchive(direntry))
+ addFile(direntry, warn);
+ }
+ }
+
+ public Path addFiles(String files, boolean warn) {
+ if (files != null) {
+ addFiles(getPathEntries(files, emptyPathDefault), warn);
+ }
+ return this;
+ }
+
+ public Path addFiles(String files) {
+ return addFiles(files, warn);
+ }
+
+ public Path addFiles(Iterable<? extends File> files, boolean warn) {
+ if (files != null) {
+ for (File file: files)
+ addFile(file, warn);
+ }
+ return this;
+ }
+
+ public Path addFiles(Iterable<? extends File> files) {
+ return addFiles(files, warn);
+ }
+
+ public void addFile(File file, boolean warn) {
+ if (contains(file)) {
+ // discard duplicates
+ return;
+ }
+
+ if (! fsInfo.exists(file)) {
+ /* No such file or directory exists */
+ if (warn) {
+ log.warning(Lint.LintCategory.PATH,
+ "path.element.not.found", file);
+ }
+ super.add(file);
+ return;
+ }
+
+ File canonFile = fsInfo.getCanonicalFile(file);
+ if (canonicalValues.contains(canonFile)) {
+ /* Discard duplicates and avoid infinite recursion */
+ return;
+ }
+
+ if (fsInfo.isFile(file)) {
+ /* File is an ordinary file. */
+ if (!isArchive(file)) {
+ /* Not a recognized extension; open it to see if
+ it looks like a valid zip file. */
+ try {
+ ZipFile z = new ZipFile(file);
+ z.close();
+ if (warn) {
+ log.warning(Lint.LintCategory.PATH,
+ "unexpected.archive.file", file);
+ }
+ } catch (IOException e) {
+ // FIXME: include e.getLocalizedMessage in warning
+ if (warn) {
+ log.warning(Lint.LintCategory.PATH,
+ "invalid.archive.file", file);
+ }
+ return;
+ }
+ }
+ }
+
+ /* Now what we have left is either a directory or a file name
+ conforming to archive naming convention */
+ super.add(file);
+ canonicalValues.add(canonFile);
+
+ if (expandJarClassPaths && fsInfo.isFile(file))
+ addJarClassPath(file, warn);
+ }
+
+ // Adds referenced classpath elements from a jar's Class-Path
+ // Manifest entry. In some future release, we may want to
+ // update this code to recognize URLs rather than simple
+ // filenames, but if we do, we should redo all path-related code.
+ private void addJarClassPath(File jarFile, boolean warn) {
+ try {
+ for (File f: fsInfo.getJarClassPath(jarFile)) {
+ addFile(f, warn);
+ }
+ } catch (IOException e) {
+ log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e));
+ }
+ }
+ }
+
+ /**
+ * Base class for handling support for the representation of Locations.
+ * Implementations are responsible for handling the interactions between
+ * the command line options for a location, and API access via setLocation.
+ * @see #initHandlers
+ * @see #getHandler
+ */
+ protected abstract class LocationHandler {
+ final Location location;
+ final Set<OptionName> options;
+
+ /**
+ * Create a handler. The location and options provide a way to map
+ * from a location or an option to the corresponding handler.
+ * @see #initHandlers
+ */
+ protected LocationHandler(Location location, OptionName... options) {
+ this.location = location;
+ this.options = options.length == 0 ?
+ EnumSet.noneOf(OptionName.class):
+ EnumSet.copyOf(Arrays.asList(options));
+ }
+
+ // TODO: TEMPORARY, while Options still used for command line options
+ void update(Options optionTable) {
+ for (OptionName o: options) {
+ String v = optionTable.get(o);
+ if (v != null) {
+ handleOption(o, v);
+ }
+ }
+ }
+
+ /** @see JavaFileManager#handleOption. */
+ abstract boolean handleOption(OptionName option, String value);
+ /** @see JavaFileManager#getLocation. */
+ abstract Collection<File> getLocation();
+ /** @see JavaFileManager#setLocation. */
+ abstract void setLocation(Iterable<? extends File> files) throws IOException;
+ }
+
+ /**
+ * General purpose implementation for output locations,
+ * such as -d/CLASS_OUTPUT and -s/SOURCE_OUTPUT.
+ * All options are treated as equivalent (i.e. aliases.)
+ * The value is a single file, possibly null.
+ */
+ private class OutputLocationHandler extends LocationHandler {
+ private File outputDir;
+
+ OutputLocationHandler(Location location, OptionName... options) {
+ super(location, options);
+ }
+
+ @Override
+ boolean handleOption(OptionName option, String value) {
+ if (!options.contains(option))
+ return false;
+
+ // TODO: could/should validate outputDir exists and is a directory
+ // need to decide how best to report issue for benefit of
+ // direct API call on JavaFileManager.handleOption(specifies IAE)
+ // vs. command line decoding.
+ outputDir = new File(value);
+ return true;
+ }
+
+ @Override
+ Collection<File> getLocation() {
+ return (outputDir == null) ? null : Collections.singleton(outputDir);
+ }
+
+ @Override
+ void setLocation(Iterable<? extends File> files) throws IOException {
+ if (files == null) {
+ outputDir = null;
+ } else {
+ Iterator<? extends File> pathIter = files.iterator();
+ if (!pathIter.hasNext())
+ throw new IllegalArgumentException("empty path for directory");
+ File dir = pathIter.next();
+ if (pathIter.hasNext())
+ throw new IllegalArgumentException("path too long for directory");
+ if (!dir.exists())
+ throw new FileNotFoundException(dir + ": does not exist");
+ else if (!dir.isDirectory())
+ throw new IOException(dir + ": not a directory");
+ outputDir = dir;
+ }
+ }
+ }
+
+ /**
+ * General purpose implementation for search path locations,
+ * such as -sourcepath/SOURCE_PATH and -processorPath/ANNOTATION_PROCESS_PATH.
+ * All options are treated as equivalent (i.e. aliases.)
+ * The value is an ordered set of files and/or directories.
+ */
+ private class SimpleLocationHandler extends LocationHandler {
+ protected Collection<File> searchPath;
+
+ SimpleLocationHandler(Location location, OptionName... options) {
+ super(location, options);
+ }
+
+ @Override
+ boolean handleOption(OptionName option, String value) {
+ if (!options.contains(option))
+ return false;
+ searchPath = value == null ? null :
+ Collections.unmodifiableCollection(computePath(value));
+ return true;
+ }
+
+ protected Path computePath(String value) {
+ return new Path().addFiles(value);
+ }
+
+ @Override
+ Collection<File> getLocation() {
+ return searchPath;
+ }
+
+ @Override
+ void setLocation(Iterable<? extends File> files) {
+ Path p;
+ if (files == null) {
+ p = computePath(null);
+ } else {
+ p = new Path().addFiles(files);
+ }
+ searchPath = Collections.unmodifiableCollection(p);
+ }
+ }
+
+ /**
+ * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
+ * If no value is given, a default is provided, based on system properties
+ * and other values.
+ */
+ private class ClassPathLocationHandler extends SimpleLocationHandler {
+ ClassPathLocationHandler() {
+ super(StandardLocation.CLASS_PATH,
+ OptionName.CLASSPATH, OptionName.CP);
+ }
+
+ @Override
+ Collection<File> getLocation() {
+ lazy();
+ return searchPath;
+ }
+
+ @Override
+ protected Path computePath(String value) {
+ String cp = value;
+
+ // CLASSPATH environment variable when run from `javac'.
+ if (cp == null) cp = System.getProperty("env.class.path");
+
+ // If invoked via a java VM (not the javac launcher), use the
+ // platform class path
+ if (cp == null && System.getProperty("application.home") == null)
+ cp = System.getProperty("java.class.path");
+
+ // Default to current working directory.
+ if (cp == null) cp = ".";
+
+ return new Path()
+ .expandJarClassPaths(true) // Only search user jars for Class-Paths
+ .emptyPathDefault(new File(".")) // Empty path elt ==> current directory
+ .addFiles(cp);
+ }
+
+ private void lazy() {
+ if (searchPath == null)
+ setLocation(null);
+ }
+ }
+
+ /**
+ * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH.
+ * Various options are supported for different components of the
+ * platform class path.
+ * Setting a value with setLocation overrides all existing option values.
+ * Setting any option overrides any value set with setLocation, and reverts
+ * to using default values for options that have not been set.
+ * Setting -bootclasspath or -Xbootclasspath overrides any existing
+ * value for -Xbootclasspath/p: and -Xbootclasspath/a:.
+ */
+ private class BootClassPathLocationHandler extends LocationHandler {
+ private Collection<File> searchPath;
+ final Map<OptionName, String> optionValues = new EnumMap<OptionName,String>(OptionName.class);
+
+ /**
+ * rt.jar as found on the default bootclasspath.
+ * If the user specified a bootclasspath, null is used.
+ */
+ private File defaultBootClassPathRtJar = null;
+
+ /**
+ * Is bootclasspath the default?
+ */
+ private boolean isDefaultBootClassPath;
+
+ BootClassPathLocationHandler() {
+ super(StandardLocation.PLATFORM_CLASS_PATH,
+ OptionName.BOOTCLASSPATH, OptionName.XBOOTCLASSPATH,
+ OptionName.XBOOTCLASSPATH_PREPEND,
+ OptionName.XBOOTCLASSPATH_APPEND,
+ OptionName.ENDORSEDDIRS, OptionName.DJAVA_ENDORSED_DIRS,
+ OptionName.EXTDIRS, OptionName.DJAVA_EXT_DIRS);
+ }
+
+ boolean isDefault() {
+ lazy();
+ return isDefaultBootClassPath;
+ }
+
+ boolean isDefaultRtJar(File file) {
+ lazy();
+ return file.equals(defaultBootClassPathRtJar);
+ }
+
+ @Override
+ boolean handleOption(OptionName option, String value) {
+ if (!options.contains(option))
+ return false;
+
+ option = canonicalize(option);
+ optionValues.put(option, value);
+ if (option == BOOTCLASSPATH) {
+ optionValues.remove(XBOOTCLASSPATH_PREPEND);
+ optionValues.remove(XBOOTCLASSPATH_APPEND);
+ }
+ searchPath = null; // reset to "uninitialized"
+ return true;
+ }
+ // where
+ // TODO: would be better if option aliasing was handled at a higher
+ // level
+ private OptionName canonicalize(OptionName option) {
+ switch (option) {
+ case XBOOTCLASSPATH:
+ return OptionName.BOOTCLASSPATH;
+ case DJAVA_ENDORSED_DIRS:
+ return OptionName.ENDORSEDDIRS;
+ case DJAVA_EXT_DIRS:
+ return OptionName.EXTDIRS;
+ default:
+ return option;
+ }
+ }
+
+ @Override
+ Collection<File> getLocation() {
+ lazy();
+ return searchPath;
+ }
+
+ @Override
+ void setLocation(Iterable<? extends File> files) {
+ if (files == null) {
+ searchPath = null; // reset to "uninitialized"
+ } else {
+ defaultBootClassPathRtJar = null;
+ isDefaultBootClassPath = false;
+ Path p = new Path().addFiles(files, false);
+ searchPath = Collections.unmodifiableCollection(p);
+ optionValues.clear();
+ }
+ }
+
+ Path computePath() {
+ defaultBootClassPathRtJar = null;
+ Path path = new Path();
+
+ String bootclasspathOpt = optionValues.get(BOOTCLASSPATH);
+ String endorseddirsOpt = optionValues.get(ENDORSEDDIRS);
+ String extdirsOpt = optionValues.get(EXTDIRS);
+ String xbootclasspathPrependOpt = optionValues.get(XBOOTCLASSPATH_PREPEND);
+ String xbootclasspathAppendOpt = optionValues.get(XBOOTCLASSPATH_APPEND);
+
+ path.addFiles(xbootclasspathPrependOpt);
+
+ if (endorseddirsOpt != null)
+ path.addDirectories(endorseddirsOpt);
+ else
+ path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
+
+ if (bootclasspathOpt != null) {
+ path.addFiles(bootclasspathOpt);
+ } else {
+ // Standard system classes for this compiler's release.
+ String files = System.getProperty("sun.boot.class.path");
+ path.addFiles(files, false);
+ File rt_jar = new File("rt.jar");
+ for (File file : getPathEntries(files)) {
+ if (new File(file.getName()).equals(rt_jar))
+ defaultBootClassPathRtJar = file;
+ }
+ }
+
+ path.addFiles(xbootclasspathAppendOpt);
+
+ // Strictly speaking, standard extensions are not bootstrap
+ // classes, but we treat them identically, so we'll pretend
+ // that they are.
+ if (extdirsOpt != null)
+ path.addDirectories(extdirsOpt);
+ else
+ path.addDirectories(System.getProperty("java.ext.dirs"), false);
+
+ isDefaultBootClassPath =
+ (xbootclasspathPrependOpt == null) &&
+ (bootclasspathOpt == null) &&
+ (xbootclasspathAppendOpt == null);
+
+ return path;
+ }
+
+ private void lazy() {
+ if (searchPath == null)
+ searchPath = Collections.unmodifiableCollection(computePath());
+ }
+ }
+
+ Map<Location, LocationHandler> handlersForLocation;
+ Map<OptionName, LocationHandler> handlersForOption;
+
+ void initHandlers() {
+ handlersForLocation = new HashMap<Location, LocationHandler>();
+ handlersForOption = new EnumMap<OptionName, LocationHandler>(OptionName.class);
+
+ LocationHandler[] handlers = {
+ new BootClassPathLocationHandler(),
+ new ClassPathLocationHandler(),
+ new SimpleLocationHandler(StandardLocation.SOURCE_PATH, OptionName.SOURCEPATH),
+ new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, OptionName.PROCESSORPATH),
+ new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), OptionName.D),
+ new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), OptionName.S)
+ };
+
+ for (LocationHandler h: handlers) {
+ handlersForLocation.put(h.location, h);
+ for (OptionName o: h.options)
+ handlersForOption.put(o, h);
+ }
+ }
+
+ boolean handleOption(OptionName option, String value) {
+ LocationHandler h = handlersForOption.get(option);
+ return (h == null ? false : h.handleOption(option, value));
+ }
+
+ Collection<File> getLocation(Location location) {
+ LocationHandler h = getHandler(location);
+ return (h == null ? null : h.getLocation());
+ }
+
+ File getOutputLocation(Location location) {
+ if (!location.isOutputLocation())
+ throw new IllegalArgumentException();
+ LocationHandler h = getHandler(location);
+ return ((OutputLocationHandler) h).outputDir;
+ }
+
+ void setLocation(Location location, Iterable<? extends File> files) throws IOException {
+ LocationHandler h = getHandler(location);
+ if (h == null) {
+ if (location.isOutputLocation())
+ h = new OutputLocationHandler(location);
+ else
+ h = new SimpleLocationHandler(location);
+ handlersForLocation.put(location, h);
+ }
+ h.setLocation(files);
+ }
+
+ protected LocationHandler getHandler(Location location) {
+ location.getClass(); // null check
+ lazy();
+ return handlersForLocation.get(location);
+ }
+
+// TOGO
+ protected void lazy() {
+ if (!inited) {
+ warn = lint.isEnabled(Lint.LintCategory.PATH);
+
+ for (LocationHandler h: handlersForLocation.values()) {
+ h.update(options);
+ }
+
+ inited = true;
+ }
+ }
+
+ /** Is this the name of an archive file? */
+ private boolean isArchive(File file) {
+ String n = file.getName().toLowerCase();
+ return fsInfo.isFile(file)
+ && (n.endsWith(".jar") || n.endsWith(".zip"));
+ }
+
+ /**
+ * Utility method for converting a search path string to an array
+ * of directory and JAR file URLs.
+ *
+ * Note that this method is called by apt and the DocletInvoker.
+ *
+ * @param path the search path string
+ * @return the resulting array of directory and JAR file URLs
+ */
+ public static URL[] pathToURLs(String path) {
+ StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+ URL[] urls = new URL[st.countTokens()];
+ int count = 0;
+ while (st.hasMoreTokens()) {
+ URL url = fileToURL(new File(st.nextToken()));
+ if (url != null) {
+ urls[count++] = url;
+ }
+ }
+ if (urls.length != count) {
+ URL[] tmp = new URL[count];
+ System.arraycopy(urls, 0, tmp, 0, count);
+ urls = tmp;
+ }
+ return urls;
+ }
+
+ /**
+ * Returns the directory or JAR file URL corresponding to the specified
+ * local file name.
+ *
+ * @param file the File object
+ * @return the resulting directory or JAR file URL, or null if unknown
+ */
+ private static URL fileToURL(File file) {
+ String name;
+ try {
+ name = file.getCanonicalPath();
+ } catch (IOException e) {
+ name = file.getAbsolutePath();
+ }
+ name = name.replace(File.separatorChar, '/');
+ if (!name.startsWith("/")) {
+ name = "/" + name;
+ }
+ // If the file does not exist, then assume that it's a directory
+ if (!file.isFile()) {
+ name = name + "/";
+ }
+ try {
+ return new URL("file", "", name);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(file.toString());
+ }
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Thu Nov 03 13:26:57 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,558 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.file;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.StringTokenizer;
-import java.util.zip.ZipFile;
-import javax.tools.JavaFileManager.Location;
-
-import com.sun.tools.javac.code.Lint;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Options;
-
-import static javax.tools.StandardLocation.*;
-import static com.sun.tools.javac.main.OptionName.*;
-
-/** This class converts command line arguments, environment variables
- * and system properties (in File.pathSeparator-separated String form)
- * into a boot class path, user class path, and source path (in
- * Collection<String> form).
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class Paths {
-
- /** The context key for the todo list */
- protected static final Context.Key<Paths> pathsKey =
- new Context.Key<Paths>();
-
- /** Get the Paths instance for this context.
- * @param context the context
- * @return the Paths instance for this context
- */
- public static Paths instance(Context context) {
- Paths instance = context.get(pathsKey);
- if (instance == null)
- instance = new Paths(context);
- return instance;
- }
-
- /** The log to use for warning output */
- private Log log;
-
- /** Collection of command-line options */
- private Options options;
-
- /** Handler for -Xlint options */
- private Lint lint;
-
- /** Access to (possibly cached) file info */
- private FSInfo fsInfo;
-
- protected Paths(Context context) {
- context.put(pathsKey, this);
- pathsForLocation = new HashMap<Location,Path>(16);
- setContext(context);
- }
-
- void setContext(Context context) {
- log = Log.instance(context);
- options = Options.instance(context);
- lint = Lint.instance(context);
- fsInfo = FSInfo.instance(context);
- }
-
- /** Whether to warn about non-existent path elements */
- private boolean warn;
-
- private Map<Location, Path> pathsForLocation;
-
- private boolean inited = false; // TODO? caching bad?
-
- /**
- * rt.jar as found on the default bootclass path. If the user specified a
- * bootclasspath, null is used.
- */
- private File defaultBootClassPathRtJar = null;
-
- /**
- * Is bootclasspath the default?
- */
- private boolean isDefaultBootClassPath;
-
- Path getPathForLocation(Location location) {
- Path path = pathsForLocation.get(location);
- if (path == null)
- setPathForLocation(location, null);
- return pathsForLocation.get(location);
- }
-
- void setPathForLocation(Location location, Iterable<? extends File> path) {
- // TODO? if (inited) throw new IllegalStateException
- // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
- Path p;
- if (path == null) {
- if (location == CLASS_PATH)
- p = computeUserClassPath();
- else if (location == PLATFORM_CLASS_PATH)
- p = computeBootClassPath(); // sets isDefaultBootClassPath
- else if (location == ANNOTATION_PROCESSOR_PATH)
- p = computeAnnotationProcessorPath();
- else if (location == SOURCE_PATH)
- p = computeSourcePath();
- else
- // no defaults for other paths
- p = null;
- } else {
- if (location == PLATFORM_CLASS_PATH) {
- defaultBootClassPathRtJar = null;
- isDefaultBootClassPath = false;
- }
- p = new Path();
- for (File f: path)
- p.addFile(f, warn); // TODO: is use of warn appropriate?
- }
- pathsForLocation.put(location, p);
- }
-
- public boolean isDefaultBootClassPath() {
- lazy();
- return isDefaultBootClassPath;
- }
-
- protected void lazy() {
- if (!inited) {
- warn = lint.isEnabled(Lint.LintCategory.PATH);
-
- pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
- pathsForLocation.put(CLASS_PATH, computeUserClassPath());
- pathsForLocation.put(SOURCE_PATH, computeSourcePath());
-
- inited = true;
- }
- }
-
- public Collection<File> bootClassPath() {
- lazy();
- return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
- }
- public Collection<File> userClassPath() {
- lazy();
- return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
- }
- public Collection<File> sourcePath() {
- lazy();
- Path p = getPathForLocation(SOURCE_PATH);
- return p == null || p.size() == 0
- ? null
- : Collections.unmodifiableCollection(p);
- }
-
- boolean isDefaultBootClassPathRtJar(File file) {
- return file.equals(defaultBootClassPathRtJar);
- }
-
- /**
- * Split a path into its elements. Empty path elements will be ignored.
- * @param path The path to be split
- * @return The elements of the path
- */
- private static Iterable<File> getPathEntries(String path) {
- return getPathEntries(path, null);
- }
-
- /**
- * Split a path into its elements. If emptyPathDefault is not null, all
- * empty elements in the path, including empty elements at either end of
- * the path, will be replaced with the value of emptyPathDefault.
- * @param path The path to be split
- * @param emptyPathDefault The value to substitute for empty path elements,
- * or null, to ignore empty path elements
- * @return The elements of the path
- */
- private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
- ListBuffer<File> entries = new ListBuffer<File>();
- int start = 0;
- while (start <= path.length()) {
- int sep = path.indexOf(File.pathSeparatorChar, start);
- if (sep == -1)
- sep = path.length();
- if (start < sep)
- entries.add(new File(path.substring(start, sep)));
- else if (emptyPathDefault != null)
- entries.add(emptyPathDefault);
- start = sep + 1;
- }
- return entries;
- }
-
- private class Path extends LinkedHashSet<File> {
- private static final long serialVersionUID = 0;
-
- private boolean expandJarClassPaths = false;
- private Set<File> canonicalValues = new HashSet<File>();
-
- public Path expandJarClassPaths(boolean x) {
- expandJarClassPaths = x;
- return this;
- }
-
- /** What to use when path element is the empty string */
- private File emptyPathDefault = null;
-
- public Path emptyPathDefault(File x) {
- emptyPathDefault = x;
- return this;
- }
-
- public Path() { super(); }
-
- public Path addDirectories(String dirs, boolean warn) {
- boolean prev = expandJarClassPaths;
- expandJarClassPaths = true;
- try {
- if (dirs != null)
- for (File dir : getPathEntries(dirs))
- addDirectory(dir, warn);
- return this;
- } finally {
- expandJarClassPaths = prev;
- }
- }
-
- public Path addDirectories(String dirs) {
- return addDirectories(dirs, warn);
- }
-
- private void addDirectory(File dir, boolean warn) {
- if (!dir.isDirectory()) {
- if (warn)
- log.warning(Lint.LintCategory.PATH,
- "dir.path.element.not.found", dir);
- return;
- }
-
- File[] files = dir.listFiles();
- if (files == null)
- return;
-
- for (File direntry : files) {
- if (isArchive(direntry))
- addFile(direntry, warn);
- }
- }
-
- public Path addFiles(String files, boolean warn) {
- if (files != null) {
- for (File file : getPathEntries(files, emptyPathDefault))
- addFile(file, warn);
- }
- return this;
- }
-
- public Path addFiles(String files) {
- return addFiles(files, warn);
- }
-
- public void addFile(File file, boolean warn) {
- if (contains(file)) {
- // discard duplicates
- return;
- }
-
- if (! fsInfo.exists(file)) {
- /* No such file or directory exists */
- if (warn) {
- log.warning(Lint.LintCategory.PATH,
- "path.element.not.found", file);
- }
- super.add(file);
- return;
- }
-
- File canonFile = fsInfo.getCanonicalFile(file);
- if (canonicalValues.contains(canonFile)) {
- /* Discard duplicates and avoid infinite recursion */
- return;
- }
-
- if (fsInfo.isFile(file)) {
- /* File is an ordinary file. */
- if (!isArchive(file)) {
- /* Not a recognized extension; open it to see if
- it looks like a valid zip file. */
- try {
- ZipFile z = new ZipFile(file);
- z.close();
- if (warn) {
- log.warning(Lint.LintCategory.PATH,
- "unexpected.archive.file", file);
- }
- } catch (IOException e) {
- // FIXME: include e.getLocalizedMessage in warning
- if (warn) {
- log.warning(Lint.LintCategory.PATH,
- "invalid.archive.file", file);
- }
- return;
- }
- }
- }
-
- /* Now what we have left is either a directory or a file name
- conforming to archive naming convention */
- super.add(file);
- canonicalValues.add(canonFile);
-
- if (expandJarClassPaths && fsInfo.isFile(file))
- addJarClassPath(file, warn);
- }
-
- // Adds referenced classpath elements from a jar's Class-Path
- // Manifest entry. In some future release, we may want to
- // update this code to recognize URLs rather than simple
- // filenames, but if we do, we should redo all path-related code.
- private void addJarClassPath(File jarFile, boolean warn) {
- try {
- for (File f: fsInfo.getJarClassPath(jarFile)) {
- addFile(f, warn);
- }
- } catch (IOException e) {
- log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e));
- }
- }
- }
-
- private Path computeBootClassPath() {
- defaultBootClassPathRtJar = null;
- Path path = new Path();
-
- String bootclasspathOpt = options.get(BOOTCLASSPATH);
- String endorseddirsOpt = options.get(ENDORSEDDIRS);
- String extdirsOpt = options.get(EXTDIRS);
- String xbootclasspathPrependOpt = options.get(XBOOTCLASSPATH_PREPEND);
- String xbootclasspathAppendOpt = options.get(XBOOTCLASSPATH_APPEND);
-
- path.addFiles(xbootclasspathPrependOpt);
-
- if (endorseddirsOpt != null)
- path.addDirectories(endorseddirsOpt);
- else
- path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
-
- if (bootclasspathOpt != null) {
- path.addFiles(bootclasspathOpt);
- } else {
- // Standard system classes for this compiler's release.
- String files = System.getProperty("sun.boot.class.path");
- path.addFiles(files, false);
- File rt_jar = new File("rt.jar");
- for (File file : getPathEntries(files)) {
- if (new File(file.getName()).equals(rt_jar))
- defaultBootClassPathRtJar = file;
- }
- }
-
- path.addFiles(xbootclasspathAppendOpt);
-
- // Strictly speaking, standard extensions are not bootstrap
- // classes, but we treat them identically, so we'll pretend
- // that they are.
- if (extdirsOpt != null)
- path.addDirectories(extdirsOpt);
- else
- path.addDirectories(System.getProperty("java.ext.dirs"), false);
-
- isDefaultBootClassPath =
- (xbootclasspathPrependOpt == null) &&
- (bootclasspathOpt == null) &&
- (xbootclasspathAppendOpt == null);
-
- return path;
- }
-
- private Path computeUserClassPath() {
- String cp = options.get(CLASSPATH);
-
- // CLASSPATH environment variable when run from `javac'.
- if (cp == null) cp = System.getProperty("env.class.path");
-
- // If invoked via a java VM (not the javac launcher), use the
- // platform class path
- if (cp == null && System.getProperty("application.home") == null)
- cp = System.getProperty("java.class.path");
-
- // Default to current working directory.
- if (cp == null) cp = ".";
-
- return new Path()
- .expandJarClassPaths(true) // Only search user jars for Class-Paths
- .emptyPathDefault(new File(".")) // Empty path elt ==> current directory
- .addFiles(cp);
- }
-
- private Path computeSourcePath() {
- String sourcePathArg = options.get(SOURCEPATH);
- if (sourcePathArg == null)
- return null;
-
- return new Path().addFiles(sourcePathArg);
- }
-
- private Path computeAnnotationProcessorPath() {
- String processorPathArg = options.get(PROCESSORPATH);
- if (processorPathArg == null)
- return null;
-
- return new Path().addFiles(processorPathArg);
- }
-
- /** The actual effective locations searched for sources */
- private Path sourceSearchPath;
-
- public Collection<File> sourceSearchPath() {
- if (sourceSearchPath == null) {
- lazy();
- Path sourcePath = getPathForLocation(SOURCE_PATH);
- Path userClassPath = getPathForLocation(CLASS_PATH);
- sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
- }
- return Collections.unmodifiableCollection(sourceSearchPath);
- }
-
- /** The actual effective locations searched for classes */
- private Path classSearchPath;
-
- public Collection<File> classSearchPath() {
- if (classSearchPath == null) {
- lazy();
- Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
- Path userClassPath = getPathForLocation(CLASS_PATH);
- classSearchPath = new Path();
- classSearchPath.addAll(bootClassPath);
- classSearchPath.addAll(userClassPath);
- }
- return Collections.unmodifiableCollection(classSearchPath);
- }
-
- /** The actual effective locations for non-source, non-class files */
- private Path otherSearchPath;
-
- Collection<File> otherSearchPath() {
- if (otherSearchPath == null) {
- lazy();
- Path userClassPath = getPathForLocation(CLASS_PATH);
- Path sourcePath = getPathForLocation(SOURCE_PATH);
- if (sourcePath == null)
- otherSearchPath = userClassPath;
- else {
- otherSearchPath = new Path();
- otherSearchPath.addAll(userClassPath);
- otherSearchPath.addAll(sourcePath);
- }
- }
- return Collections.unmodifiableCollection(otherSearchPath);
- }
-
- /** Is this the name of an archive file? */
- private boolean isArchive(File file) {
- String n = file.getName().toLowerCase();
- return fsInfo.isFile(file)
- && (n.endsWith(".jar") || n.endsWith(".zip"));
- }
-
- /**
- * Utility method for converting a search path string to an array
- * of directory and JAR file URLs.
- *
- * Note that this method is called by apt and the DocletInvoker.
- *
- * @param path the search path string
- * @return the resulting array of directory and JAR file URLs
- */
- public static URL[] pathToURLs(String path) {
- StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
- URL[] urls = new URL[st.countTokens()];
- int count = 0;
- while (st.hasMoreTokens()) {
- URL url = fileToURL(new File(st.nextToken()));
- if (url != null) {
- urls[count++] = url;
- }
- }
- if (urls.length != count) {
- URL[] tmp = new URL[count];
- System.arraycopy(urls, 0, tmp, 0, count);
- urls = tmp;
- }
- return urls;
- }
-
- /**
- * Returns the directory or JAR file URL corresponding to the specified
- * local file name.
- *
- * @param file the File object
- * @return the resulting directory or JAR file URL, or null if unknown
- */
- private static URL fileToURL(File file) {
- String name;
- try {
- name = file.getCanonicalPath();
- } catch (IOException e) {
- name = file.getAbsolutePath();
- }
- name = name.replace(File.separatorChar, '/');
- if (!name.startsWith("/")) {
- name = "/" + name;
- }
- // If the file does not exist, then assume that it's a directory
- if (!file.isFile()) {
- name = name + "/";
- }
- try {
- return new URL("file", "", name);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(file.toString());
- }
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java Sat Nov 05 00:00:43 2011 -0700
@@ -1542,7 +1542,28 @@
*/
public void addCatch(
char startPc, char endPc, char handlerPc, char catchType) {
- catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
+ catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
+ }
+
+
+ public void compressCatchTable() {
+ ListBuffer<char[]> compressedCatchInfo = ListBuffer.lb();
+ List<Integer> handlerPcs = List.nil();
+ for (char[] catchEntry : catchInfo.elems) {
+ handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
+ }
+ for (char[] catchEntry : catchInfo.elems) {
+ int startpc = catchEntry[0];
+ int endpc = catchEntry[1];
+ if (startpc == endpc ||
+ (startpc == (endpc - 1) &&
+ handlerPcs.contains(startpc))) {
+ continue;
+ } else {
+ compressedCatchInfo.append(catchEntry);
+ }
+ }
+ catchInfo = compressedCatchInfo;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Sat Nov 05 00:00:43 2011 -0700
@@ -959,6 +959,9 @@
code.lastFrame = null;
code.frameBeforeLast = null;
}
+
+ //compress exception table
+ code.compressCatchTable();
}
}
@@ -1437,7 +1440,6 @@
code.markDead();
}
}
-
// Resolve all breaks.
code.resolve(exitChain);
@@ -1496,23 +1498,21 @@
void registerCatch(DiagnosticPosition pos,
int startpc, int endpc,
int handler_pc, int catch_type) {
- if (startpc != endpc) {
- char startpc1 = (char)startpc;
- char endpc1 = (char)endpc;
- char handler_pc1 = (char)handler_pc;
- if (startpc1 == startpc &&
- endpc1 == endpc &&
- handler_pc1 == handler_pc) {
- code.addCatch(startpc1, endpc1, handler_pc1,
- (char)catch_type);
+ char startpc1 = (char)startpc;
+ char endpc1 = (char)endpc;
+ char handler_pc1 = (char)handler_pc;
+ if (startpc1 == startpc &&
+ endpc1 == endpc &&
+ handler_pc1 == handler_pc) {
+ code.addCatch(startpc1, endpc1, handler_pc1,
+ (char)catch_type);
+ } else {
+ if (!useJsrLocally && !target.generateStackMapTable()) {
+ useJsrLocally = true;
+ throw new CodeSizeOverflow();
} else {
- if (!useJsrLocally && !target.generateStackMapTable()) {
- useJsrLocally = true;
- throw new CodeSizeOverflow();
- } else {
- log.error(pos, "limit.code.too.large.for.try.stmt");
- nerrs++;
- }
+ log.error(pos, "limit.code.too.large.for.try.stmt");
+ nerrs++;
}
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java Sat Nov 05 00:00:43 2011 -0700
@@ -25,9 +25,7 @@
package com.sun.tools.javac.nio;
-
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
@@ -60,7 +58,6 @@
import static java.nio.file.FileVisitOption.*;
import static javax.tools.StandardLocation.*;
-import com.sun.tools.javac.file.Paths;
import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
@@ -125,9 +122,8 @@
* Set the context for JavacPathFileManager.
*/
@Override
- protected void setContext(Context context) {
+ public void setContext(Context context) {
super.setContext(context);
- searchPaths = Paths.instance(context);
}
@Override
@@ -173,7 +169,7 @@
@Override
public boolean isDefaultBootClassPath() {
- return searchPaths.isDefaultBootClassPath();
+ return locations.isDefaultBootClassPath();
}
// <editor-fold defaultstate="collapsed" desc="Location handling">
@@ -231,13 +227,13 @@
if (locn instanceof StandardLocation) {
switch ((StandardLocation) locn) {
case CLASS_PATH:
- files = searchPaths.userClassPath();
+ files = locations.userClassPath();
break;
case PLATFORM_CLASS_PATH:
- files = searchPaths.bootClassPath();
+ files = locations.bootClassPath();
break;
case SOURCE_PATH:
- files = searchPaths.sourcePath();
+ files = locations.sourcePath();
break;
case CLASS_OUTPUT: {
String arg = options.get(D);
@@ -272,7 +268,6 @@
private boolean inited = false;
private Map<Location, PathsForLocation> pathsForLocation;
- private Paths searchPaths;
private static class PathsForLocation extends LinkedHashSet<Path> {
private static final long serialVersionUID = 6788510222394486733L;
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentScanner.java Thu Nov 03 13:26:57 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.parser;
-
-import java.nio.*;
-
-import com.sun.tools.javac.util.*;
-import static com.sun.tools.javac.util.LayoutCharacters.*;
-
-/** An extension to the base lexical analyzer that captures
- * and processes the contents of doc comments. It does so by
- * translating Unicode escape sequences and by stripping the
- * leading whitespace and starts from each line of the comment.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class DocCommentScanner extends Scanner {
-
- /** Create a scanner from the input buffer. buffer must implement
- * array() and compact(), and remaining() must be less than limit().
- */
- protected DocCommentScanner(ScannerFactory fac, CharBuffer buffer) {
- super(fac, buffer);
- }
-
- /** Create a scanner from the input array. The array must have at
- * least a single character of extra space.
- */
- protected DocCommentScanner(ScannerFactory fac, char[] input, int inputLength) {
- super(fac, input, inputLength);
- }
-
- /** Starting position of the comment in original source
- */
- private int pos;
-
- /** The comment input buffer, index of next chacter to be read,
- * index of one past last character in buffer.
- */
- private char[] buf;
- private int bp;
- private int buflen;
-
- /** The current character.
- */
- private char ch;
-
- /** The column number position of the current character.
- */
- private int col;
-
- /** The buffer index of the last converted Unicode character
- */
- private int unicodeConversionBp = 0;
-
- /**
- * Buffer for doc comment.
- */
- private char[] docCommentBuffer = new char[1024];
-
- /**
- * Number of characters in doc comment buffer.
- */
- private int docCommentCount;
-
- /**
- * Translated and stripped contents of doc comment
- */
- private String docComment = null;
-
-
- /** Unconditionally expand the comment buffer.
- */
- private void expandCommentBuffer() {
- char[] newBuffer = new char[docCommentBuffer.length * 2];
- System.arraycopy(docCommentBuffer, 0, newBuffer,
- 0, docCommentBuffer.length);
- docCommentBuffer = newBuffer;
- }
-
- /** Convert an ASCII digit from its base (8, 10, or 16)
- * to its value.
- */
- private int digit(int base) {
- char c = ch;
- int result = Character.digit(c, base);
- if (result >= 0 && c > 0x7f) {
- ch = "0123456789abcdef".charAt(result);
- }
- return result;
- }
-
- /** Convert Unicode escape; bp points to initial '\' character
- * (Spec 3.3).
- */
- private void convertUnicode() {
- if (ch == '\\' && unicodeConversionBp != bp) {
- bp++; ch = buf[bp]; col++;
- if (ch == 'u') {
- do {
- bp++; ch = buf[bp]; col++;
- } while (ch == 'u');
- int limit = bp + 3;
- if (limit < buflen) {
- int d = digit(16);
- int code = d;
- while (bp < limit && d >= 0) {
- bp++; ch = buf[bp]; col++;
- d = digit(16);
- code = (code << 4) + d;
- }
- if (d >= 0) {
- ch = (char)code;
- unicodeConversionBp = bp;
- return;
- }
- }
- // "illegal.Unicode.esc", reported by base scanner
- } else {
- bp--;
- ch = '\\';
- col--;
- }
- }
- }
-
-
- /** Read next character.
- */
- private void scanChar() {
- bp++;
- ch = buf[bp];
- switch (ch) {
- case '\r': // return
- col = 0;
- break;
- case '\n': // newline
- if (bp == 0 || buf[bp-1] != '\r') {
- col = 0;
- }
- break;
- case '\t': // tab
- col = (col / TabInc * TabInc) + TabInc;
- break;
- case '\\': // possible Unicode
- col++;
- convertUnicode();
- break;
- default:
- col++;
- break;
- }
- }
-
- /**
- * Read next character in doc comment, skipping over double '\' characters.
- * If a double '\' is skipped, put in the buffer and update buffer count.
- */
- private void scanDocCommentChar() {
- scanChar();
- if (ch == '\\') {
- if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- bp++; col++;
- } else {
- convertUnicode();
- }
- }
- }
-
- /* Reset doc comment before reading each new token
- */
- public void nextToken() {
- docComment = null;
- super.nextToken();
- }
-
- /**
- * Returns the documentation string of the current token.
- */
- public String docComment() {
- return docComment;
- }
-
- /**
- * Process a doc comment and make the string content available.
- * Strips leading whitespace and stars.
- */
- @SuppressWarnings("fallthrough")
- protected void processComment(CommentStyle style) {
- if (style != CommentStyle.JAVADOC) {
- return;
- }
-
- pos = pos();
- buf = getRawCharacters(pos, endPos());
- buflen = buf.length;
- bp = 0;
- col = 0;
-
- docCommentCount = 0;
-
- boolean firstLine = true;
-
- // Skip over first slash
- scanDocCommentChar();
- // Skip over first star
- scanDocCommentChar();
-
- // consume any number of stars
- while (bp < buflen && ch == '*') {
- scanDocCommentChar();
- }
- // is the comment in the form /**/, /***/, /****/, etc. ?
- if (bp < buflen && ch == '/') {
- docComment = "";
- return;
- }
-
- // skip a newline on the first line of the comment.
- if (bp < buflen) {
- if (ch == LF) {
- scanDocCommentChar();
- firstLine = false;
- } else if (ch == CR) {
- scanDocCommentChar();
- if (ch == LF) {
- scanDocCommentChar();
- firstLine = false;
- }
- }
- }
-
- outerLoop:
-
- // The outerLoop processes the doc comment, looping once
- // for each line. For each line, it first strips off
- // whitespace, then it consumes any stars, then it
- // puts the rest of the line into our buffer.
- while (bp < buflen) {
-
- // The wsLoop consumes whitespace from the beginning
- // of each line.
- wsLoop:
-
- while (bp < buflen) {
- switch(ch) {
- case ' ':
- scanDocCommentChar();
- break;
- case '\t':
- col = ((col - 1) / TabInc * TabInc) + TabInc;
- scanDocCommentChar();
- break;
- case FF:
- col = 0;
- scanDocCommentChar();
- break;
-// Treat newline at beginning of line (blank line, no star)
-// as comment text. Old Javadoc compatibility requires this.
-/*---------------------------------*
- case CR: // (Spec 3.4)
- scanDocCommentChar();
- if (ch == LF) {
- col = 0;
- scanDocCommentChar();
- }
- break;
- case LF: // (Spec 3.4)
- scanDocCommentChar();
- break;
-*---------------------------------*/
- default:
- // we've seen something that isn't whitespace;
- // jump out.
- break wsLoop;
- }
- }
-
- // Are there stars here? If so, consume them all
- // and check for the end of comment.
- if (ch == '*') {
- // skip all of the stars
- do {
- scanDocCommentChar();
- } while (ch == '*');
-
- // check for the closing slash.
- if (ch == '/') {
- // We're done with the doc comment
- // scanChar() and breakout.
- break outerLoop;
- }
- } else if (! firstLine) {
- //The current line does not begin with a '*' so we will indent it.
- for (int i = 1; i < col; i++) {
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ' ';
- }
- }
-
- // The textLoop processes the rest of the characters
- // on the line, adding them to our buffer.
- textLoop:
- while (bp < buflen) {
- switch (ch) {
- case '*':
- // Is this just a star? Or is this the
- // end of a comment?
- scanDocCommentChar();
- if (ch == '/') {
- // This is the end of the comment,
- // set ch and return our buffer.
- break outerLoop;
- }
- // This is just an ordinary star. Add it to
- // the buffer.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = '*';
- break;
- case ' ':
- case '\t':
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- break;
- case FF:
- scanDocCommentChar();
- break textLoop; // treat as end of line
- case CR: // (Spec 3.4)
- scanDocCommentChar();
- if (ch != LF) {
- // Canonicalize CR-only line terminator to LF
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = (char)LF;
- break textLoop;
- }
- /* fall through to LF case */
- case LF: // (Spec 3.4)
- // We've seen a newline. Add it to our
- // buffer and break out of this loop,
- // starting fresh on a new line.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- break textLoop;
- default:
- // Add the character to our buffer.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- }
- } // end textLoop
- firstLine = false;
- } // end outerLoop
-
- if (docCommentCount > 0) {
- int i = docCommentCount - 1;
- trailLoop:
- while (i > -1) {
- switch (docCommentBuffer[i]) {
- case '*':
- i--;
- break;
- default:
- break trailLoop;
- }
- }
- docCommentCount = i + 1;
-
- // Store the text of the doc comment
- docComment = new String(docCommentBuffer, 0 , docCommentCount);
- } else {
- docComment = "";
- }
- }
-
- /** Build a map for translating between line numbers and
- * positions in the input.
- *
- * @return a LineMap */
- public Position.LineMap getLineMap() {
- char[] buf = getRawCharacters();
- return Position.makeLineMap(buf, buf.length, true);
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java Sat Nov 05 00:00:43 2011 -0700
@@ -67,14 +67,14 @@
/** {@inheritDoc} */
@Override
protected <T extends JCTree> T to(T t) {
- storeEnd(t, S.endPos());
+ storeEnd(t, token.endPos);
return t;
}
/** {@inheritDoc} */
@Override
protected <T extends JCTree> T toP(T t) {
- storeEnd(t, S.prevEndPos());
+ storeEnd(t, S.prevToken().endPos);
return t;
}
@@ -88,7 +88,7 @@
/** {@inheritDoc} */
@Override
JCExpression parExpression() {
- int pos = S.pos();
+ int pos = token.pos;
JCExpression t = super.parExpression();
return toP(F.at(pos).Parens(t));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,896 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.parser;
+
+import java.nio.CharBuffer;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.util.*;
+
+
+import static com.sun.tools.javac.parser.Tokens.*;
+import static com.sun.tools.javac.util.LayoutCharacters.*;
+
+/** The lexical analyzer maps an input stream consisting of
+ * ASCII characters and Unicode escapes into a token sequence.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class JavaTokenizer {
+
+ private static boolean scannerDebug = false;
+
+ /** Allow hex floating-point literals.
+ */
+ private boolean allowHexFloats;
+
+ /** Allow binary literals.
+ */
+ private boolean allowBinaryLiterals;
+
+ /** Allow underscores in literals.
+ */
+ private boolean allowUnderscoresInLiterals;
+
+ /** The source language setting.
+ */
+ private Source source;
+
+ /** The log to be used for error reporting.
+ */
+ private final Log log;
+
+ /** The name table. */
+ private final Names names;
+
+ /** The token factory. */
+ private final Tokens tokens;
+
+ /** The token kind, set by nextToken().
+ */
+ protected TokenKind tk;
+
+ /** The token's radix, set by nextToken().
+ */
+ protected int radix;
+
+ /** The token's name, set by nextToken().
+ */
+ protected Name name;
+
+ /** The position where a lexical error occurred;
+ */
+ protected int errPos = Position.NOPOS;
+
+ /** Has a @deprecated been encountered in last doc comment?
+ * this needs to be reset by client.
+ */
+ protected boolean deprecatedFlag = false;
+
+ /** A character buffer for saved chars.
+ */
+ protected char[] sbuf = new char[128];
+ protected int sp;
+
+ protected UnicodeReader reader;
+
+ private static final boolean hexFloatsWork = hexFloatsWork();
+ private static boolean hexFloatsWork() {
+ try {
+ Float.valueOf("0x1.0p1");
+ return true;
+ } catch (NumberFormatException ex) {
+ return false;
+ }
+ }
+
+ /**
+ * Create a scanner from the input array. This method might
+ * modify the array. To avoid copying the input array, ensure
+ * that {@code inputLength < input.length} or
+ * {@code input[input.length -1]} is a white space character.
+ *
+ * @param fac the factory which created this Scanner
+ * @param input the input, might be modified
+ * @param inputLength the size of the input.
+ * Must be positive and less than or equal to input.length.
+ */
+ protected JavaTokenizer(ScannerFactory fac, CharBuffer buf) {
+ this(fac, new UnicodeReader(fac, buf));
+ }
+
+ protected JavaTokenizer(ScannerFactory fac, char[] buf, int inputLength) {
+ this(fac, new UnicodeReader(fac, buf, inputLength));
+ }
+
+ protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) {
+ log = fac.log;
+ names = fac.names;
+ tokens = fac.tokens;
+ source = fac.source;
+ this.reader = reader;
+ allowBinaryLiterals = source.allowBinaryLiterals();
+ allowHexFloats = source.allowHexFloats();
+ allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
+ }
+
+ /** Report an error at the given position using the provided arguments.
+ */
+ protected void lexError(int pos, String key, Object... args) {
+ log.error(pos, key, args);
+ tk = TokenKind.ERROR;
+ errPos = pos;
+ }
+
+ /** Read next character in comment, skipping over double '\' characters.
+ */
+ protected void scanCommentChar() {
+ reader.scanChar();
+ if (reader.ch == '\\') {
+ if (reader.peekChar() == '\\' && !reader.isUnicode()) {
+ reader.skipChar();
+ } else {
+ reader.convertUnicode();
+ }
+ }
+ }
+
+ /** Append a character to sbuf.
+ */
+ private void putChar(char ch) {
+ if (sp == sbuf.length) {
+ char[] newsbuf = new char[sbuf.length * 2];
+ System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
+ sbuf = newsbuf;
+ }
+ sbuf[sp++] = ch;
+ }
+
+ /** Read next character in character or string literal and copy into sbuf.
+ */
+ private void scanLitChar(int pos) {
+ if (reader.ch == '\\') {
+ if (reader.peekChar() == '\\' && !reader.isUnicode()) {
+ reader.skipChar();
+ putChar('\\');
+ reader.scanChar();
+ } else {
+ reader.scanChar();
+ switch (reader.ch) {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ char leadch = reader.ch;
+ int oct = reader.digit(pos, 8);
+ reader.scanChar();
+ if ('0' <= reader.ch && reader.ch <= '7') {
+ oct = oct * 8 + reader.digit(pos, 8);
+ reader.scanChar();
+ if (leadch <= '3' && '0' <= reader.ch && reader.ch <= '7') {
+ oct = oct * 8 + reader.digit(pos, 8);
+ reader.scanChar();
+ }
+ }
+ putChar((char)oct);
+ break;
+ case 'b':
+ putChar('\b'); reader.scanChar(); break;
+ case 't':
+ putChar('\t'); reader.scanChar(); break;
+ case 'n':
+ putChar('\n'); reader.scanChar(); break;
+ case 'f':
+ putChar('\f'); reader.scanChar(); break;
+ case 'r':
+ putChar('\r'); reader.scanChar(); break;
+ case '\'':
+ putChar('\''); reader.scanChar(); break;
+ case '\"':
+ putChar('\"'); reader.scanChar(); break;
+ case '\\':
+ putChar('\\'); reader.scanChar(); break;
+ default:
+ lexError(reader.bp, "illegal.esc.char");
+ }
+ }
+ } else if (reader.bp != reader.buflen) {
+ putChar(reader.ch); reader.scanChar();
+ }
+ }
+
+ private void scanDigits(int pos, int digitRadix) {
+ char saveCh;
+ int savePos;
+ do {
+ if (reader.ch != '_') {
+ putChar(reader.ch);
+ } else {
+ if (!allowUnderscoresInLiterals) {
+ lexError(pos, "unsupported.underscore.lit", source.name);
+ allowUnderscoresInLiterals = true;
+ }
+ }
+ saveCh = reader.ch;
+ savePos = reader.bp;
+ reader.scanChar();
+ } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_');
+ if (saveCh == '_')
+ lexError(savePos, "illegal.underscore");
+ }
+
+ /** Read fractional part of hexadecimal floating point number.
+ */
+ private void scanHexExponentAndSuffix(int pos) {
+ if (reader.ch == 'p' || reader.ch == 'P') {
+ putChar(reader.ch);
+ reader.scanChar();
+ skipIllegalUnderscores();
+ if (reader.ch == '+' || reader.ch == '-') {
+ putChar(reader.ch);
+ reader.scanChar();
+ }
+ skipIllegalUnderscores();
+ if ('0' <= reader.ch && reader.ch <= '9') {
+ scanDigits(pos, 10);
+ if (!allowHexFloats) {
+ lexError(pos, "unsupported.fp.lit", source.name);
+ allowHexFloats = true;
+ }
+ else if (!hexFloatsWork)
+ lexError(pos, "unsupported.cross.fp.lit");
+ } else
+ lexError(pos, "malformed.fp.lit");
+ } else {
+ lexError(pos, "malformed.fp.lit");
+ }
+ if (reader.ch == 'f' || reader.ch == 'F') {
+ putChar(reader.ch);
+ reader.scanChar();
+ tk = TokenKind.FLOATLITERAL;
+ radix = 16;
+ } else {
+ if (reader.ch == 'd' || reader.ch == 'D') {
+ putChar(reader.ch);
+ reader.scanChar();
+ }
+ tk = TokenKind.DOUBLELITERAL;
+ radix = 16;
+ }
+ }
+
+ /** Read fractional part of floating point number.
+ */
+ private void scanFraction(int pos) {
+ skipIllegalUnderscores();
+ if ('0' <= reader.ch && reader.ch <= '9') {
+ scanDigits(pos, 10);
+ }
+ int sp1 = sp;
+ if (reader.ch == 'e' || reader.ch == 'E') {
+ putChar(reader.ch);
+ reader.scanChar();
+ skipIllegalUnderscores();
+ if (reader.ch == '+' || reader.ch == '-') {
+ putChar(reader.ch);
+ reader.scanChar();
+ }
+ skipIllegalUnderscores();
+ if ('0' <= reader.ch && reader.ch <= '9') {
+ scanDigits(pos, 10);
+ return;
+ }
+ lexError(pos, "malformed.fp.lit");
+ sp = sp1;
+ }
+ }
+
+ /** Read fractional part and 'd' or 'f' suffix of floating point number.
+ */
+ private void scanFractionAndSuffix(int pos) {
+ radix = 10;
+ scanFraction(pos);
+ if (reader.ch == 'f' || reader.ch == 'F') {
+ putChar(reader.ch);
+ reader.scanChar();
+ tk = TokenKind.FLOATLITERAL;
+ } else {
+ if (reader.ch == 'd' || reader.ch == 'D') {
+ putChar(reader.ch);
+ reader.scanChar();
+ }
+ tk = TokenKind.DOUBLELITERAL;
+ }
+ }
+
+ /** Read fractional part and 'd' or 'f' suffix of floating point number.
+ */
+ private void scanHexFractionAndSuffix(int pos, boolean seendigit) {
+ radix = 16;
+ Assert.check(reader.ch == '.');
+ putChar(reader.ch);
+ reader.scanChar();
+ skipIllegalUnderscores();
+ if (reader.digit(pos, 16) >= 0) {
+ seendigit = true;
+ scanDigits(pos, 16);
+ }
+ if (!seendigit)
+ lexError(pos, "invalid.hex.number");
+ else
+ scanHexExponentAndSuffix(pos);
+ }
+
+ private void skipIllegalUnderscores() {
+ if (reader.ch == '_') {
+ lexError(reader.bp, "illegal.underscore");
+ while (reader.ch == '_')
+ reader.scanChar();
+ }
+ }
+
+ /** Read a number.
+ * @param radix The radix of the number; one of 2, j8, 10, 16.
+ */
+ private void scanNumber(int pos, int radix) {
+ // for octal, allow base-10 digit in case it's a float literal
+ this.radix = radix;
+ int digitRadix = (radix == 8 ? 10 : radix);
+ boolean seendigit = false;
+ if (reader.digit(pos, digitRadix) >= 0) {
+ seendigit = true;
+ scanDigits(pos, digitRadix);
+ }
+ if (radix == 16 && reader.ch == '.') {
+ scanHexFractionAndSuffix(pos, seendigit);
+ } else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) {
+ scanHexExponentAndSuffix(pos);
+ } else if (digitRadix == 10 && reader.ch == '.') {
+ putChar(reader.ch);
+ reader.scanChar();
+ scanFractionAndSuffix(pos);
+ } else if (digitRadix == 10 &&
+ (reader.ch == 'e' || reader.ch == 'E' ||
+ reader.ch == 'f' || reader.ch == 'F' ||
+ reader.ch == 'd' || reader.ch == 'D')) {
+ scanFractionAndSuffix(pos);
+ } else {
+ if (reader.ch == 'l' || reader.ch == 'L') {
+ reader.scanChar();
+ tk = TokenKind.LONGLITERAL;
+ } else {
+ tk = TokenKind.INTLITERAL;
+ }
+ }
+ }
+
+ /** Read an identifier.
+ */
+ private void scanIdent() {
+ boolean isJavaIdentifierPart;
+ char high;
+ do {
+ if (sp == sbuf.length) putChar(reader.ch); else sbuf[sp++] = reader.ch;
+ // optimization, was: putChar(reader.ch);
+
+ reader.scanChar();
+ switch (reader.ch) {
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y':
+ case 'Z':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ case '$': case '_':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '\u0000': case '\u0001': case '\u0002': case '\u0003':
+ case '\u0004': case '\u0005': case '\u0006': case '\u0007':
+ case '\u0008': case '\u000E': case '\u000F': case '\u0010':
+ case '\u0011': case '\u0012': case '\u0013': case '\u0014':
+ case '\u0015': case '\u0016': case '\u0017':
+ case '\u0018': case '\u0019': case '\u001B':
+ case '\u007F':
+ break;
+ case '\u001A': // EOI is also a legal identifier part
+ if (reader.bp >= reader.buflen) {
+ name = names.fromChars(sbuf, 0, sp);
+ tk = tokens.lookupKind(name);
+ return;
+ }
+ break;
+ default:
+ if (reader.ch < '\u0080') {
+ // all ASCII range chars already handled, above
+ isJavaIdentifierPart = false;
+ } else {
+ high = reader.scanSurrogates();
+ if (high != 0) {
+ if (sp == sbuf.length) {
+ putChar(high);
+ } else {
+ sbuf[sp++] = high;
+ }
+ isJavaIdentifierPart = Character.isJavaIdentifierPart(
+ Character.toCodePoint(high, reader.ch));
+ } else {
+ isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch);
+ }
+ }
+ if (!isJavaIdentifierPart) {
+ name = names.fromChars(sbuf, 0, sp);
+ tk = tokens.lookupKind(name);
+ return;
+ }
+ }
+ } while (true);
+ }
+
+ /** Return true if reader.ch can be part of an operator.
+ */
+ private boolean isSpecial(char ch) {
+ switch (ch) {
+ case '!': case '%': case '&': case '*': case '?':
+ case '+': case '-': case ':': case '<': case '=':
+ case '>': case '^': case '|': case '~':
+ case '@':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /** Read longest possible sequence of special characters and convert
+ * to token.
+ */
+ private void scanOperator() {
+ while (true) {
+ putChar(reader.ch);
+ Name newname = names.fromChars(sbuf, 0, sp);
+ TokenKind tk1 = tokens.lookupKind(newname);
+ if (tk1 == TokenKind.IDENTIFIER) {
+ sp--;
+ break;
+ }
+ tk = tk1;
+ reader.scanChar();
+ if (!isSpecial(reader.ch)) break;
+ }
+ }
+
+ /**
+ * Scan a documentation comment; determine if a deprecated tag is present.
+ * Called once the initial /, * have been skipped, positioned at the second *
+ * (which is treated as the beginning of the first line).
+ * Stops positioned at the closing '/'.
+ */
+ @SuppressWarnings("fallthrough")
+ private void scanDocComment() {
+ boolean deprecatedPrefix = false;
+
+ forEachLine:
+ while (reader.bp < reader.buflen) {
+
+ // Skip optional WhiteSpace at beginning of line
+ while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) {
+ scanCommentChar();
+ }
+
+ // Skip optional consecutive Stars
+ while (reader.bp < reader.buflen && reader.ch == '*') {
+ scanCommentChar();
+ if (reader.ch == '/') {
+ return;
+ }
+ }
+
+ // Skip optional WhiteSpace after Stars
+ while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) {
+ scanCommentChar();
+ }
+
+ deprecatedPrefix = false;
+ // At beginning of line in the JavaDoc sense.
+ if (reader.bp < reader.buflen && reader.ch == '@' && !deprecatedFlag) {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'd') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'e') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'p') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'r') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'e') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'c') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'a') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 't') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'e') {
+ scanCommentChar();
+ if (reader.bp < reader.buflen && reader.ch == 'd') {
+ deprecatedPrefix = true;
+ scanCommentChar();
+ }}}}}}}}}}}
+ if (deprecatedPrefix && reader.bp < reader.buflen) {
+ if (Character.isWhitespace(reader.ch)) {
+ deprecatedFlag = true;
+ } else if (reader.ch == '*') {
+ scanCommentChar();
+ if (reader.ch == '/') {
+ deprecatedFlag = true;
+ return;
+ }
+ }
+ }
+
+ // Skip rest of line
+ while (reader.bp < reader.buflen) {
+ switch (reader.ch) {
+ case '*':
+ scanCommentChar();
+ if (reader.ch == '/') {
+ return;
+ }
+ break;
+ case CR: // (Spec 3.4)
+ scanCommentChar();
+ if (reader.ch != LF) {
+ continue forEachLine;
+ }
+ /* fall through to LF case */
+ case LF: // (Spec 3.4)
+ scanCommentChar();
+ continue forEachLine;
+ default:
+ scanCommentChar();
+ }
+ } // rest of line
+ } // forEachLine
+ return;
+ }
+
+ /** Read token.
+ */
+ public Token readToken() {
+
+ sp = 0;
+ name = null;
+ deprecatedFlag = false;
+ radix = 0;
+ int pos = 0;
+ int endPos = 0;
+
+ try {
+ loop: while (true) {
+ pos = reader.bp;
+ switch (reader.ch) {
+ case ' ': // (Spec 3.6)
+ case '\t': // (Spec 3.6)
+ case FF: // (Spec 3.6)
+ do {
+ reader.scanChar();
+ } while (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF);
+ processWhiteSpace(pos, reader.bp);
+ break;
+ case LF: // (Spec 3.4)
+ reader.scanChar();
+ processLineTerminator(pos, reader.bp);
+ break;
+ case CR: // (Spec 3.4)
+ reader.scanChar();
+ if (reader.ch == LF) {
+ reader.scanChar();
+ }
+ processLineTerminator(pos, reader.bp);
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y':
+ case 'Z':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ case '$': case '_':
+ scanIdent();
+ break loop;
+ case '0':
+ reader.scanChar();
+ if (reader.ch == 'x' || reader.ch == 'X') {
+ reader.scanChar();
+ skipIllegalUnderscores();
+ if (reader.ch == '.') {
+ scanHexFractionAndSuffix(pos, false);
+ } else if (reader.digit(pos, 16) < 0) {
+ lexError(pos, "invalid.hex.number");
+ } else {
+ scanNumber(pos, 16);
+ }
+ } else if (reader.ch == 'b' || reader.ch == 'B') {
+ if (!allowBinaryLiterals) {
+ lexError(pos, "unsupported.binary.lit", source.name);
+ allowBinaryLiterals = true;
+ }
+ reader.scanChar();
+ skipIllegalUnderscores();
+ if (reader.digit(pos, 2) < 0) {
+ lexError(pos, "invalid.binary.number");
+ } else {
+ scanNumber(pos, 2);
+ }
+ } else {
+ putChar('0');
+ if (reader.ch == '_') {
+ int savePos = reader.bp;
+ do {
+ reader.scanChar();
+ } while (reader.ch == '_');
+ if (reader.digit(pos, 10) < 0) {
+ lexError(savePos, "illegal.underscore");
+ }
+ }
+ scanNumber(pos, 8);
+ }
+ break loop;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ scanNumber(pos, 10);
+ break loop;
+ case '.':
+ reader.scanChar();
+ if ('0' <= reader.ch && reader.ch <= '9') {
+ putChar('.');
+ scanFractionAndSuffix(pos);
+ } else if (reader.ch == '.') {
+ putChar('.'); putChar('.');
+ reader.scanChar();
+ if (reader.ch == '.') {
+ reader.scanChar();
+ putChar('.');
+ tk = TokenKind.ELLIPSIS;
+ } else {
+ lexError(pos, "malformed.fp.lit");
+ }
+ } else {
+ tk = TokenKind.DOT;
+ }
+ break loop;
+ case ',':
+ reader.scanChar(); tk = TokenKind.COMMA; break loop;
+ case ';':
+ reader.scanChar(); tk = TokenKind.SEMI; break loop;
+ case '(':
+ reader.scanChar(); tk = TokenKind.LPAREN; break loop;
+ case ')':
+ reader.scanChar(); tk = TokenKind.RPAREN; break loop;
+ case '[':
+ reader.scanChar(); tk = TokenKind.LBRACKET; break loop;
+ case ']':
+ reader.scanChar(); tk = TokenKind.RBRACKET; break loop;
+ case '{':
+ reader.scanChar(); tk = TokenKind.LBRACE; break loop;
+ case '}':
+ reader.scanChar(); tk = TokenKind.RBRACE; break loop;
+ case '/':
+ reader.scanChar();
+ if (reader.ch == '/') {
+ do {
+ scanCommentChar();
+ } while (reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen);
+ if (reader.bp < reader.buflen) {
+ processComment(pos, reader.bp, CommentStyle.LINE);
+ }
+ break;
+ } else if (reader.ch == '*') {
+ reader.scanChar();
+ CommentStyle style;
+ if (reader.ch == '*') {
+ style = CommentStyle.JAVADOC;
+ scanDocComment();
+ } else {
+ style = CommentStyle.BLOCK;
+ while (reader.bp < reader.buflen) {
+ if (reader.ch == '*') {
+ reader.scanChar();
+ if (reader.ch == '/') break;
+ } else {
+ scanCommentChar();
+ }
+ }
+ }
+ if (reader.ch == '/') {
+ reader.scanChar();
+ processComment(pos, reader.bp, style);
+ break;
+ } else {
+ lexError(pos, "unclosed.comment");
+ break loop;
+ }
+ } else if (reader.ch == '=') {
+ tk = TokenKind.SLASHEQ;
+ reader.scanChar();
+ } else {
+ tk = TokenKind.SLASH;
+ }
+ break loop;
+ case '\'':
+ reader.scanChar();
+ if (reader.ch == '\'') {
+ lexError(pos, "empty.char.lit");
+ } else {
+ if (reader.ch == CR || reader.ch == LF)
+ lexError(pos, "illegal.line.end.in.char.lit");
+ scanLitChar(pos);
+ char ch2 = reader.ch;
+ if (reader.ch == '\'') {
+ reader.scanChar();
+ tk = TokenKind.CHARLITERAL;
+ } else {
+ lexError(pos, "unclosed.char.lit");
+ }
+ }
+ break loop;
+ case '\"':
+ reader.scanChar();
+ while (reader.ch != '\"' && reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen)
+ scanLitChar(pos);
+ if (reader.ch == '\"') {
+ tk = TokenKind.STRINGLITERAL;
+ reader.scanChar();
+ } else {
+ lexError(pos, "unclosed.str.lit");
+ }
+ break loop;
+ default:
+ if (isSpecial(reader.ch)) {
+ scanOperator();
+ } else {
+ boolean isJavaIdentifierStart;
+ if (reader.ch < '\u0080') {
+ // all ASCII range chars already handled, above
+ isJavaIdentifierStart = false;
+ } else {
+ char high = reader.scanSurrogates();
+ if (high != 0) {
+ if (sp == sbuf.length) {
+ putChar(high);
+ } else {
+ sbuf[sp++] = high;
+ }
+
+ isJavaIdentifierStart = Character.isJavaIdentifierStart(
+ Character.toCodePoint(high, reader.ch));
+ } else {
+ isJavaIdentifierStart = Character.isJavaIdentifierStart(reader.ch);
+ }
+ }
+ if (isJavaIdentifierStart) {
+ scanIdent();
+ } else if (reader.bp == reader.buflen || reader.ch == EOI && reader.bp + 1 == reader.buflen) { // JLS 3.5
+ tk = TokenKind.EOF;
+ pos = reader.buflen;
+ } else {
+ lexError(pos, "illegal.char", String.valueOf((int)reader.ch));
+ reader.scanChar();
+ }
+ }
+ break loop;
+ }
+ }
+ endPos = reader.bp;
+ switch (tk.tag) {
+ case DEFAULT: return new Token(tk, pos, endPos, deprecatedFlag);
+ case NAMED: return new NamedToken(tk, pos, endPos, name, deprecatedFlag);
+ case STRING: return new StringToken(tk, pos, endPos, new String(sbuf, 0, sp), deprecatedFlag);
+ case NUMERIC: return new NumericToken(tk, pos, endPos, new String(sbuf, 0, sp), radix, deprecatedFlag);
+ default: throw new AssertionError();
+ }
+ }
+ finally {
+ if (scannerDebug) {
+ System.out.println("nextToken(" + pos
+ + "," + endPos + ")=|" +
+ new String(reader.getRawCharacters(pos, endPos))
+ + "|");
+ }
+ }
+ }
+
+ /** Return the position where a lexical error occurred;
+ */
+ public int errPos() {
+ return errPos;
+ }
+
+ /** Set the position where a lexical error occurred;
+ */
+ public void errPos(int pos) {
+ errPos = pos;
+ }
+
+ public enum CommentStyle {
+ LINE,
+ BLOCK,
+ JAVADOC,
+ }
+
+ /**
+ * Called when a complete comment has been scanned. pos and endPos
+ * will mark the comment boundary.
+ */
+ protected void processComment(int pos, int endPos, CommentStyle style) {
+ if (scannerDebug)
+ System.out.println("processComment(" + pos
+ + "," + endPos + "," + style + ")=|"
+ + new String(reader.getRawCharacters(pos, endPos))
+ + "|");
+ }
+
+ /**
+ * Called when a complete whitespace run has been scanned. pos and endPos
+ * will mark the whitespace boundary.
+ */
+ protected void processWhiteSpace(int pos, int endPos) {
+ if (scannerDebug)
+ System.out.println("processWhitespace(" + pos
+ + "," + endPos + ")=|" +
+ new String(reader.getRawCharacters(pos, endPos))
+ + "|");
+ }
+
+ /**
+ * Called when a line terminator has been processed.
+ */
+ protected void processLineTerminator(int pos, int endPos) {
+ if (scannerDebug)
+ System.out.println("processTerminator(" + pos
+ + "," + endPos + ")=|" +
+ new String(reader.getRawCharacters(pos, endPos))
+ + "|");
+ }
+
+ /** Build a map for translating between line numbers and
+ * positions in the input.
+ *
+ * @return a LineMap */
+ public Position.LineMap getLineMap() {
+ return Position.makeLineMap(reader.getRawCharacters(), reader.buflen, false);
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Sat Nov 05 00:00:43 2011 -0700
@@ -28,6 +28,7 @@
import java.util.*;
import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.parser.Tokens.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*;
@@ -36,7 +37,7 @@
import com.sun.tools.javac.util.List;
import static com.sun.tools.javac.util.ListBuffer.lb;
-import static com.sun.tools.javac.parser.Token.*;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
/** The parser maps a token sequence into an abstract syntax
* tree. It operates by recursive descent, with code derived
@@ -67,9 +68,6 @@
*/
private Log log;
- /** The keyword table. */
- private Keywords keywords;
-
/** The Source language setting. */
private Source source;
@@ -83,11 +81,10 @@
boolean keepDocComments,
boolean keepLineMap) {
this.S = S;
- S.nextToken(); // prime the pump
+ nextToken(); // prime the pump
this.F = fac.F;
this.log = fac.log;
this.names = fac.names;
- this.keywords = fac.keywords;
this.source = fac.source;
this.allowGenerics = source.allowGenerics();
this.allowVarargs = source.allowVarargs();
@@ -178,7 +175,16 @@
*/
private int lastmode = 0;
-/* ---------- error recovery -------------- */
+ /* ---------- token management -------------- */
+
+ protected Token token;
+
+ protected void nextToken() {
+ S.nextToken();
+ token = S.token();
+ }
+
+ /* ---------- error recovery -------------- */
private JCErroneous errorTree;
@@ -186,9 +192,9 @@
*/
private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
while (true) {
- switch (S.token()) {
+ switch (token.kind) {
case SEMI:
- S.nextToken();
+ nextToken();
return;
case PUBLIC:
case FINAL:
@@ -249,15 +255,15 @@
return;
break;
}
- S.nextToken();
+ nextToken();
}
}
- private JCErroneous syntaxError(int pos, String key, Token... args) {
+ private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
return syntaxError(pos, List.<JCTree>nil(), key, args);
}
- private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
+ private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
setErrorEndPos(pos);
JCErroneous err = F.at(pos).Erroneous(errs);
reportSyntaxError(err, key, (Object[])args);
@@ -287,16 +293,16 @@
private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
int pos = diagPos.getPreferredPosition();
if (pos > S.errPos() || pos == Position.NOPOS) {
- if (S.token() == EOF) {
+ if (token.kind == EOF) {
error(diagPos, "premature.eof");
} else {
error(diagPos, key, args);
}
}
S.errPos(pos);
- if (S.pos() == errorPos)
- S.nextToken(); // guarantee progress
- errorPos = S.pos();
+ if (token.pos == errorPos)
+ nextToken(); // guarantee progress
+ errorPos = token.pos;
}
@@ -304,25 +310,25 @@
* reported at the same position.
*/
private JCErroneous syntaxError(String key) {
- return syntaxError(S.pos(), key);
+ return syntaxError(token.pos, key);
}
/** Generate a syntax error at current position unless one was
* already reported at the same position.
*/
- private JCErroneous syntaxError(String key, Token arg) {
- return syntaxError(S.pos(), key, arg);
+ private JCErroneous syntaxError(String key, TokenKind arg) {
+ return syntaxError(token.pos, key, arg);
}
/** If next input token matches given token, skip it, otherwise report
* an error.
*/
- public void accept(Token token) {
- if (S.token() == token) {
- S.nextToken();
+ public void accept(TokenKind tk) {
+ if (token.kind == tk) {
+ nextToken();
} else {
- setErrorEndPos(S.pos());
- reportSyntaxError(S.prevEndPos(), "expected", token);
+ setErrorEndPos(token.pos);
+ reportSyntaxError(S.prevToken().endPos, "expected", tk);
}
}
@@ -340,14 +346,14 @@
/** Report an illegal start of expression/type error at current position.
*/
JCExpression illegal() {
- return illegal(S.pos());
+ return illegal(token.pos);
}
/** Diagnose a modifier flag from the set, if any. */
void checkNoMods(long mods) {
if (mods != 0) {
long lowestMod = mods & -mods;
- error(S.pos(), "mod.not.allowed.here",
+ error(token.pos, "mod.not.allowed.here",
Flags.asFlagSet(lowestMod));
}
}
@@ -435,30 +441,30 @@
* Ident = IDENTIFIER
*/
Name ident() {
- if (S.token() == IDENTIFIER) {
- Name name = S.name();
- S.nextToken();
+ if (token.kind == IDENTIFIER) {
+ Name name = token.name();
+ nextToken();
return name;
- } else if (S.token() == ASSERT) {
+ } else if (token.kind == ASSERT) {
if (allowAsserts) {
- error(S.pos(), "assert.as.identifier");
- S.nextToken();
+ error(token.pos, "assert.as.identifier");
+ nextToken();
return names.error;
} else {
- warning(S.pos(), "assert.as.identifier");
- Name name = S.name();
- S.nextToken();
+ warning(token.pos, "assert.as.identifier");
+ Name name = token.name();
+ nextToken();
return name;
}
- } else if (S.token() == ENUM) {
+ } else if (token.kind == ENUM) {
if (allowEnums) {
- error(S.pos(), "enum.as.identifier");
- S.nextToken();
+ error(token.pos, "enum.as.identifier");
+ nextToken();
return names.error;
} else {
- warning(S.pos(), "enum.as.identifier");
- Name name = S.name();
- S.nextToken();
+ warning(token.pos, "enum.as.identifier");
+ Name name = token.name();
+ nextToken();
return name;
}
} else {
@@ -471,17 +477,17 @@
* Qualident = Ident { DOT Ident }
*/
public JCExpression qualident() {
- JCExpression t = toP(F.at(S.pos()).Ident(ident()));
- while (S.token() == DOT) {
- int pos = S.pos();
- S.nextToken();
+ JCExpression t = toP(F.at(token.pos).Ident(ident()));
+ while (token.kind == DOT) {
+ int pos = token.pos;
+ nextToken();
t = toP(F.at(pos).Select(t, ident()));
}
return t;
}
JCExpression literal(Name prefix) {
- return literal(prefix, S.pos());
+ return literal(prefix, token.pos);
}
/**
@@ -498,27 +504,29 @@
*/
JCExpression literal(Name prefix, int pos) {
JCExpression t = errorTree;
- switch (S.token()) {
+ switch (token.kind) {
case INTLITERAL:
try {
t = F.at(pos).Literal(
TypeTags.INT,
- Convert.string2int(strval(prefix), S.radix()));
+ Convert.string2int(strval(prefix), token.radix()));
} catch (NumberFormatException ex) {
- error(S.pos(), "int.number.too.large", strval(prefix));
+ error(token.pos, "int.number.too.large", strval(prefix));
}
break;
case LONGLITERAL:
try {
t = F.at(pos).Literal(
TypeTags.LONG,
- new Long(Convert.string2long(strval(prefix), S.radix())));
+ new Long(Convert.string2long(strval(prefix), token.radix())));
} catch (NumberFormatException ex) {
- error(S.pos(), "int.number.too.large", strval(prefix));
+ error(token.pos, "int.number.too.large", strval(prefix));
}
break;
case FLOATLITERAL: {
- String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
+ String proper = token.radix() == 16 ?
+ ("0x"+ token.stringVal()) :
+ token.stringVal();
Float n;
try {
n = Float.valueOf(proper);
@@ -527,15 +535,17 @@
n = Float.NaN;
}
if (n.floatValue() == 0.0f && !isZero(proper))
- error(S.pos(), "fp.number.too.small");
+ error(token.pos, "fp.number.too.small");
else if (n.floatValue() == Float.POSITIVE_INFINITY)
- error(S.pos(), "fp.number.too.large");
+ error(token.pos, "fp.number.too.large");
else
t = F.at(pos).Literal(TypeTags.FLOAT, n);
break;
}
case DOUBLELITERAL: {
- String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
+ String proper = token.radix() == 16 ?
+ ("0x"+ token.stringVal()) :
+ token.stringVal();
Double n;
try {
n = Double.valueOf(proper);
@@ -544,9 +554,9 @@
n = Double.NaN;
}
if (n.doubleValue() == 0.0d && !isZero(proper))
- error(S.pos(), "fp.number.too.small");
+ error(token.pos, "fp.number.too.small");
else if (n.doubleValue() == Double.POSITIVE_INFINITY)
- error(S.pos(), "fp.number.too.large");
+ error(token.pos, "fp.number.too.large");
else
t = F.at(pos).Literal(TypeTags.DOUBLE, n);
break;
@@ -554,17 +564,17 @@
case CHARLITERAL:
t = F.at(pos).Literal(
TypeTags.CHAR,
- S.stringVal().charAt(0) + 0);
+ token.stringVal().charAt(0) + 0);
break;
case STRINGLITERAL:
t = F.at(pos).Literal(
TypeTags.CLASS,
- S.stringVal());
+ token.stringVal());
break;
case TRUE: case FALSE:
t = F.at(pos).Literal(
TypeTags.BOOLEAN,
- (S.token() == TRUE ? 1 : 0));
+ (token.kind == TRUE ? 1 : 0));
break;
case NULL:
t = F.at(pos).Literal(
@@ -576,8 +586,8 @@
}
if (t == errorTree)
t = F.at(pos).Erroneous();
- storeEnd(t, S.endPos());
- S.nextToken();
+ storeEnd(t, token.endPos);
+ nextToken();
return t;
}
//where
@@ -590,7 +600,7 @@
}
String strval(Name prefix) {
- String s = S.stringVal();
+ String s = token.stringVal();
return prefix.isEmpty() ? s : prefix + s;
}
@@ -627,17 +637,17 @@
JCExpression term() {
JCExpression t = term1();
if ((mode & EXPR) != 0 &&
- S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
+ token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
return termRest(t);
else
return t;
}
JCExpression termRest(JCExpression t) {
- switch (S.token()) {
+ switch (token.kind) {
case EQ: {
- int pos = S.pos();
- S.nextToken();
+ int pos = token.pos;
+ nextToken();
mode = EXPR;
JCExpression t1 = term();
return toP(F.at(pos).Assign(t, t1));
@@ -653,12 +663,12 @@
case LTLTEQ:
case GTGTEQ:
case GTGTGTEQ:
- int pos = S.pos();
- Token token = S.token();
- S.nextToken();
+ int pos = token.pos;
+ TokenKind tk = token.kind;
+ nextToken();
mode = EXPR;
JCExpression t1 = term();
- return F.at(pos).Assignop(optag(token), t, t1);
+ return F.at(pos).Assignop(optag(tk), t, t1);
default:
return t;
}
@@ -670,7 +680,7 @@
*/
JCExpression term1() {
JCExpression t = term2();
- if ((mode & EXPR) != 0 && S.token() == QUES) {
+ if ((mode & EXPR) != 0 && token.kind == QUES) {
mode = EXPR;
return term1Rest(t);
} else {
@@ -681,9 +691,9 @@
/** Expression1Rest = ["?" Expression ":" Expression1]
*/
JCExpression term1Rest(JCExpression t) {
- if (S.token() == QUES) {
- int pos = S.pos();
- S.nextToken();
+ if (token.kind == QUES) {
+ int pos = token.pos;
+ nextToken();
JCExpression t1 = term();
accept(COLON);
JCExpression t2 = term1();
@@ -699,7 +709,7 @@
*/
JCExpression term2() {
JCExpression t = term3();
- if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
+ if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
mode = EXPR;
return term2Rest(t, TreeInfo.orPrec);
} else {
@@ -725,28 +735,23 @@
JCExpression[] odStack = newOdStack();
List<Token[]> savedOp = opStackSupply.elems;
Token[] opStack = newOpStack();
- List<int[]> savedPos = posStackSupply.elems;
- int[] posStack = newPosStack();
+
// optimization, was odStack = new Tree[...]; opStack = new Tree[...];
int top = 0;
odStack[0] = t;
- int startPos = S.pos();
- Token topOp = ERROR;
- int topOpPos = Position.NOPOS;
- while (prec(S.token()) >= minprec) {
- posStack[top] = topOpPos;
+ int startPos = token.pos;
+ Token topOp = Tokens.DUMMY;
+ while (prec(token.kind) >= minprec) {
opStack[top] = topOp;
top++;
- topOp = S.token();
- topOpPos = S.pos();
- S.nextToken();
- odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
- while (top > 0 && prec(topOp) >= prec(S.token())) {
- odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
+ topOp = token;
+ nextToken();
+ odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
+ while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
+ odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
odStack[top]);
top--;
topOp = opStack[top];
- topOpPos = posStack[top];
}
}
Assert.check(top == 0);
@@ -761,14 +766,13 @@
odStackSupply.elems = savedOd; // optimization
opStackSupply.elems = savedOp; // optimization
- posStackSupply.elems = savedPos; // optimization
return t;
}
//where
/** Construct a binary or type test node.
*/
private JCExpression makeOp(int pos,
- Token topOp,
+ TokenKind topOp,
JCExpression od1,
JCExpression od2)
{
@@ -817,7 +821,6 @@
*/
ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
- ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
private JCExpression[] newOdStack() {
if (odStackSupply.elems == odStackSupply.last)
@@ -835,14 +838,6 @@
return opStack;
}
- private int[] newPosStack() {
- if (posStackSupply.elems == posStackSupply.last)
- posStackSupply.append(new int[infixPrecedenceLevels + 1]);
- int[] posStack = posStackSupply.elems.head;
- posStackSupply.elems = posStackSupply.elems.tail;
- return posStack;
- }
-
/** Expression3 = PrefixOp Expression3
* | "(" Expr | TypeNoParams ")" Expression3
* | Primary {Selector} {PostfixOp}
@@ -871,10 +866,10 @@
* SuperSuffix = Arguments | "." Ident [Arguments]
*/
protected JCExpression term3() {
- int pos = S.pos();
+ int pos = token.pos;
JCExpression t;
List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
- switch (S.token()) {
+ switch (token.kind) {
case QUES:
if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
mode = TYPE;
@@ -883,49 +878,49 @@
return illegal();
case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
if (typeArgs == null && (mode & EXPR) != 0) {
- Token token = S.token();
- S.nextToken();
+ TokenKind tk = token.kind;
+ nextToken();
mode = EXPR;
- if (token == SUB &&
- (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
- S.radix() == 10) {
+ if (tk == SUB &&
+ (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
+ token.radix() == 10) {
mode = EXPR;
t = literal(names.hyphen, pos);
} else {
t = term3();
- return F.at(pos).Unary(unoptag(token), t);
+ return F.at(pos).Unary(unoptag(tk), t);
}
} else return illegal();
break;
case LPAREN:
if (typeArgs == null && (mode & EXPR) != 0) {
- S.nextToken();
+ nextToken();
mode = EXPR | TYPE | NOPARAMS;
t = term3();
- if ((mode & TYPE) != 0 && S.token() == LT) {
+ if ((mode & TYPE) != 0 && token.kind == LT) {
// Could be a cast to a parameterized type
int op = JCTree.LT;
- int pos1 = S.pos();
- S.nextToken();
+ int pos1 = token.pos;
+ nextToken();
mode &= (EXPR | TYPE);
mode |= TYPEARG;
JCExpression t1 = term3();
if ((mode & TYPE) != 0 &&
- (S.token() == COMMA || S.token() == GT)) {
+ (token.kind == COMMA || token.kind == GT)) {
mode = TYPE;
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
args.append(t1);
- while (S.token() == COMMA) {
- S.nextToken();
+ while (token.kind == COMMA) {
+ nextToken();
args.append(typeArgument());
}
accept(GT);
t = toP(F.at(pos1).TypeApply(t, args.toList()));
checkGenerics();
- while (S.token() == DOT) {
- S.nextToken();
+ while (token.kind == DOT) {
+ nextToken();
mode = TYPE;
- t = toP(F.at(S.pos()).Select(t, ident()));
+ t = toP(F.at(token.pos).Select(t, ident()));
t = typeArgumentsOpt(t);
}
t = bracketsOpt(toP(t));
@@ -948,7 +943,7 @@
JCExpression t1 = term3();
return F.at(pos).TypeCast(t, t1);
} else if ((lastmode & TYPE) != 0) {
- switch (S.token()) {
+ switch (token.kind) {
/*case PLUSPLUS: case SUBSUB: */
case BANG: case TILDE:
case LPAREN: case THIS: case SUPER:
@@ -969,7 +964,7 @@
if ((mode & EXPR) != 0) {
mode = EXPR;
t = to(F.at(pos).Ident(names._this));
- S.nextToken();
+ nextToken();
if (typeArgs == null)
t = argumentsOpt(null, t);
else
@@ -997,22 +992,22 @@
if (typeArgs != null) return illegal();
if ((mode & EXPR) != 0) {
mode = EXPR;
- S.nextToken();
- if (S.token() == LT) typeArgs = typeArguments(false);
+ nextToken();
+ if (token.kind == LT) typeArgs = typeArguments(false);
t = creator(pos, typeArgs);
typeArgs = null;
} else return illegal();
break;
case IDENTIFIER: case ASSERT: case ENUM:
if (typeArgs != null) return illegal();
- t = toP(F.at(S.pos()).Ident(ident()));
+ t = toP(F.at(token.pos).Ident(ident()));
loop: while (true) {
- pos = S.pos();
- switch (S.token()) {
+ pos = token.pos;
+ switch (token.kind) {
case LBRACKET:
- S.nextToken();
- if (S.token() == RBRACKET) {
- S.nextToken();
+ nextToken();
+ if (token.kind == RBRACKET) {
+ nextToken();
t = bracketsOpt(t);
t = toP(F.at(pos).TypeArray(t));
t = bracketsSuffix(t);
@@ -1033,24 +1028,24 @@
}
break loop;
case DOT:
- S.nextToken();
+ nextToken();
int oldmode = mode;
mode &= ~NOPARAMS;
typeArgs = typeArgumentsOpt(EXPR);
mode = oldmode;
if ((mode & EXPR) != 0) {
- switch (S.token()) {
+ switch (token.kind) {
case CLASS:
if (typeArgs != null) return illegal();
mode = EXPR;
t = to(F.at(pos).Select(t, names._class));
- S.nextToken();
+ nextToken();
break loop;
case THIS:
if (typeArgs != null) return illegal();
mode = EXPR;
t = to(F.at(pos).Select(t, names._this));
- S.nextToken();
+ nextToken();
break loop;
case SUPER:
mode = EXPR;
@@ -1061,9 +1056,9 @@
case NEW:
if (typeArgs != null) return illegal();
mode = EXPR;
- int pos1 = S.pos();
- S.nextToken();
- if (S.token() == LT) typeArgs = typeArguments(false);
+ int pos1 = token.pos;
+ nextToken();
+ if (token.kind == LT) typeArgs = typeArguments(false);
t = innerCreator(pos1, typeArgs, t);
typeArgs = null;
break loop;
@@ -1087,8 +1082,8 @@
case VOID:
if (typeArgs != null) illegal();
if ((mode & EXPR) != 0) {
- S.nextToken();
- if (S.token() == DOT) {
+ nextToken();
+ if (token.kind == DOT) {
JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
t = bracketsSuffix(ti);
} else {
@@ -1099,7 +1094,7 @@
// a void type (like other primitive types) to the next phase.
// The error will be reported in Attr.attribTypes or Attr.visitApply.
JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
- S.nextToken();
+ nextToken();
return ti;
//return illegal();
}
@@ -1109,14 +1104,14 @@
}
if (typeArgs != null) illegal();
while (true) {
- int pos1 = S.pos();
- if (S.token() == LBRACKET) {
- S.nextToken();
+ int pos1 = token.pos;
+ if (token.kind == LBRACKET) {
+ nextToken();
if ((mode & TYPE) != 0) {
int oldmode = mode;
mode = TYPE;
- if (S.token() == RBRACKET) {
- S.nextToken();
+ if (token.kind == RBRACKET) {
+ nextToken();
t = bracketsOpt(t);
t = toP(F.at(pos1).TypeArray(t));
return t;
@@ -1129,21 +1124,21 @@
t = to(F.at(pos1).Indexed(t, t1));
}
accept(RBRACKET);
- } else if (S.token() == DOT) {
- S.nextToken();
+ } else if (token.kind == DOT) {
+ nextToken();
typeArgs = typeArgumentsOpt(EXPR);
- if (S.token() == SUPER && (mode & EXPR) != 0) {
+ if (token.kind == SUPER && (mode & EXPR) != 0) {
mode = EXPR;
t = to(F.at(pos1).Select(t, names._super));
- S.nextToken();
+ nextToken();
t = arguments(typeArgs, t);
typeArgs = null;
- } else if (S.token() == NEW && (mode & EXPR) != 0) {
+ } else if (token.kind == NEW && (mode & EXPR) != 0) {
if (typeArgs != null) return illegal();
mode = EXPR;
- int pos2 = S.pos();
- S.nextToken();
- if (S.token() == LT) typeArgs = typeArguments(false);
+ int pos2 = token.pos;
+ nextToken();
+ if (token.kind == LT) typeArgs = typeArguments(false);
t = innerCreator(pos2, typeArgs, t);
typeArgs = null;
} else {
@@ -1155,11 +1150,11 @@
break;
}
}
- while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
+ while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
mode = EXPR;
- t = to(F.at(S.pos()).Unary(
- S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
- S.nextToken();
+ t = to(F.at(token.pos).Unary(
+ token.kind == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
+ nextToken();
}
return toP(t);
}
@@ -1167,13 +1162,13 @@
/** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
*/
JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
- S.nextToken();
- if (S.token() == LPAREN || typeArgs != null) {
+ nextToken();
+ if (token.kind == LPAREN || typeArgs != null) {
t = arguments(typeArgs, t);
} else {
- int pos = S.pos();
+ int pos = token.pos;
accept(DOT);
- typeArgs = (S.token() == LT) ? typeArguments(false) : null;
+ typeArgs = (token.kind == LT) ? typeArguments(false) : null;
t = toP(F.at(pos).Select(t, ident()));
t = argumentsOpt(typeArgs, t);
}
@@ -1183,15 +1178,15 @@
/** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
*/
JCPrimitiveTypeTree basicType() {
- JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
- S.nextToken();
+ JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
+ nextToken();
return t;
}
/** ArgumentsOpt = [ Arguments ]
*/
JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
- if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
+ if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
mode = EXPR;
return arguments(typeArgs, t);
} else {
@@ -1203,24 +1198,24 @@
*/
List<JCExpression> arguments() {
ListBuffer<JCExpression> args = lb();
- if (S.token() == LPAREN) {
- S.nextToken();
- if (S.token() != RPAREN) {
+ if (token.kind == LPAREN) {
+ nextToken();
+ if (token.kind != RPAREN) {
args.append(parseExpression());
- while (S.token() == COMMA) {
- S.nextToken();
+ while (token.kind == COMMA) {
+ nextToken();
args.append(parseExpression());
}
}
accept(RPAREN);
} else {
- syntaxError(S.pos(), "expected", LPAREN);
+ syntaxError(token.pos, "expected", LPAREN);
}
return args.toList();
}
JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
- int pos = S.pos();
+ int pos = token.pos;
List<JCExpression> args = arguments();
return toP(F.at(pos).Apply(typeArgs, t, args));
}
@@ -1228,7 +1223,7 @@
/** TypeArgumentsOpt = [ TypeArguments ]
*/
JCExpression typeArgumentsOpt(JCExpression t) {
- if (S.token() == LT &&
+ if (token.kind == LT &&
(mode & TYPE) != 0 &&
(mode & NOPARAMS) == 0) {
mode = TYPE;
@@ -1243,7 +1238,7 @@
}
List<JCExpression> typeArgumentsOpt(int useMode) {
- if (S.token() == LT) {
+ if (token.kind == LT) {
checkGenerics();
if ((mode & useMode) == 0 ||
(mode & NOPARAMS) != 0) {
@@ -1258,47 +1253,37 @@
/** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
*/
List<JCExpression> typeArguments(boolean diamondAllowed) {
- if (S.token() == LT) {
- S.nextToken();
- if (S.token() == GT && diamondAllowed) {
+ if (token.kind == LT) {
+ nextToken();
+ if (token.kind == GT && diamondAllowed) {
checkDiamond();
mode |= DIAMOND;
- S.nextToken();
+ nextToken();
return List.nil();
} else {
ListBuffer<JCExpression> args = ListBuffer.lb();
args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
- while (S.token() == COMMA) {
- S.nextToken();
+ while (token.kind == COMMA) {
+ nextToken();
args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
}
- switch (S.token()) {
- case GTGTGTEQ:
- S.token(GTGTEQ);
- break;
- case GTGTEQ:
- S.token(GTEQ);
- break;
- case GTEQ:
- S.token(EQ);
- break;
- case GTGTGT:
- S.token(GTGT);
- break;
- case GTGT:
- S.token(GT);
+ switch (token.kind) {
+
+ case GTGTGTEQ: case GTGTEQ: case GTEQ:
+ case GTGTGT: case GTGT:
+ token = S.split();
break;
case GT:
- S.nextToken();
+ nextToken();
break;
default:
- args.append(syntaxError(S.pos(), "expected", GT));
+ args.append(syntaxError(token.pos, "expected", GT));
break;
}
return args.toList();
}
} else {
- return List.<JCExpression>of(syntaxError(S.pos(), "expected", LT));
+ return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
}
}
@@ -1308,24 +1293,24 @@
* | "?" SUPER Type
*/
JCExpression typeArgument() {
- if (S.token() != QUES) return parseType();
- int pos = S.pos();
- S.nextToken();
- if (S.token() == EXTENDS) {
+ if (token.kind != QUES) return parseType();
+ int pos = token.pos;
+ nextToken();
+ if (token.kind == EXTENDS) {
TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
- S.nextToken();
+ nextToken();
JCExpression bound = parseType();
return F.at(pos).Wildcard(t, bound);
- } else if (S.token() == SUPER) {
+ } else if (token.kind == SUPER) {
TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
- S.nextToken();
+ nextToken();
JCExpression bound = parseType();
return F.at(pos).Wildcard(t, bound);
- } else if (S.token() == IDENTIFIER) {
+ } else if (token.kind == IDENTIFIER) {
//error recovery
TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
JCExpression wc = toP(F.at(pos).Wildcard(t, null));
- JCIdent id = toP(F.at(S.pos()).Ident(ident()));
+ JCIdent id = toP(F.at(token.pos).Ident(ident()));
JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
return err;
@@ -1336,7 +1321,7 @@
}
JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
- int pos = S.pos();
+ int pos = token.pos;
List<JCExpression> args = typeArguments(diamondAllowed);
return toP(F.at(pos).TypeApply(t, args));
}
@@ -1344,9 +1329,9 @@
/** BracketsOpt = {"[" "]"}
*/
private JCExpression bracketsOpt(JCExpression t) {
- if (S.token() == LBRACKET) {
- int pos = S.pos();
- S.nextToken();
+ if (token.kind == LBRACKET) {
+ int pos = token.pos;
+ nextToken();
t = bracketsOptCont(t, pos);
F.at(pos);
}
@@ -1363,17 +1348,17 @@
* BracketsSuffixType =
*/
JCExpression bracketsSuffix(JCExpression t) {
- if ((mode & EXPR) != 0 && S.token() == DOT) {
+ if ((mode & EXPR) != 0 && token.kind == DOT) {
mode = EXPR;
- int pos = S.pos();
- S.nextToken();
+ int pos = token.pos;
+ nextToken();
accept(CLASS);
- if (S.pos() == errorEndPos) {
+ if (token.pos == errorEndPos) {
// error recovery
Name name = null;
- if (S.token() == IDENTIFIER) {
- name = S.name();
- S.nextToken();
+ if (token.kind == IDENTIFIER) {
+ name = token.name();
+ nextToken();
} else {
name = names.error;
}
@@ -1384,7 +1369,7 @@
} else if ((mode & TYPE) != 0) {
mode = TYPE;
} else {
- syntaxError(S.pos(), "dot.class.expected");
+ syntaxError(token.pos, "dot.class.expected");
}
return t;
}
@@ -1392,7 +1377,7 @@
/** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
*/
JCExpression creator(int newpos, List<JCExpression> typeArgs) {
- switch (S.token()) {
+ switch (token.kind) {
case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
case DOUBLE: case BOOLEAN:
if (typeArgs == null)
@@ -1405,29 +1390,29 @@
mode = TYPE;
boolean diamondFound = false;
int lastTypeargsPos = -1;
- if (S.token() == LT) {
+ if (token.kind == LT) {
checkGenerics();
- lastTypeargsPos = S.pos();
+ lastTypeargsPos = token.pos;
t = typeArguments(t, true);
diamondFound = (mode & DIAMOND) != 0;
}
- while (S.token() == DOT) {
+ while (token.kind == DOT) {
if (diamondFound) {
//cannot select after a diamond
illegal();
}
- int pos = S.pos();
- S.nextToken();
+ int pos = token.pos;
+ nextToken();
t = toP(F.at(pos).Select(t, ident()));
- if (S.token() == LT) {
- lastTypeargsPos = S.pos();
+ if (token.kind == LT) {
+ lastTypeargsPos = token.pos;
checkGenerics();
t = typeArguments(t, true);
diamondFound = (mode & DIAMOND) != 0;
}
}
mode = oldmode;
- if (S.token() == LBRACKET) {
+ if (token.kind == LBRACKET) {
JCExpression e = arrayCreatorRest(newpos, t);
if (diamondFound) {
reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
@@ -1441,17 +1426,17 @@
// modified to improve error recovery.
pos = typeArgs.head.pos;
}
- setErrorEndPos(S.prevEndPos());
+ setErrorEndPos(S.prevToken().endPos);
JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
reportSyntaxError(err, "cannot.create.array.with.type.arguments");
return toP(err);
}
return e;
- } else if (S.token() == LPAREN) {
+ } else if (token.kind == LPAREN) {
return classCreatorRest(newpos, null, typeArgs, t);
} else {
- setErrorEndPos(S.pos());
- reportSyntaxError(S.pos(), "expected2", LPAREN, LBRACKET);
+ setErrorEndPos(token.pos);
+ reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
}
@@ -1460,8 +1445,8 @@
/** InnerCreator = Ident [TypeArguments] ClassCreatorRest
*/
JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
- JCExpression t = toP(F.at(S.pos()).Ident(ident()));
- if (S.token() == LT) {
+ JCExpression t = toP(F.at(token.pos).Ident(ident()));
+ if (token.kind == LT) {
int oldmode = mode;
checkGenerics();
t = typeArguments(t, true);
@@ -1475,23 +1460,23 @@
*/
JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
accept(LBRACKET);
- if (S.token() == RBRACKET) {
+ if (token.kind == RBRACKET) {
accept(RBRACKET);
elemtype = bracketsOpt(elemtype);
- if (S.token() == LBRACE) {
+ if (token.kind == LBRACE) {
return arrayInitializer(newpos, elemtype);
} else {
JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
- return syntaxError(S.pos(), List.<JCTree>of(t), "array.dimension.missing");
+ return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
}
} else {
ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
dims.append(parseExpression());
accept(RBRACKET);
- while (S.token() == LBRACKET) {
- int pos = S.pos();
- S.nextToken();
- if (S.token() == RBRACKET) {
+ while (token.kind == LBRACKET) {
+ int pos = token.pos;
+ nextToken();
+ if (token.kind == RBRACKET) {
elemtype = bracketsOptCont(elemtype, pos);
} else {
dims.append(parseExpression());
@@ -1511,8 +1496,8 @@
{
List<JCExpression> args = arguments();
JCClassDecl body = null;
- if (S.token() == LBRACE) {
- int pos = S.pos();
+ if (token.kind == LBRACE) {
+ int pos = token.pos;
List<JCTree> defs = classOrInterfaceBody(names.empty, false);
JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
body = toP(F.at(pos).AnonymousClassDef(mods, defs));
@@ -1525,13 +1510,13 @@
JCExpression arrayInitializer(int newpos, JCExpression t) {
accept(LBRACE);
ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
- if (S.token() == COMMA) {
- S.nextToken();
- } else if (S.token() != RBRACE) {
+ if (token.kind == COMMA) {
+ nextToken();
+ } else if (token.kind != RBRACE) {
elems.append(variableInitializer());
- while (S.token() == COMMA) {
- S.nextToken();
- if (S.token() == RBRACE) break;
+ while (token.kind == COMMA) {
+ nextToken();
+ if (token.kind == RBRACE) break;
elems.append(variableInitializer());
}
}
@@ -1542,7 +1527,7 @@
/** VariableInitializer = ArrayInitializer | Expression
*/
public JCExpression variableInitializer() {
- return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
+ return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
}
/** ParExpression = "(" Expression ")"
@@ -1560,19 +1545,19 @@
accept(LBRACE);
List<JCStatement> stats = blockStatements();
JCBlock t = F.at(pos).Block(flags, stats);
- while (S.token() == CASE || S.token() == DEFAULT) {
- syntaxError("orphaned", S.token());
+ while (token.kind == CASE || token.kind == DEFAULT) {
+ syntaxError("orphaned", token.kind);
switchBlockStatementGroups();
}
// the Block node has a field "endpos" for first char of last token, which is
// usually but not necessarily the last char of the last token.
- t.endpos = S.pos();
+ t.endpos = token.pos;
accept(RBRACE);
return toP(t);
}
public JCBlock block() {
- return block(S.pos(), 0);
+ return block(token.pos, 0);
}
/** BlockStatements = { BlockStatement }
@@ -1588,8 +1573,8 @@
int lastErrPos = -1;
ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
while (true) {
- int pos = S.pos();
- switch (S.token()) {
+ int pos = token.pos;
+ switch (token.kind) {
case RBRACE: case CASE: case DEFAULT: case EOF:
return stats.toList();
case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
@@ -1599,64 +1584,63 @@
break;
case MONKEYS_AT:
case FINAL: {
- String dc = S.docComment();
+ String dc = token.docComment;
JCModifiers mods = modifiersOpt();
- if (S.token() == INTERFACE ||
- S.token() == CLASS ||
- allowEnums && S.token() == ENUM) {
+ if (token.kind == INTERFACE ||
+ token.kind == CLASS ||
+ allowEnums && token.kind == ENUM) {
stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
} else {
JCExpression t = parseType();
stats.appendList(variableDeclarators(mods, t,
new ListBuffer<JCStatement>()));
// A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
- storeEnd(stats.elems.last(), S.endPos());
+ storeEnd(stats.elems.last(), token.endPos);
accept(SEMI);
}
break;
}
case ABSTRACT: case STRICTFP: {
- String dc = S.docComment();
+ String dc = token.docComment;
JCModifiers mods = modifiersOpt();
stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
break;
}
case INTERFACE:
case CLASS:
- stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
- S.docComment()));
+ String dc = token.docComment;
+ stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
break;
case ENUM:
case ASSERT:
- if (allowEnums && S.token() == ENUM) {
- error(S.pos(), "local.enum");
- stats.
- append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
- S.docComment()));
+ if (allowEnums && token.kind == ENUM) {
+ error(token.pos, "local.enum");
+ dc = token.docComment;
+ stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
break;
- } else if (allowAsserts && S.token() == ASSERT) {
+ } else if (allowAsserts && token.kind == ASSERT) {
stats.append(parseStatement());
break;
}
/* fall through to default */
default:
- Name name = S.name();
+ Token prevToken = token;
JCExpression t = term(EXPR | TYPE);
- if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
- S.nextToken();
+ if (token.kind == COLON && t.getTag() == JCTree.IDENT) {
+ nextToken();
JCStatement stat = parseStatement();
- stats.append(F.at(pos).Labelled(name, stat));
+ stats.append(F.at(pos).Labelled(prevToken.name(), stat));
} else if ((lastmode & TYPE) != 0 &&
- (S.token() == IDENTIFIER ||
- S.token() == ASSERT ||
- S.token() == ENUM)) {
- pos = S.pos();
+ (token.kind == IDENTIFIER ||
+ token.kind == ASSERT ||
+ token.kind == ENUM)) {
+ pos = token.pos;
JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
F.at(pos);
stats.appendList(variableDeclarators(mods, t,
new ListBuffer<JCStatement>()));
// A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
- storeEnd(stats.elems.last(), S.endPos());
+ storeEnd(stats.elems.last(), token.endPos);
accept(SEMI);
} else {
// This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
@@ -1666,15 +1650,12 @@
}
// error recovery
- if (S.pos() == lastErrPos)
+ if (token.pos == lastErrPos)
return stats.toList();
- if (S.pos() <= errorEndPos) {
+ if (token.pos <= errorEndPos) {
skip(false, true, true, true);
- lastErrPos = S.pos();
+ lastErrPos = token.pos;
}
-
- // ensure no dangling /** @deprecated */ active
- S.resetDeprecatedFlag();
}
}
@@ -1700,29 +1681,29 @@
*/
@SuppressWarnings("fallthrough")
public JCStatement parseStatement() {
- int pos = S.pos();
- switch (S.token()) {
+ int pos = token.pos;
+ switch (token.kind) {
case LBRACE:
return block();
case IF: {
- S.nextToken();
+ nextToken();
JCExpression cond = parExpression();
JCStatement thenpart = parseStatement();
JCStatement elsepart = null;
- if (S.token() == ELSE) {
- S.nextToken();
+ if (token.kind == ELSE) {
+ nextToken();
elsepart = parseStatement();
}
return F.at(pos).If(cond, thenpart, elsepart);
}
case FOR: {
- S.nextToken();
+ nextToken();
accept(LPAREN);
- List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
+ List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
if (inits.length() == 1 &&
inits.head.getTag() == JCTree.VARDEF &&
((JCVariableDecl) inits.head).init == null &&
- S.token() == COLON) {
+ token.kind == COLON) {
checkForeach();
JCVariableDecl var = (JCVariableDecl)inits.head;
accept(COLON);
@@ -1732,22 +1713,22 @@
return F.at(pos).ForeachLoop(var, expr, body);
} else {
accept(SEMI);
- JCExpression cond = S.token() == SEMI ? null : parseExpression();
+ JCExpression cond = token.kind == SEMI ? null : parseExpression();
accept(SEMI);
- List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
+ List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
accept(RPAREN);
JCStatement body = parseStatement();
return F.at(pos).ForLoop(inits, cond, steps, body);
}
}
case WHILE: {
- S.nextToken();
+ nextToken();
JCExpression cond = parExpression();
JCStatement body = parseStatement();
return F.at(pos).WhileLoop(cond, body);
}
case DO: {
- S.nextToken();
+ nextToken();
JCStatement body = parseStatement();
accept(WHILE);
JCExpression cond = parExpression();
@@ -1756,21 +1737,21 @@
return t;
}
case TRY: {
- S.nextToken();
+ nextToken();
List<JCTree> resources = List.<JCTree>nil();
- if (S.token() == LPAREN) {
+ if (token.kind == LPAREN) {
checkTryWithResources();
- S.nextToken();
+ nextToken();
resources = resources();
accept(RPAREN);
}
JCBlock body = block();
ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
JCBlock finalizer = null;
- if (S.token() == CATCH || S.token() == FINALLY) {
- while (S.token() == CATCH) catchers.append(catchClause());
- if (S.token() == FINALLY) {
- S.nextToken();
+ if (token.kind == CATCH || token.kind == FINALLY) {
+ while (token.kind == CATCH) catchers.append(catchClause());
+ if (token.kind == FINALLY) {
+ nextToken();
finalizer = block();
}
} else {
@@ -1783,7 +1764,7 @@
return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
}
case SWITCH: {
- S.nextToken();
+ nextToken();
JCExpression selector = parExpression();
accept(LBRACE);
List<JCCase> cases = switchBlockStatementGroups();
@@ -1792,41 +1773,41 @@
return t;
}
case SYNCHRONIZED: {
- S.nextToken();
+ nextToken();
JCExpression lock = parExpression();
JCBlock body = block();
return F.at(pos).Synchronized(lock, body);
}
case RETURN: {
- S.nextToken();
- JCExpression result = S.token() == SEMI ? null : parseExpression();
+ nextToken();
+ JCExpression result = token.kind == SEMI ? null : parseExpression();
JCReturn t = to(F.at(pos).Return(result));
accept(SEMI);
return t;
}
case THROW: {
- S.nextToken();
+ nextToken();
JCExpression exc = parseExpression();
JCThrow t = to(F.at(pos).Throw(exc));
accept(SEMI);
return t;
}
case BREAK: {
- S.nextToken();
- Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+ nextToken();
+ Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
JCBreak t = to(F.at(pos).Break(label));
accept(SEMI);
return t;
}
case CONTINUE: {
- S.nextToken();
- Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+ nextToken();
+ Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
JCContinue t = to(F.at(pos).Continue(label));
accept(SEMI);
return t;
}
case SEMI:
- S.nextToken();
+ nextToken();
return toP(F.at(pos).Skip());
case ELSE:
return toP(F.Exec(syntaxError("else.without.if")));
@@ -1835,12 +1816,12 @@
case CATCH:
return toP(F.Exec(syntaxError("catch.without.try")));
case ASSERT: {
- if (allowAsserts && S.token() == ASSERT) {
- S.nextToken();
+ if (allowAsserts && token.kind == ASSERT) {
+ nextToken();
JCExpression assertion = parseExpression();
JCExpression message = null;
- if (S.token() == COLON) {
- S.nextToken();
+ if (token.kind == COLON) {
+ nextToken();
message = parseExpression();
}
JCAssert t = to(F.at(pos).Assert(assertion, message));
@@ -1851,12 +1832,12 @@
}
case ENUM:
default:
- Name name = S.name();
+ Token prevToken = token;
JCExpression expr = parseExpression();
- if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
- S.nextToken();
+ if (token.kind == COLON && expr.getTag() == JCTree.IDENT) {
+ nextToken();
JCStatement stat = parseStatement();
- return F.at(pos).Labelled(name, stat);
+ return F.at(pos).Labelled(prevToken.name(), stat);
} else {
// This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
@@ -1869,7 +1850,7 @@
/** CatchClause = CATCH "(" FormalParameter ")" Block
*/
protected JCCatch catchClause() {
- int pos = S.pos();
+ int pos = token.pos;
accept(CATCH);
accept(LPAREN);
JCModifiers mods = optFinal(Flags.PARAMETER);
@@ -1886,9 +1867,9 @@
List<JCExpression> catchTypes() {
ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
catchTypes.add(parseType());
- while (S.token() == BAR) {
+ while (token.kind == BAR) {
checkMulticatch();
- S.nextToken();
+ nextToken();
catchTypes.add(qualident());
}
return catchTypes.toList();
@@ -1901,33 +1882,33 @@
List<JCCase> switchBlockStatementGroups() {
ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
while (true) {
- int pos = S.pos();
- switch (S.token()) {
+ int pos = token.pos;
+ switch (token.kind) {
case CASE: {
- S.nextToken();
+ nextToken();
JCExpression pat = parseExpression();
accept(COLON);
List<JCStatement> stats = blockStatements();
JCCase c = F.at(pos).Case(pat, stats);
if (stats.isEmpty())
- storeEnd(c, S.prevEndPos());
+ storeEnd(c, S.prevToken().endPos);
cases.append(c);
break;
}
case DEFAULT: {
- S.nextToken();
+ nextToken();
accept(COLON);
List<JCStatement> stats = blockStatements();
JCCase c = F.at(pos).Case(null, stats);
if (stats.isEmpty())
- storeEnd(c, S.prevEndPos());
+ storeEnd(c, S.prevToken().endPos);
cases.append(c);
break;
}
case RBRACE: case EOF:
return cases.toList();
default:
- S.nextToken(); // to ensure progress
+ nextToken(); // to ensure progress
syntaxError(pos, "expected3",
CASE, DEFAULT, RBRACE);
}
@@ -1941,9 +1922,9 @@
T stats) {
// This Exec is a "StatementExpression"; it subsumes no terminating token
stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
- while (S.token() == COMMA) {
- S.nextToken();
- pos = S.pos();
+ while (token.kind == COMMA) {
+ nextToken();
+ pos = token.pos;
JCExpression t = parseExpression();
// This Exec is a "StatementExpression"; it subsumes no terminating token
stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
@@ -1956,13 +1937,13 @@
*/
List<JCStatement> forInit() {
ListBuffer<JCStatement> stats = lb();
- int pos = S.pos();
- if (S.token() == FINAL || S.token() == MONKEYS_AT) {
+ int pos = token.pos;
+ if (token.kind == FINAL || token.kind == MONKEYS_AT) {
return variableDeclarators(optFinal(0), parseType(), stats).toList();
} else {
JCExpression t = term(EXPR | TYPE);
if ((lastmode & TYPE) != 0 &&
- (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
+ (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM))
return variableDeclarators(modifiersOpt(), t, stats).toList();
else
return moreStatementExpressions(pos, t, stats).toList();
@@ -1972,7 +1953,7 @@
/** ForUpdate = StatementExpression MoreStatementExpressions
*/
List<JCExpressionStatement> forUpdate() {
- return moreStatementExpressions(S.pos(),
+ return moreStatementExpressions(token.pos,
parseExpression(),
new ListBuffer<JCExpressionStatement>()).toList();
}
@@ -1980,11 +1961,11 @@
/** AnnotationsOpt = { '@' Annotation }
*/
List<JCAnnotation> annotationsOpt() {
- if (S.token() != MONKEYS_AT) return List.nil(); // optimization
+ if (token.kind != MONKEYS_AT) return List.nil(); // optimization
ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
- while (S.token() == MONKEYS_AT) {
- int pos = S.pos();
- S.nextToken();
+ while (token.kind == MONKEYS_AT) {
+ int pos = token.pos;
+ nextToken();
buf.append(annotation(pos));
}
return buf.toList();
@@ -2004,21 +1985,20 @@
int pos;
if (partial == null) {
flags = 0;
- pos = S.pos();
+ pos = token.pos;
} else {
flags = partial.flags;
annotations.appendList(partial.annotations);
pos = partial.pos;
}
- if (S.deprecatedFlag()) {
+ if (token.deprecatedFlag) {
flags |= Flags.DEPRECATED;
- S.resetDeprecatedFlag();
}
int lastPos = Position.NOPOS;
loop:
while (true) {
long flag;
- switch (S.token()) {
+ switch (token.kind) {
case PRIVATE : flag = Flags.PRIVATE; break;
case PROTECTED : flag = Flags.PROTECTED; break;
case PUBLIC : flag = Flags.PUBLIC; break;
@@ -2031,15 +2011,15 @@
case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
case STRICTFP : flag = Flags.STRICTFP; break;
case MONKEYS_AT : flag = Flags.ANNOTATION; break;
- case ERROR : flag = 0; S.nextToken(); break;
+ case ERROR : flag = 0; nextToken(); break;
default: break loop;
}
- if ((flags & flag) != 0) error(S.pos(), "repeated.modifier");
- lastPos = S.pos();
- S.nextToken();
+ if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
+ lastPos = token.pos;
+ nextToken();
if (flag == Flags.ANNOTATION) {
checkAnnotations();
- if (S.token() != INTERFACE) {
+ if (token.kind != INTERFACE) {
JCAnnotation ann = annotation(lastPos);
// if first modifier is an annotation, set pos to annotation's.
if (flags == 0 && annotations.isEmpty())
@@ -2051,7 +2031,7 @@
}
flags |= flag;
}
- switch (S.token()) {
+ switch (token.kind) {
case ENUM: flags |= Flags.ENUM; break;
case INTERFACE: flags |= Flags.INTERFACE; break;
default: break;
@@ -2064,7 +2044,7 @@
JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
if (pos != Position.NOPOS)
- storeEnd(mods, S.prevEndPos());
+ storeEnd(mods, S.prevToken().endPos);
return mods;
}
@@ -2077,22 +2057,22 @@
JCTree ident = qualident();
List<JCExpression> fieldValues = annotationFieldValuesOpt();
JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
- storeEnd(ann, S.prevEndPos());
+ storeEnd(ann, S.prevToken().endPos);
return ann;
}
List<JCExpression> annotationFieldValuesOpt() {
- return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
+ return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
}
/** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
List<JCExpression> annotationFieldValues() {
accept(LPAREN);
ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
- if (S.token() != RPAREN) {
+ if (token.kind != RPAREN) {
buf.append(annotationFieldValue());
- while (S.token() == COMMA) {
- S.nextToken();
+ while (token.kind == COMMA) {
+ nextToken();
buf.append(annotationFieldValue());
}
}
@@ -2104,11 +2084,11 @@
* | Identifier "=" AnnotationValue
*/
JCExpression annotationFieldValue() {
- if (S.token() == IDENTIFIER) {
+ if (token.kind == IDENTIFIER) {
mode = EXPR;
JCExpression t1 = term1();
- if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
- int pos = S.pos();
+ if (t1.getTag() == JCTree.IDENT && token.kind == EQ) {
+ int pos = token.pos;
accept(EQ);
JCExpression v = annotationValue();
return toP(F.at(pos).Assign(t1, v));
@@ -2125,20 +2105,20 @@
*/
JCExpression annotationValue() {
int pos;
- switch (S.token()) {
+ switch (token.kind) {
case MONKEYS_AT:
- pos = S.pos();
- S.nextToken();
+ pos = token.pos;
+ nextToken();
return annotation(pos);
case LBRACE:
- pos = S.pos();
+ pos = token.pos;
accept(LBRACE);
ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
- if (S.token() != RBRACE) {
+ if (token.kind != RBRACE) {
buf.append(annotationValue());
- while (S.token() == COMMA) {
- S.nextToken();
- if (S.token() == RBRACE) break;
+ while (token.kind == COMMA) {
+ nextToken();
+ if (token.kind == RBRACE) break;
buf.append(annotationValue());
}
}
@@ -2156,7 +2136,7 @@
JCExpression type,
T vdefs)
{
- return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
+ return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
}
/** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
@@ -2174,10 +2154,10 @@
T vdefs)
{
vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
- while (S.token() == COMMA) {
+ while (token.kind == COMMA) {
// All but last of multiple declarators subsume a comma
- storeEnd((JCTree)vdefs.elems.last(), S.endPos());
- S.nextToken();
+ storeEnd((JCTree)vdefs.elems.last(), token.endPos);
+ nextToken();
vdefs.append(variableDeclarator(mods, type, reqInit, dc));
}
return vdefs;
@@ -2187,7 +2167,7 @@
* ConstantDeclarator = Ident ConstantDeclaratorRest
*/
JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
- return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
+ return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
}
/** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
@@ -2200,11 +2180,11 @@
boolean reqInit, String dc) {
type = bracketsOpt(type);
JCExpression init = null;
- if (S.token() == EQ) {
- S.nextToken();
+ if (token.kind == EQ) {
+ nextToken();
init = variableInitializer();
}
- else if (reqInit) syntaxError(S.pos(), "expected", EQ);
+ else if (reqInit) syntaxError(token.pos, "expected", EQ);
JCVariableDecl result =
toP(F.at(pos).VarDef(mods, name, type, init));
attach(result, dc);
@@ -2214,11 +2194,11 @@
/** VariableDeclaratorId = Ident BracketsOpt
*/
JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
- int pos = S.pos();
+ int pos = token.pos;
Name name = ident();
if ((mods.flags & Flags.VARARGS) != 0 &&
- S.token() == LBRACKET) {
- log.error(S.pos(), "varargs.and.old.array.syntax");
+ token.kind == LBRACKET) {
+ log.error(token.pos, "varargs.and.old.array.syntax");
}
type = bracketsOpt(type);
return toP(F.at(pos).VarDef(mods, name, type, null));
@@ -2229,12 +2209,12 @@
List<JCTree> resources() {
ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
defs.append(resource());
- while (S.token() == SEMI) {
+ while (token.kind == SEMI) {
// All but last of multiple declarators must subsume a semicolon
- storeEnd(defs.elems.last(), S.endPos());
- int semiColonPos = S.pos();
- S.nextToken();
- if (S.token() == RPAREN) { // Optional trailing semicolon
+ storeEnd(defs.elems.last(), token.endPos);
+ int semiColonPos = token.pos;
+ nextToken();
+ if (token.kind == RPAREN) { // Optional trailing semicolon
// after last resource
break;
}
@@ -2248,7 +2228,7 @@
protected JCTree resource() {
JCModifiers optFinal = optFinal(Flags.FINAL);
JCExpression type = parseType();
- int pos = S.pos();
+ int pos = token.pos;
Name ident = ident();
return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
}
@@ -2256,54 +2236,61 @@
/** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
*/
public JCTree.JCCompilationUnit parseCompilationUnit() {
- int pos = S.pos();
+ Token firstToken = token;
JCExpression pid = null;
- String dc = S.docComment();
JCModifiers mods = null;
+ boolean consumedToplevelDoc = false;
+ boolean seenImport = false;
+ boolean seenPackage = false;
List<JCAnnotation> packageAnnotations = List.nil();
- if (S.token() == MONKEYS_AT)
+ if (token.kind == MONKEYS_AT)
mods = modifiersOpt();
- if (S.token() == PACKAGE) {
+ if (token.kind == PACKAGE) {
+ seenPackage = true;
if (mods != null) {
checkNoMods(mods.flags);
packageAnnotations = mods.annotations;
mods = null;
}
- S.nextToken();
+ nextToken();
pid = qualident();
accept(SEMI);
}
ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
boolean checkForImports = true;
- while (S.token() != EOF) {
- if (S.pos() <= errorEndPos) {
+ boolean firstTypeDecl = true;
+ while (token.kind != EOF) {
+ if (token.pos <= errorEndPos) {
// error recovery
skip(checkForImports, false, false, false);
- if (S.token() == EOF)
+ if (token.kind == EOF)
break;
}
- if (checkForImports && mods == null && S.token() == IMPORT) {
+ if (checkForImports && mods == null && token.kind == IMPORT) {
+ seenImport = true;
defs.append(importDeclaration());
} else {
- JCTree def = typeDeclaration(mods);
- if (keepDocComments && dc != null && docComments.get(def) == dc) {
- // If the first type declaration has consumed the first doc
- // comment, then don't use it for the top level comment as well.
- dc = null;
+ String docComment = token.docComment;
+ if (firstTypeDecl && !seenImport && !seenPackage) {
+ docComment = firstToken.docComment;
+ consumedToplevelDoc = true;
}
+ JCTree def = typeDeclaration(mods, docComment);
if (def instanceof JCExpressionStatement)
def = ((JCExpressionStatement)def).expr;
defs.append(def);
if (def instanceof JCClassDecl)
checkForImports = false;
mods = null;
+ firstTypeDecl = false;
}
}
- JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
- attach(toplevel, dc);
+ JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
+ if (!consumedToplevelDoc)
+ attach(toplevel, firstToken.docComment);
if (defs.elems.isEmpty())
- storeEnd(toplevel, S.prevEndPos());
+ storeEnd(toplevel, S.prevToken().endPos);
if (keepDocComments)
toplevel.docComments = docComments;
if (keepLineMap)
@@ -2314,26 +2301,26 @@
/** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
*/
JCTree importDeclaration() {
- int pos = S.pos();
- S.nextToken();
+ int pos = token.pos;
+ nextToken();
boolean importStatic = false;
- if (S.token() == STATIC) {
+ if (token.kind == STATIC) {
checkStaticImports();
importStatic = true;
- S.nextToken();
+ nextToken();
}
- JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
+ JCExpression pid = toP(F.at(token.pos).Ident(ident()));
do {
- int pos1 = S.pos();
+ int pos1 = token.pos;
accept(DOT);
- if (S.token() == STAR) {
+ if (token.kind == STAR) {
pid = to(F.at(pos1).Select(pid, names.asterisk));
- S.nextToken();
+ nextToken();
break;
} else {
pid = toP(F.at(pos1).Select(pid, ident()));
}
- } while (S.token() == DOT);
+ } while (token.kind == DOT);
accept(SEMI);
return toP(F.at(pos).Import(pid, importStatic));
}
@@ -2341,14 +2328,13 @@
/** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
* | ";"
*/
- JCTree typeDeclaration(JCModifiers mods) {
- int pos = S.pos();
- if (mods == null && S.token() == SEMI) {
- S.nextToken();
+ JCTree typeDeclaration(JCModifiers mods, String docComment) {
+ int pos = token.pos;
+ if (mods == null && token.kind == SEMI) {
+ nextToken();
return toP(F.at(pos).Skip());
} else {
- String dc = S.docComment();
- return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
+ return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
}
}
@@ -2358,19 +2344,19 @@
* @param dc The documentation comment for the class, or null.
*/
JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
- if (S.token() == CLASS) {
+ if (token.kind == CLASS) {
return classDeclaration(mods, dc);
- } else if (S.token() == INTERFACE) {
+ } else if (token.kind == INTERFACE) {
return interfaceDeclaration(mods, dc);
} else if (allowEnums) {
- if (S.token() == ENUM) {
+ if (token.kind == ENUM) {
return enumDeclaration(mods, dc);
} else {
- int pos = S.pos();
+ int pos = token.pos;
List<JCTree> errs;
- if (S.token() == IDENTIFIER) {
+ if (token.kind == IDENTIFIER) {
errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
- setErrorEndPos(S.pos());
+ setErrorEndPos(token.pos);
} else {
errs = List.<JCTree>of(mods);
}
@@ -2378,16 +2364,16 @@
CLASS, INTERFACE, ENUM)));
}
} else {
- if (S.token() == ENUM) {
- error(S.pos(), "enums.not.supported.in.source", source.name);
+ if (token.kind == ENUM) {
+ error(token.pos, "enums.not.supported.in.source", source.name);
allowEnums = true;
return enumDeclaration(mods, dc);
}
- int pos = S.pos();
+ int pos = token.pos;
List<JCTree> errs;
- if (S.token() == IDENTIFIER) {
+ if (token.kind == IDENTIFIER) {
errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
- setErrorEndPos(S.pos());
+ setErrorEndPos(token.pos);
} else {
errs = List.<JCTree>of(mods);
}
@@ -2402,20 +2388,20 @@
* @param dc The documentation comment for the class, or null.
*/
JCClassDecl classDeclaration(JCModifiers mods, String dc) {
- int pos = S.pos();
+ int pos = token.pos;
accept(CLASS);
Name name = ident();
List<JCTypeParameter> typarams = typeParametersOpt();
JCExpression extending = null;
- if (S.token() == EXTENDS) {
- S.nextToken();
+ if (token.kind == EXTENDS) {
+ nextToken();
extending = parseType();
}
List<JCExpression> implementing = List.nil();
- if (S.token() == IMPLEMENTS) {
- S.nextToken();
+ if (token.kind == IMPLEMENTS) {
+ nextToken();
implementing = typeList();
}
List<JCTree> defs = classOrInterfaceBody(name, false);
@@ -2431,15 +2417,15 @@
* @param dc The documentation comment for the interface, or null.
*/
JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
- int pos = S.pos();
+ int pos = token.pos;
accept(INTERFACE);
Name name = ident();
List<JCTypeParameter> typarams = typeParametersOpt();
List<JCExpression> extending = List.nil();
- if (S.token() == EXTENDS) {
- S.nextToken();
+ if (token.kind == EXTENDS) {
+ nextToken();
extending = typeList();
}
List<JCTree> defs = classOrInterfaceBody(name, true);
@@ -2454,13 +2440,13 @@
* @param dc The documentation comment for the enum, or null.
*/
JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
- int pos = S.pos();
+ int pos = token.pos;
accept(ENUM);
Name name = ident();
List<JCExpression> implementing = List.nil();
- if (S.token() == IMPLEMENTS) {
- S.nextToken();
+ if (token.kind == IMPLEMENTS) {
+ nextToken();
implementing = typeList();
}
@@ -2479,27 +2465,27 @@
List<JCTree> enumBody(Name enumName) {
accept(LBRACE);
ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
- if (S.token() == COMMA) {
- S.nextToken();
- } else if (S.token() != RBRACE && S.token() != SEMI) {
+ if (token.kind == COMMA) {
+ nextToken();
+ } else if (token.kind != RBRACE && token.kind != SEMI) {
defs.append(enumeratorDeclaration(enumName));
- while (S.token() == COMMA) {
- S.nextToken();
- if (S.token() == RBRACE || S.token() == SEMI) break;
+ while (token.kind == COMMA) {
+ nextToken();
+ if (token.kind == RBRACE || token.kind == SEMI) break;
defs.append(enumeratorDeclaration(enumName));
}
- if (S.token() != SEMI && S.token() != RBRACE) {
- defs.append(syntaxError(S.pos(), "expected3",
+ if (token.kind != SEMI && token.kind != RBRACE) {
+ defs.append(syntaxError(token.pos, "expected3",
COMMA, RBRACE, SEMI));
- S.nextToken();
+ nextToken();
}
}
- if (S.token() == SEMI) {
- S.nextToken();
- while (S.token() != RBRACE && S.token() != EOF) {
+ if (token.kind == SEMI) {
+ nextToken();
+ while (token.kind != RBRACE && token.kind != EOF) {
defs.appendList(classOrInterfaceBodyDeclaration(enumName,
false));
- if (S.pos() <= errorEndPos) {
+ if (token.pos <= errorEndPos) {
// error recovery
skip(false, true, true, false);
}
@@ -2512,23 +2498,22 @@
/** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
*/
JCTree enumeratorDeclaration(Name enumName) {
- String dc = S.docComment();
+ String dc = token.docComment;
int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
- if (S.deprecatedFlag()) {
+ if (token.deprecatedFlag) {
flags |= Flags.DEPRECATED;
- S.resetDeprecatedFlag();
}
- int pos = S.pos();
+ int pos = token.pos;
List<JCAnnotation> annotations = annotationsOpt();
JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
List<JCExpression> typeArgs = typeArgumentsOpt();
- int identPos = S.pos();
+ int identPos = token.pos;
Name name = ident();
- int createPos = S.pos();
- List<JCExpression> args = (S.token() == LPAREN)
+ int createPos = token.pos;
+ List<JCExpression> args = (token.kind == LPAREN)
? arguments() : List.<JCExpression>nil();
JCClassDecl body = null;
- if (S.token() == LBRACE) {
+ if (token.kind == LBRACE) {
JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
List<JCTree> defs = classOrInterfaceBody(names.empty, false);
body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
@@ -2538,7 +2523,7 @@
JCIdent ident = F.at(identPos).Ident(enumName);
JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
if (createPos != identPos)
- storeEnd(create, S.prevEndPos());
+ storeEnd(create, S.prevToken().endPos);
ident = F.at(identPos).Ident(enumName);
JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
attach(result, dc);
@@ -2550,8 +2535,8 @@
List<JCExpression> typeList() {
ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
ts.append(parseType());
- while (S.token() == COMMA) {
- S.nextToken();
+ while (token.kind == COMMA) {
+ nextToken();
ts.append(parseType());
}
return ts.toList();
@@ -2562,16 +2547,16 @@
*/
List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
accept(LBRACE);
- if (S.pos() <= errorEndPos) {
+ if (token.pos <= errorEndPos) {
// error recovery
skip(false, true, false, false);
- if (S.token() == LBRACE)
- S.nextToken();
+ if (token.kind == LBRACE)
+ nextToken();
}
ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
- while (S.token() != RBRACE && S.token() != EOF) {
+ while (token.kind != RBRACE && token.kind != EOF) {
defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
- if (S.pos() <= errorEndPos) {
+ if (token.pos <= errorEndPos) {
// error recovery
skip(false, true, true, false);
}
@@ -2598,23 +2583,23 @@
* ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
*/
protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
- if (S.token() == SEMI) {
- S.nextToken();
+ if (token.kind == SEMI) {
+ nextToken();
return List.<JCTree>nil();
} else {
- String dc = S.docComment();
- int pos = S.pos();
+ String dc = token.docComment;
+ int pos = token.pos;
JCModifiers mods = modifiersOpt();
- if (S.token() == CLASS ||
- S.token() == INTERFACE ||
- allowEnums && S.token() == ENUM) {
+ if (token.kind == CLASS ||
+ token.kind == INTERFACE ||
+ allowEnums && token.kind == ENUM) {
return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
- } else if (S.token() == LBRACE && !isInterface &&
+ } else if (token.kind == LBRACE && !isInterface &&
(mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
mods.annotations.isEmpty()) {
return List.<JCTree>of(block(pos, mods.flags));
} else {
- pos = S.pos();
+ pos = token.pos;
List<JCTypeParameter> typarams = typeParametersOpt();
// if there are type parameters but no modifiers, save the start
// position of the method in the modifiers.
@@ -2622,26 +2607,26 @@
mods.pos = pos;
storeEnd(mods, pos);
}
- Name name = S.name();
- pos = S.pos();
+ Token tk = token;
+ pos = token.pos;
JCExpression type;
- boolean isVoid = S.token() == VOID;
+ boolean isVoid = token.kind == VOID;
if (isVoid) {
type = to(F.at(pos).TypeIdent(TypeTags.VOID));
- S.nextToken();
+ nextToken();
} else {
type = parseType();
}
- if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
- if (isInterface || name != className)
+ if (token.kind == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
+ if (isInterface || tk.name() != className)
error(pos, "invalid.meth.decl.ret.type.req");
return List.of(methodDeclaratorRest(
pos, mods, null, names.init, typarams,
isInterface, true, dc));
} else {
- pos = S.pos();
- name = ident();
- if (S.token() == LPAREN) {
+ pos = token.pos;
+ Name name = ident();
+ if (token.kind == LPAREN) {
return List.of(methodDeclaratorRest(
pos, mods, type, name, typarams,
isInterface, isVoid, dc));
@@ -2649,16 +2634,16 @@
List<JCTree> defs =
variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
new ListBuffer<JCTree>()).toList();
- storeEnd(defs.last(), S.endPos());
+ storeEnd(defs.last(), token.endPos);
accept(SEMI);
return defs;
} else {
- pos = S.pos();
+ pos = token.pos;
List<JCTree> err = isVoid
? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
: null;
- return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
+ return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
}
}
}
@@ -2686,27 +2671,27 @@
List<JCVariableDecl> params = formalParameters();
if (!isVoid) type = bracketsOpt(type);
List<JCExpression> thrown = List.nil();
- if (S.token() == THROWS) {
- S.nextToken();
+ if (token.kind == THROWS) {
+ nextToken();
thrown = qualidentList();
}
JCBlock body = null;
JCExpression defaultValue;
- if (S.token() == LBRACE) {
+ if (token.kind == LBRACE) {
body = block();
defaultValue = null;
} else {
- if (S.token() == DEFAULT) {
+ if (token.kind == DEFAULT) {
accept(DEFAULT);
defaultValue = annotationValue();
} else {
defaultValue = null;
}
accept(SEMI);
- if (S.pos() <= errorEndPos) {
+ if (token.pos <= errorEndPos) {
// error recovery
skip(false, true, false, false);
- if (S.token() == LBRACE) {
+ if (token.kind == LBRACE) {
body = block();
}
}
@@ -2725,8 +2710,8 @@
List<JCExpression> qualidentList() {
ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
ts.append(qualident());
- while (S.token() == COMMA) {
- S.nextToken();
+ while (token.kind == COMMA) {
+ nextToken();
ts.append(qualident());
}
return ts.toList();
@@ -2735,13 +2720,13 @@
/** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
*/
List<JCTypeParameter> typeParametersOpt() {
- if (S.token() == LT) {
+ if (token.kind == LT) {
checkGenerics();
ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
- S.nextToken();
+ nextToken();
typarams.append(typeParameter());
- while (S.token() == COMMA) {
- S.nextToken();
+ while (token.kind == COMMA) {
+ nextToken();
typarams.append(typeParameter());
}
accept(GT);
@@ -2756,14 +2741,14 @@
* TypeVariable = Ident
*/
JCTypeParameter typeParameter() {
- int pos = S.pos();
+ int pos = token.pos;
Name name = ident();
ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
- if (S.token() == EXTENDS) {
- S.nextToken();
+ if (token.kind == EXTENDS) {
+ nextToken();
bounds.append(parseType());
- while (S.token() == AMP) {
- S.nextToken();
+ while (token.kind == AMP) {
+ nextToken();
bounds.append(parseType());
}
}
@@ -2778,10 +2763,10 @@
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
JCVariableDecl lastParam = null;
accept(LPAREN);
- if (S.token() != RPAREN) {
+ if (token.kind != RPAREN) {
params.append(lastParam = formalParameter());
- while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
- S.nextToken();
+ while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
+ nextToken();
params.append(lastParam = formalParameter());
}
}
@@ -2802,11 +2787,11 @@
protected JCVariableDecl formalParameter() {
JCModifiers mods = optFinal(Flags.PARAMETER);
JCExpression type = parseType();
- if (S.token() == ELLIPSIS) {
+ if (token.kind == ELLIPSIS) {
checkVarargs();
mods.flags |= Flags.VARARGS;
- type = to(F.at(S.pos()).TypeArray(type));
- S.nextToken();
+ type = to(F.at(token.pos).TypeArray(type));
+ nextToken();
}
return variableDeclaratorId(mods, type);
}
@@ -2849,7 +2834,7 @@
/** Return precedence of operator represented by token,
* -1 if token is not a binary operator. @see TreeInfo.opPrec
*/
- static int prec(Token token) {
+ static int prec(TokenKind token) {
int oc = optag(token);
return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
}
@@ -2869,7 +2854,7 @@
/** Return operation tag of binary operator represented by token,
* -1 if token is not a binary operator.
*/
- static int optag(Token token) {
+ static int optag(TokenKind token) {
switch (token) {
case BARBAR:
return JCTree.OR;
@@ -2941,7 +2926,7 @@
/** Return operation tag of unary operator represented by token,
* -1 if token is not a binary operator.
*/
- static int unoptag(Token token) {
+ static int unoptag(TokenKind token) {
switch (token) {
case PLUS:
return JCTree.POS;
@@ -2963,7 +2948,7 @@
/** Return type tag of basic type represented by token,
* -1 if token is not a basic type identifier.
*/
- static int typetag(Token token) {
+ static int typetag(TokenKind token) {
switch (token) {
case BYTE:
return TypeTags.BYTE;
@@ -2988,49 +2973,49 @@
void checkGenerics() {
if (!allowGenerics) {
- error(S.pos(), "generics.not.supported.in.source", source.name);
+ error(token.pos, "generics.not.supported.in.source", source.name);
allowGenerics = true;
}
}
void checkVarargs() {
if (!allowVarargs) {
- error(S.pos(), "varargs.not.supported.in.source", source.name);
+ error(token.pos, "varargs.not.supported.in.source", source.name);
allowVarargs = true;
}
}
void checkForeach() {
if (!allowForeach) {
- error(S.pos(), "foreach.not.supported.in.source", source.name);
+ error(token.pos, "foreach.not.supported.in.source", source.name);
allowForeach = true;
}
}
void checkStaticImports() {
if (!allowStaticImport) {
- error(S.pos(), "static.import.not.supported.in.source", source.name);
+ error(token.pos, "static.import.not.supported.in.source", source.name);
allowStaticImport = true;
}
}
void checkAnnotations() {
if (!allowAnnotations) {
- error(S.pos(), "annotations.not.supported.in.source", source.name);
+ error(token.pos, "annotations.not.supported.in.source", source.name);
allowAnnotations = true;
}
}
void checkDiamond() {
if (!allowDiamond) {
- error(S.pos(), "diamond.not.supported.in.source", source.name);
+ error(token.pos, "diamond.not.supported.in.source", source.name);
allowDiamond = true;
}
}
void checkMulticatch() {
if (!allowMulticatch) {
- error(S.pos(), "multicatch.not.supported.in.source", source.name);
+ error(token.pos, "multicatch.not.supported.in.source", source.name);
allowMulticatch = true;
}
}
void checkTryWithResources() {
if (!allowTWR) {
- error(S.pos(), "try.with.resources.not.supported.in.source", source.name);
+ error(token.pos, "try.with.resources.not.supported.in.source", source.name);
allowTWR = true;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.parser;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.parser.Tokens.Token;
+import com.sun.tools.javac.util.*;
+
+import java.nio.*;
+
+import static com.sun.tools.javac.util.LayoutCharacters.*;
+
+/** An extension to the base lexical analyzer that captures
+ * and processes the contents of doc comments. It does so by
+ * translating Unicode escape sequences and by stripping the
+ * leading whitespace and starts from each line of the comment.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class JavadocTokenizer extends JavaTokenizer {
+
+ /** Create a scanner from the input buffer. buffer must implement
+ * array() and compact(), and remaining() must be less than limit().
+ */
+ protected JavadocTokenizer(ScannerFactory fac, CharBuffer buffer) {
+ super(fac, buffer);
+ }
+
+ /** Create a scanner from the input array. The array must have at
+ * least a single character of extra space.
+ */
+ protected JavadocTokenizer(ScannerFactory fac, char[] input, int inputLength) {
+ super(fac, input, inputLength);
+ }
+
+ /** The comment input buffer, index of next chacter to be read,
+ * index of one past last character in buffer.
+ */
+ private char[] buf;
+ private int bp;
+ private int buflen;
+
+ /** The current character.
+ */
+ private char ch;
+
+ /** The column number position of the current character.
+ */
+ private int col;
+
+ /** The buffer index of the last converted Unicode character
+ */
+ private int unicodeConversionBp = 0;
+
+ /**
+ * Buffer for doc comment.
+ */
+ private char[] docCommentBuffer = new char[1024];
+
+ /**
+ * Number of characters in doc comment buffer.
+ */
+ private int docCommentCount;
+
+ /**
+ * Translated and stripped contents of doc comment
+ */
+ private String docComment = null;
+
+
+ /** Unconditionally expand the comment buffer.
+ */
+ private void expandCommentBuffer() {
+ char[] newBuffer = new char[docCommentBuffer.length * 2];
+ System.arraycopy(docCommentBuffer, 0, newBuffer,
+ 0, docCommentBuffer.length);
+ docCommentBuffer = newBuffer;
+ }
+
+ /** Convert an ASCII digit from its base (8, 10, or 16)
+ * to its value.
+ */
+ private int digit(int base) {
+ char c = ch;
+ int result = Character.digit(c, base);
+ if (result >= 0 && c > 0x7f) {
+ ch = "0123456789abcdef".charAt(result);
+ }
+ return result;
+ }
+
+ /** Convert Unicode escape; bp points to initial '\' character
+ * (Spec 3.3).
+ */
+ private void convertUnicode() {
+ if (ch == '\\' && unicodeConversionBp != bp) {
+ bp++; ch = buf[bp]; col++;
+ if (ch == 'u') {
+ do {
+ bp++; ch = buf[bp]; col++;
+ } while (ch == 'u');
+ int limit = bp + 3;
+ if (limit < buflen) {
+ int d = digit(16);
+ int code = d;
+ while (bp < limit && d >= 0) {
+ bp++; ch = buf[bp]; col++;
+ d = digit(16);
+ code = (code << 4) + d;
+ }
+ if (d >= 0) {
+ ch = (char)code;
+ unicodeConversionBp = bp;
+ return;
+ }
+ }
+ // "illegal.Unicode.esc", reported by base scanner
+ } else {
+ bp--;
+ ch = '\\';
+ col--;
+ }
+ }
+ }
+
+
+ /** Read next character.
+ */
+ private void scanChar() {
+ bp++;
+ ch = buf[bp];
+ switch (ch) {
+ case '\r': // return
+ col = 0;
+ break;
+ case '\n': // newline
+ if (bp == 0 || buf[bp-1] != '\r') {
+ col = 0;
+ }
+ break;
+ case '\t': // tab
+ col = (col / TabInc * TabInc) + TabInc;
+ break;
+ case '\\': // possible Unicode
+ col++;
+ convertUnicode();
+ break;
+ default:
+ col++;
+ break;
+ }
+ }
+
+ @Override
+ public Token readToken() {
+ docComment = null;
+ Token tk = super.readToken();
+ tk.docComment = docComment;
+ return tk;
+ }
+
+ /**
+ * Read next character in doc comment, skipping over double '\' characters.
+ * If a double '\' is skipped, put in the buffer and update buffer count.
+ */
+ private void scanDocCommentChar() {
+ scanChar();
+ if (ch == '\\') {
+ if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
+ if (docCommentCount == docCommentBuffer.length)
+ expandCommentBuffer();
+ docCommentBuffer[docCommentCount++] = ch;
+ bp++; col++;
+ } else {
+ convertUnicode();
+ }
+ }
+ }
+
+ /**
+ * Process a doc comment and make the string content available.
+ * Strips leading whitespace and stars.
+ */
+ @SuppressWarnings("fallthrough")
+ protected void processComment(int pos, int endPos, CommentStyle style) {
+ if (style != CommentStyle.JAVADOC) {
+ return;
+ }
+
+ buf = reader.getRawCharacters(pos, endPos);
+ buflen = buf.length;
+ bp = 0;
+ col = 0;
+
+ docCommentCount = 0;
+
+ boolean firstLine = true;
+
+ // Skip over first slash
+ scanDocCommentChar();
+ // Skip over first star
+ scanDocCommentChar();
+
+ // consume any number of stars
+ while (bp < buflen && ch == '*') {
+ scanDocCommentChar();
+ }
+ // is the comment in the form /**/, /***/, /****/, etc. ?
+ if (bp < buflen && ch == '/') {
+ docComment = "";
+ return;
+ }
+
+ // skip a newline on the first line of the comment.
+ if (bp < buflen) {
+ if (ch == LF) {
+ scanDocCommentChar();
+ firstLine = false;
+ } else if (ch == CR) {
+ scanDocCommentChar();
+ if (ch == LF) {
+ scanDocCommentChar();
+ firstLine = false;
+ }
+ }
+ }
+
+ outerLoop:
+
+ // The outerLoop processes the doc comment, looping once
+ // for each line. For each line, it first strips off
+ // whitespace, then it consumes any stars, then it
+ // puts the rest of the line into our buffer.
+ while (bp < buflen) {
+
+ // The wsLoop consumes whitespace from the beginning
+ // of each line.
+ wsLoop:
+
+ while (bp < buflen) {
+ switch(ch) {
+ case ' ':
+ scanDocCommentChar();
+ break;
+ case '\t':
+ col = ((col - 1) / TabInc * TabInc) + TabInc;
+ scanDocCommentChar();
+ break;
+ case FF:
+ col = 0;
+ scanDocCommentChar();
+ break;
+// Treat newline at beginning of line (blank line, no star)
+// as comment text. Old Javadoc compatibility requires this.
+/*---------------------------------*
+ case CR: // (Spec 3.4)
+ scanDocCommentChar();
+ if (ch == LF) {
+ col = 0;
+ scanDocCommentChar();
+ }
+ break;
+ case LF: // (Spec 3.4)
+ scanDocCommentChar();
+ break;
+*---------------------------------*/
+ default:
+ // we've seen something that isn't whitespace;
+ // jump out.
+ break wsLoop;
+ }
+ }
+
+ // Are there stars here? If so, consume them all
+ // and check for the end of comment.
+ if (ch == '*') {
+ // skip all of the stars
+ do {
+ scanDocCommentChar();
+ } while (ch == '*');
+
+ // check for the closing slash.
+ if (ch == '/') {
+ // We're done with the doc comment
+ // scanChar() and breakout.
+ break outerLoop;
+ }
+ } else if (! firstLine) {
+ //The current line does not begin with a '*' so we will indent it.
+ for (int i = 1; i < col; i++) {
+ if (docCommentCount == docCommentBuffer.length)
+ expandCommentBuffer();
+ docCommentBuffer[docCommentCount++] = ' ';
+ }
+ }
+
+ // The textLoop processes the rest of the characters
+ // on the line, adding them to our buffer.
+ textLoop:
+ while (bp < buflen) {
+ switch (ch) {
+ case '*':
+ // Is this just a star? Or is this the
+ // end of a comment?
+ scanDocCommentChar();
+ if (ch == '/') {
+ // This is the end of the comment,
+ // set ch and return our buffer.
+ break outerLoop;
+ }
+ // This is just an ordinary star. Add it to
+ // the buffer.
+ if (docCommentCount == docCommentBuffer.length)
+ expandCommentBuffer();
+ docCommentBuffer[docCommentCount++] = '*';
+ break;
+ case ' ':
+ case '\t':
+ if (docCommentCount == docCommentBuffer.length)
+ expandCommentBuffer();
+ docCommentBuffer[docCommentCount++] = ch;
+ scanDocCommentChar();
+ break;
+ case FF:
+ scanDocCommentChar();
+ break textLoop; // treat as end of line
+ case CR: // (Spec 3.4)
+ scanDocCommentChar();
+ if (ch != LF) {
+ // Canonicalize CR-only line terminator to LF
+ if (docCommentCount == docCommentBuffer.length)
+ expandCommentBuffer();
+ docCommentBuffer[docCommentCount++] = (char)LF;
+ break textLoop;
+ }
+ /* fall through to LF case */
+ case LF: // (Spec 3.4)
+ // We've seen a newline. Add it to our
+ // buffer and break out of this loop,
+ // starting fresh on a new line.
+ if (docCommentCount == docCommentBuffer.length)
+ expandCommentBuffer();
+ docCommentBuffer[docCommentCount++] = ch;
+ scanDocCommentChar();
+ break textLoop;
+ default:
+ // Add the character to our buffer.
+ if (docCommentCount == docCommentBuffer.length)
+ expandCommentBuffer();
+ docCommentBuffer[docCommentCount++] = ch;
+ scanDocCommentChar();
+ }
+ } // end textLoop
+ firstLine = false;
+ } // end outerLoop
+
+ if (docCommentCount > 0) {
+ int i = docCommentCount - 1;
+ trailLoop:
+ while (i > -1) {
+ switch (docCommentBuffer[i]) {
+ case '*':
+ i--;
+ break;
+ default:
+ break trailLoop;
+ }
+ }
+ docCommentCount = i + 1;
+
+ // Store the text of the doc comment
+ docComment = new String(docCommentBuffer, 0 , docCommentCount);
+ } else {
+ docComment = "";
+ }
+ }
+
+ /** Build a map for translating between line numbers and
+ * positions in the input.
+ *
+ * @return a LineMap */
+ public Position.LineMap getLineMap() {
+ char[] buf = reader.getRawCharacters();
+ return Position.makeLineMap(buf, buf.length, true);
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java Thu Nov 03 13:26:57 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.parser;
-
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Names;
-
-import static com.sun.tools.javac.parser.Token.*;
-
-/**
- * Map from Name to Token and Token to String.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class Keywords {
- public static final Context.Key<Keywords> keywordsKey =
- new Context.Key<Keywords>();
-
- public static Keywords instance(Context context) {
- Keywords instance = context.get(keywordsKey);
- if (instance == null)
- instance = new Keywords(context);
- return instance;
- }
-
- private final Names names;
-
- protected Keywords(Context context) {
- context.put(keywordsKey, this);
- names = Names.instance(context);
-
- for (Token t : Token.values()) {
- if (t.name != null)
- enterKeyword(t.name, t);
- else
- tokenName[t.ordinal()] = null;
- }
-
- key = new Token[maxKey+1];
- for (int i = 0; i <= maxKey; i++) key[i] = IDENTIFIER;
- for (Token t : Token.values()) {
- if (t.name != null)
- key[tokenName[t.ordinal()].getIndex()] = t;
- }
- }
-
-
- public Token key(Name name) {
- return (name.getIndex() > maxKey) ? IDENTIFIER : key[name.getIndex()];
- }
-
- /**
- * Keyword array. Maps name indices to Token.
- */
- private final Token[] key;
-
- /** The number of the last entered keyword.
- */
- private int maxKey = 0;
-
- /** The names of all tokens.
- */
- private Name[] tokenName = new Name[Token.values().length];
-
- private void enterKeyword(String s, Token token) {
- Name n = names.fromString(s);
- tokenName[token.ordinal()] = n;
- if (n.getIndex() > maxKey) maxKey = n.getIndex();
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java Sat Nov 05 00:00:43 2011 -0700
@@ -25,7 +25,7 @@
package com.sun.tools.javac.parser;
-import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.parser.Tokens.*;
import com.sun.tools.javac.util.Position.LineMap;
/**
@@ -40,22 +40,26 @@
public interface Lexer {
/**
- * Has a @deprecated been encountered in last doc comment?
- * This needs to be reset by client with resetDeprecatedFlag.
+ * Consume the next token.
*/
- boolean deprecatedFlag();
+ void nextToken();
- void resetDeprecatedFlag();
+ /**
+ * Return current token.
+ */
+ Token token();
/**
- * Returns the documentation string of the current token.
+ * Return the last character position of the previous token.
*/
- String docComment();
+ Token prevToken();
/**
- * Return the last character position of the current token.
+ * Splits the current token in two and return the first (splitted) token.
+ * For instance '<<<' is splitted into two tokens '<' and '<<' respectively,
+ * and the latter is returned.
*/
- int endPos();
+ Token split();
/**
* Return the position where a lexical error occurred;
@@ -74,69 +78,4 @@
* @return a LineMap
*/
LineMap getLineMap();
-
- /**
- * Returns a copy of the input buffer, up to its inputLength.
- * Unicode escape sequences are not translated.
- */
- char[] getRawCharacters();
-
- /**
- * Returns a copy of a character array subset of the input buffer.
- * The returned array begins at the <code>beginIndex</code> and
- * extends to the character at index <code>endIndex - 1</code>.
- * Thus the length of the substring is <code>endIndex-beginIndex</code>.
- * This behavior is like
- * <code>String.substring(beginIndex, endIndex)</code>.
- * Unicode escape sequences are not translated.
- *
- * @param beginIndex the beginning index, inclusive.
- * @param endIndex the ending index, exclusive.
- * @throws IndexOutOfBounds if either offset is outside of the
- * array bounds
- */
- char[] getRawCharacters(int beginIndex, int endIndex);
-
- /**
- * Return the name of an identifier or token for the current token.
- */
- Name name();
-
- /**
- * Read token.
- */
- void nextToken();
-
- /**
- * Return the current token's position: a 0-based
- * offset from beginning of the raw input stream
- * (before unicode translation)
- */
- int pos();
-
- /**
- * Return the last character position of the previous token.
- */
- int prevEndPos();
-
- /**
- * Return the radix of a numeric literal token.
- */
- int radix();
-
- /**
- * The value of a literal token, recorded as a string.
- * For integers, leading 0x and 'l' suffixes are suppressed.
- */
- String stringVal();
-
- /**
- * Return the current token, set by nextToken().
- */
- Token token();
-
- /**
- * Sets the current token.
- */
- void token(Token token);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java Sat Nov 05 00:00:43 2011 -0700
@@ -55,7 +55,7 @@
final TreeMaker F;
final Log log;
- final Keywords keywords;
+ final Tokens tokens;
final Source source;
final Names names;
final Options options;
@@ -67,7 +67,7 @@
this.F = TreeMaker.instance(context);
this.log = Log.instance(context);
this.names = Names.instance(context);
- this.keywords = Keywords.instance(context);
+ this.tokens = Tokens.instance(context);
this.source = Source.instance(context);
this.options = Options.instance(context);
this.scannerFactory = ScannerFactory.instance(context);
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Sat Nov 05 00:00:43 2011 -0700
@@ -27,13 +27,11 @@
import java.nio.*;
-import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.Position.LineMap;
+import com.sun.tools.javac.parser.JavaTokenizer.*;
-
-import static com.sun.tools.javac.parser.Token.*;
-import static com.sun.tools.javac.util.LayoutCharacters.*;
+import static com.sun.tools.javac.parser.Tokens.*;
/** The lexical analyzer maps an input stream consisting of
* ASCII characters and Unicode escapes into a token sequence.
@@ -45,119 +43,17 @@
*/
public class Scanner implements Lexer {
- private static boolean scannerDebug = false;
-
- /* Output variables; set by nextToken():
- */
+ private Tokens tokens;
/** The token, set by nextToken().
*/
private Token token;
- /** Allow hex floating-point literals.
- */
- private boolean allowHexFloats;
-
- /** Allow binary literals.
- */
- private boolean allowBinaryLiterals;
-
- /** Allow underscores in literals.
- */
- private boolean allowUnderscoresInLiterals;
-
- /** The source language setting.
- */
- private Source source;
-
- /** The token's position, 0-based offset from beginning of text.
- */
- private int pos;
-
- /** Character position just after the last character of the token.
+ /** The previous token, set by nextToken().
*/
- private int endPos;
-
- /** The last character position of the previous token.
- */
- private int prevEndPos;
-
- /** The position where a lexical error occurred;
- */
- private int errPos = Position.NOPOS;
-
- /** The name of an identifier or token:
- */
- private Name name;
-
- /** The radix of a numeric literal token.
- */
- private int radix;
-
- /** Has a @deprecated been encountered in last doc comment?
- * this needs to be reset by client.
- */
- protected boolean deprecatedFlag = false;
-
- /** A character buffer for literals.
- */
- private char[] sbuf = new char[128];
- private int sp;
+ private Token prevToken;
- /** The input buffer, index of next chacter to be read,
- * index of one past last character in buffer.
- */
- private char[] buf;
- private int bp;
- private int buflen;
- private int eofPos;
-
- /** The current character.
- */
- private char ch;
-
- /** The buffer index of the last converted unicode character
- */
- private int unicodeConversionBp = -1;
-
- /** The log to be used for error reporting.
- */
- private final Log log;
-
- /** The name table. */
- private final Names names;
-
- /** The keyword table. */
- private final Keywords keywords;
-
- /** Common code for constructors. */
- private Scanner(ScannerFactory fac) {
- log = fac.log;
- names = fac.names;
- keywords = fac.keywords;
- source = fac.source;
- allowBinaryLiterals = source.allowBinaryLiterals();
- allowHexFloats = source.allowHexFloats();
- allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
- }
-
- private static final boolean hexFloatsWork = hexFloatsWork();
- private static boolean hexFloatsWork() {
- try {
- Float.valueOf("0x1.0p1");
- return true;
- } catch (NumberFormatException ex) {
- return false;
- }
- }
-
- /** Create a scanner from the input buffer. buffer must implement
- * array() and compact(), and remaining() must be less than limit().
- */
- protected Scanner(ScannerFactory fac, CharBuffer buffer) {
- this(fac, JavacFileManager.toArray(buffer), buffer.limit());
- }
-
+ private JavaTokenizer tokenizer;
/**
* Create a scanner from the input array. This method might
* modify the array. To avoid copying the input array, ensure
@@ -169,972 +65,49 @@
* @param inputLength the size of the input.
* Must be positive and less than or equal to input.length.
*/
- protected Scanner(ScannerFactory fac, char[] input, int inputLength) {
- this(fac);
- eofPos = inputLength;
- if (inputLength == input.length) {
- if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
- inputLength--;
- } else {
- char[] newInput = new char[inputLength + 1];
- System.arraycopy(input, 0, newInput, 0, input.length);
- input = newInput;
- }
- }
- buf = input;
- buflen = inputLength;
- buf[buflen] = EOI;
- bp = -1;
- scanChar();
- }
-
- /** Report an error at the given position using the provided arguments.
- */
- private void lexError(int pos, String key, Object... args) {
- log.error(pos, key, args);
- token = ERROR;
- errPos = pos;
- }
-
- /** Report an error at the current token position using the provided
- * arguments.
- */
- private void lexError(String key, Object... args) {
- lexError(pos, key, args);
- }
-
- /** Convert an ASCII digit from its base (8, 10, or 16)
- * to its value.
- */
- private int digit(int base) {
- char c = ch;
- int result = Character.digit(c, base);
- if (result >= 0 && c > 0x7f) {
- lexError(pos+1, "illegal.nonascii.digit");
- ch = "0123456789abcdef".charAt(result);
- }
- return result;
- }
-
- /** Convert unicode escape; bp points to initial '\' character
- * (Spec 3.3).
- */
- private void convertUnicode() {
- if (ch == '\\' && unicodeConversionBp != bp) {
- bp++; ch = buf[bp];
- if (ch == 'u') {
- do {
- bp++; ch = buf[bp];
- } while (ch == 'u');
- int limit = bp + 3;
- if (limit < buflen) {
- int d = digit(16);
- int code = d;
- while (bp < limit && d >= 0) {
- bp++; ch = buf[bp];
- d = digit(16);
- code = (code << 4) + d;
- }
- if (d >= 0) {
- ch = (char)code;
- unicodeConversionBp = bp;
- return;
- }
- }
- lexError(bp, "illegal.unicode.esc");
- } else {
- bp--;
- ch = '\\';
- }
- }
- }
-
- /** Read next character.
- */
- private void scanChar() {
- ch = buf[++bp];
- if (ch == '\\') {
- convertUnicode();
- }
- }
-
- /** Read next character in comment, skipping over double '\' characters.
- */
- private void scanCommentChar() {
- scanChar();
- if (ch == '\\') {
- if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
- bp++;
- } else {
- convertUnicode();
- }
- }
- }
-
- /** Append a character to sbuf.
- */
- private void putChar(char ch) {
- if (sp == sbuf.length) {
- char[] newsbuf = new char[sbuf.length * 2];
- System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
- sbuf = newsbuf;
- }
- sbuf[sp++] = ch;
- }
-
- /** Read next character in character or string literal and copy into sbuf.
- */
- private void scanLitChar() {
- if (ch == '\\') {
- if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
- bp++;
- putChar('\\');
- scanChar();
- } else {
- scanChar();
- switch (ch) {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- char leadch = ch;
- int oct = digit(8);
- scanChar();
- if ('0' <= ch && ch <= '7') {
- oct = oct * 8 + digit(8);
- scanChar();
- if (leadch <= '3' && '0' <= ch && ch <= '7') {
- oct = oct * 8 + digit(8);
- scanChar();
- }
- }
- putChar((char)oct);
- break;
- case 'b':
- putChar('\b'); scanChar(); break;
- case 't':
- putChar('\t'); scanChar(); break;
- case 'n':
- putChar('\n'); scanChar(); break;
- case 'f':
- putChar('\f'); scanChar(); break;
- case 'r':
- putChar('\r'); scanChar(); break;
- case '\'':
- putChar('\''); scanChar(); break;
- case '\"':
- putChar('\"'); scanChar(); break;
- case '\\':
- putChar('\\'); scanChar(); break;
- default:
- lexError(bp, "illegal.esc.char");
- }
- }
- } else if (bp != buflen) {
- putChar(ch); scanChar();
- }
- }
-
- private void scanDigits(int digitRadix) {
- char saveCh;
- int savePos;
- do {
- if (ch != '_') {
- putChar(ch);
- } else {
- if (!allowUnderscoresInLiterals) {
- lexError("unsupported.underscore.lit", source.name);
- allowUnderscoresInLiterals = true;
- }
- }
- saveCh = ch;
- savePos = bp;
- scanChar();
- } while (digit(digitRadix) >= 0 || ch == '_');
- if (saveCh == '_')
- lexError(savePos, "illegal.underscore");
- }
-
- /** Read fractional part of hexadecimal floating point number.
- */
- private void scanHexExponentAndSuffix() {
- if (ch == 'p' || ch == 'P') {
- putChar(ch);
- scanChar();
- skipIllegalUnderscores();
- if (ch == '+' || ch == '-') {
- putChar(ch);
- scanChar();
- }
- skipIllegalUnderscores();
- if ('0' <= ch && ch <= '9') {
- scanDigits(10);
- if (!allowHexFloats) {
- lexError("unsupported.fp.lit", source.name);
- allowHexFloats = true;
- }
- else if (!hexFloatsWork)
- lexError("unsupported.cross.fp.lit");
- } else
- lexError("malformed.fp.lit");
- } else {
- lexError("malformed.fp.lit");
- }
- if (ch == 'f' || ch == 'F') {
- putChar(ch);
- scanChar();
- token = FLOATLITERAL;
- } else {
- if (ch == 'd' || ch == 'D') {
- putChar(ch);
- scanChar();
- }
- token = DOUBLELITERAL;
- }
- }
-
- /** Read fractional part of floating point number.
- */
- private void scanFraction() {
- skipIllegalUnderscores();
- if ('0' <= ch && ch <= '9') {
- scanDigits(10);
- }
- int sp1 = sp;
- if (ch == 'e' || ch == 'E') {
- putChar(ch);
- scanChar();
- skipIllegalUnderscores();
- if (ch == '+' || ch == '-') {
- putChar(ch);
- scanChar();
- }
- skipIllegalUnderscores();
- if ('0' <= ch && ch <= '9') {
- scanDigits(10);
- return;
- }
- lexError("malformed.fp.lit");
- sp = sp1;
- }
- }
-
- /** Read fractional part and 'd' or 'f' suffix of floating point number.
- */
- private void scanFractionAndSuffix() {
- this.radix = 10;
- scanFraction();
- if (ch == 'f' || ch == 'F') {
- putChar(ch);
- scanChar();
- token = FLOATLITERAL;
- } else {
- if (ch == 'd' || ch == 'D') {
- putChar(ch);
- scanChar();
- }
- token = DOUBLELITERAL;
- }
- }
-
- /** Read fractional part and 'd' or 'f' suffix of floating point number.
- */
- private void scanHexFractionAndSuffix(boolean seendigit) {
- this.radix = 16;
- Assert.check(ch == '.');
- putChar(ch);
- scanChar();
- skipIllegalUnderscores();
- if (digit(16) >= 0) {
- seendigit = true;
- scanDigits(16);
- }
- if (!seendigit)
- lexError("invalid.hex.number");
- else
- scanHexExponentAndSuffix();
- }
-
- private void skipIllegalUnderscores() {
- if (ch == '_') {
- lexError(bp, "illegal.underscore");
- while (ch == '_')
- scanChar();
- }
- }
-
- /** Read a number.
- * @param radix The radix of the number; one of 2, j8, 10, 16.
- */
- private void scanNumber(int radix) {
- this.radix = radix;
- // for octal, allow base-10 digit in case it's a float literal
- int digitRadix = (radix == 8 ? 10 : radix);
- boolean seendigit = false;
- if (digit(digitRadix) >= 0) {
- seendigit = true;
- scanDigits(digitRadix);
- }
- if (radix == 16 && ch == '.') {
- scanHexFractionAndSuffix(seendigit);
- } else if (seendigit && radix == 16 && (ch == 'p' || ch == 'P')) {
- scanHexExponentAndSuffix();
- } else if (digitRadix == 10 && ch == '.') {
- putChar(ch);
- scanChar();
- scanFractionAndSuffix();
- } else if (digitRadix == 10 &&
- (ch == 'e' || ch == 'E' ||
- ch == 'f' || ch == 'F' ||
- ch == 'd' || ch == 'D')) {
- scanFractionAndSuffix();
- } else {
- if (ch == 'l' || ch == 'L') {
- scanChar();
- token = LONGLITERAL;
- } else {
- token = INTLITERAL;
- }
- }
- }
-
- /** Read an identifier.
- */
- private void scanIdent() {
- boolean isJavaIdentifierPart;
- char high;
- do {
- if (sp == sbuf.length) putChar(ch); else sbuf[sp++] = ch;
- // optimization, was: putChar(ch);
-
- scanChar();
- switch (ch) {
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'L': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- case '$': case '_':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '\u0000': case '\u0001': case '\u0002': case '\u0003':
- case '\u0004': case '\u0005': case '\u0006': case '\u0007':
- case '\u0008': case '\u000E': case '\u000F': case '\u0010':
- case '\u0011': case '\u0012': case '\u0013': case '\u0014':
- case '\u0015': case '\u0016': case '\u0017':
- case '\u0018': case '\u0019': case '\u001B':
- case '\u007F':
- break;
- case '\u001A': // EOI is also a legal identifier part
- if (bp >= buflen) {
- name = names.fromChars(sbuf, 0, sp);
- token = keywords.key(name);
- return;
- }
- break;
- default:
- if (ch < '\u0080') {
- // all ASCII range chars already handled, above
- isJavaIdentifierPart = false;
- } else {
- high = scanSurrogates();
- if (high != 0) {
- if (sp == sbuf.length) {
- putChar(high);
- } else {
- sbuf[sp++] = high;
- }
- isJavaIdentifierPart = Character.isJavaIdentifierPart(
- Character.toCodePoint(high, ch));
- } else {
- isJavaIdentifierPart = Character.isJavaIdentifierPart(ch);
- }
- }
- if (!isJavaIdentifierPart) {
- name = names.fromChars(sbuf, 0, sp);
- token = keywords.key(name);
- return;
- }
- }
- } while (true);
+ protected Scanner(ScannerFactory fac, CharBuffer buf) {
+ this(fac, new JavaTokenizer(fac, buf));
}
- /** Are surrogates supported?
- */
- final static boolean surrogatesSupported = surrogatesSupported();
- private static boolean surrogatesSupported() {
- try {
- Character.isHighSurrogate('a');
- return true;
- } catch (NoSuchMethodError ex) {
- return false;
- }
- }
-
- /** Scan surrogate pairs. If 'ch' is a high surrogate and
- * the next character is a low surrogate, then put the low
- * surrogate in 'ch', and return the high surrogate.
- * otherwise, just return 0.
- */
- private char scanSurrogates() {
- if (surrogatesSupported && Character.isHighSurrogate(ch)) {
- char high = ch;
-
- scanChar();
-
- if (Character.isLowSurrogate(ch)) {
- return high;
- }
-
- ch = high;
- }
-
- return 0;
- }
-
- /** Return true if ch can be part of an operator.
- */
- private boolean isSpecial(char ch) {
- switch (ch) {
- case '!': case '%': case '&': case '*': case '?':
- case '+': case '-': case ':': case '<': case '=':
- case '>': case '^': case '|': case '~':
- case '@':
- return true;
- default:
- return false;
- }
- }
-
- /** Read longest possible sequence of special characters and convert
- * to token.
- */
- private void scanOperator() {
- while (true) {
- putChar(ch);
- Name newname = names.fromChars(sbuf, 0, sp);
- if (keywords.key(newname) == IDENTIFIER) {
- sp--;
- break;
- }
- name = newname;
- token = keywords.key(newname);
- scanChar();
- if (!isSpecial(ch)) break;
- }
- }
-
- /**
- * Scan a documention comment; determine if a deprecated tag is present.
- * Called once the initial /, * have been skipped, positioned at the second *
- * (which is treated as the beginning of the first line).
- * Stops positioned at the closing '/'.
- */
- @SuppressWarnings("fallthrough")
- private void scanDocComment() {
- boolean deprecatedPrefix = false;
-
- forEachLine:
- while (bp < buflen) {
-
- // Skip optional WhiteSpace at beginning of line
- while (bp < buflen && (ch == ' ' || ch == '\t' || ch == FF)) {
- scanCommentChar();
- }
-
- // Skip optional consecutive Stars
- while (bp < buflen && ch == '*') {
- scanCommentChar();
- if (ch == '/') {
- return;
- }
- }
-
- // Skip optional WhiteSpace after Stars
- while (bp < buflen && (ch == ' ' || ch == '\t' || ch == FF)) {
- scanCommentChar();
- }
-
- deprecatedPrefix = false;
- // At beginning of line in the JavaDoc sense.
- if (bp < buflen && ch == '@' && !deprecatedFlag) {
- scanCommentChar();
- if (bp < buflen && ch == 'd') {
- scanCommentChar();
- if (bp < buflen && ch == 'e') {
- scanCommentChar();
- if (bp < buflen && ch == 'p') {
- scanCommentChar();
- if (bp < buflen && ch == 'r') {
- scanCommentChar();
- if (bp < buflen && ch == 'e') {
- scanCommentChar();
- if (bp < buflen && ch == 'c') {
- scanCommentChar();
- if (bp < buflen && ch == 'a') {
- scanCommentChar();
- if (bp < buflen && ch == 't') {
- scanCommentChar();
- if (bp < buflen && ch == 'e') {
- scanCommentChar();
- if (bp < buflen && ch == 'd') {
- deprecatedPrefix = true;
- scanCommentChar();
- }}}}}}}}}}}
- if (deprecatedPrefix && bp < buflen) {
- if (Character.isWhitespace(ch)) {
- deprecatedFlag = true;
- } else if (ch == '*') {
- scanCommentChar();
- if (ch == '/') {
- deprecatedFlag = true;
- return;
- }
- }
- }
-
- // Skip rest of line
- while (bp < buflen) {
- switch (ch) {
- case '*':
- scanCommentChar();
- if (ch == '/') {
- return;
- }
- break;
- case CR: // (Spec 3.4)
- scanCommentChar();
- if (ch != LF) {
- continue forEachLine;
- }
- /* fall through to LF case */
- case LF: // (Spec 3.4)
- scanCommentChar();
- continue forEachLine;
- default:
- scanCommentChar();
- }
- } // rest of line
- } // forEachLine
- return;
- }
-
- /** The value of a literal token, recorded as a string.
- * For integers, leading 0x and 'l' suffixes are suppressed.
- */
- public String stringVal() {
- return new String(sbuf, 0, sp);
+ protected Scanner(ScannerFactory fac, char[] buf, int inputLength) {
+ this(fac, new JavaTokenizer(fac, buf, inputLength));
}
- /** Read token.
- */
- public void nextToken() {
-
- try {
- prevEndPos = endPos;
- sp = 0;
-
- while (true) {
- pos = bp;
- switch (ch) {
- case ' ': // (Spec 3.6)
- case '\t': // (Spec 3.6)
- case FF: // (Spec 3.6)
- do {
- scanChar();
- } while (ch == ' ' || ch == '\t' || ch == FF);
- endPos = bp;
- processWhiteSpace();
- break;
- case LF: // (Spec 3.4)
- scanChar();
- endPos = bp;
- processLineTerminator();
- break;
- case CR: // (Spec 3.4)
- scanChar();
- if (ch == LF) {
- scanChar();
- }
- endPos = bp;
- processLineTerminator();
- break;
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'L': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- case '$': case '_':
- scanIdent();
- return;
- case '0':
- scanChar();
- if (ch == 'x' || ch == 'X') {
- scanChar();
- skipIllegalUnderscores();
- if (ch == '.') {
- scanHexFractionAndSuffix(false);
- } else if (digit(16) < 0) {
- lexError("invalid.hex.number");
- } else {
- scanNumber(16);
- }
- } else if (ch == 'b' || ch == 'B') {
- if (!allowBinaryLiterals) {
- lexError("unsupported.binary.lit", source.name);
- allowBinaryLiterals = true;
- }
- scanChar();
- skipIllegalUnderscores();
- if (digit(2) < 0) {
- lexError("invalid.binary.number");
- } else {
- scanNumber(2);
- }
- } else {
- putChar('0');
- if (ch == '_') {
- int savePos = bp;
- do {
- scanChar();
- } while (ch == '_');
- if (digit(10) < 0) {
- lexError(savePos, "illegal.underscore");
- }
- }
- scanNumber(8);
- }
- return;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- scanNumber(10);
- return;
- case '.':
- scanChar();
- if ('0' <= ch && ch <= '9') {
- putChar('.');
- scanFractionAndSuffix();
- } else if (ch == '.') {
- putChar('.'); putChar('.');
- scanChar();
- if (ch == '.') {
- scanChar();
- putChar('.');
- token = ELLIPSIS;
- } else {
- lexError("malformed.fp.lit");
- }
- } else {
- token = DOT;
- }
- return;
- case ',':
- scanChar(); token = COMMA; return;
- case ';':
- scanChar(); token = SEMI; return;
- case '(':
- scanChar(); token = LPAREN; return;
- case ')':
- scanChar(); token = RPAREN; return;
- case '[':
- scanChar(); token = LBRACKET; return;
- case ']':
- scanChar(); token = RBRACKET; return;
- case '{':
- scanChar(); token = LBRACE; return;
- case '}':
- scanChar(); token = RBRACE; return;
- case '/':
- scanChar();
- if (ch == '/') {
- do {
- scanCommentChar();
- } while (ch != CR && ch != LF && bp < buflen);
- if (bp < buflen) {
- endPos = bp;
- processComment(CommentStyle.LINE);
- }
- break;
- } else if (ch == '*') {
- scanChar();
- CommentStyle style;
- if (ch == '*') {
- style = CommentStyle.JAVADOC;
- scanDocComment();
- } else {
- style = CommentStyle.BLOCK;
- while (bp < buflen) {
- if (ch == '*') {
- scanChar();
- if (ch == '/') break;
- } else {
- scanCommentChar();
- }
- }
- }
- if (ch == '/') {
- scanChar();
- endPos = bp;
- processComment(style);
- break;
- } else {
- lexError("unclosed.comment");
- return;
- }
- } else if (ch == '=') {
- name = names.slashequals;
- token = SLASHEQ;
- scanChar();
- } else {
- name = names.slash;
- token = SLASH;
- }
- return;
- case '\'':
- scanChar();
- if (ch == '\'') {
- lexError("empty.char.lit");
- } else {
- if (ch == CR || ch == LF)
- lexError(pos, "illegal.line.end.in.char.lit");
- scanLitChar();
- if (ch == '\'') {
- scanChar();
- token = CHARLITERAL;
- } else {
- lexError(pos, "unclosed.char.lit");
- }
- }
- return;
- case '\"':
- scanChar();
- while (ch != '\"' && ch != CR && ch != LF && bp < buflen)
- scanLitChar();
- if (ch == '\"') {
- token = STRINGLITERAL;
- scanChar();
- } else {
- lexError(pos, "unclosed.str.lit");
- }
- return;
- default:
- if (isSpecial(ch)) {
- scanOperator();
- } else {
- boolean isJavaIdentifierStart;
- if (ch < '\u0080') {
- // all ASCII range chars already handled, above
- isJavaIdentifierStart = false;
- } else {
- char high = scanSurrogates();
- if (high != 0) {
- if (sp == sbuf.length) {
- putChar(high);
- } else {
- sbuf[sp++] = high;
- }
-
- isJavaIdentifierStart = Character.isJavaIdentifierStart(
- Character.toCodePoint(high, ch));
- } else {
- isJavaIdentifierStart = Character.isJavaIdentifierStart(ch);
- }
- }
- if (isJavaIdentifierStart) {
- scanIdent();
- } else if (bp == buflen || ch == EOI && bp+1 == buflen) { // JLS 3.5
- token = EOF;
- pos = bp = eofPos;
- } else {
- lexError("illegal.char", String.valueOf((int)ch));
- scanChar();
- }
- }
- return;
- }
- }
- } finally {
- endPos = bp;
- if (scannerDebug)
- System.out.println("nextToken(" + pos
- + "," + endPos + ")=|" +
- new String(getRawCharacters(pos, endPos))
- + "|");
- }
+ protected Scanner(ScannerFactory fac, JavaTokenizer tokenizer) {
+ this.tokenizer = tokenizer;
+ tokens = fac.tokens;
+ token = prevToken = DUMMY;
}
- /** Return the current token, set by nextToken().
- */
public Token token() {
return token;
}
- /** Sets the current token.
- * This method is primarily used to update the token stream when the
- * parser is handling the end of nested type arguments such as
- * {@code List<List<String>>} and needs to disambiguate between
- * repeated use of ">" and relation operators such as ">>" and ">>>". Noting
- * that this does not handle arbitrary tokens containing Unicode escape
- * sequences.
- */
- public void token(Token token) {
- pos += this.token.name.length() - token.name.length();
- prevEndPos = pos;
- this.token = token;
- }
-
- /** Return the current token's position: a 0-based
- * offset from beginning of the raw input stream
- * (before unicode translation)
- */
- public int pos() {
- return pos;
- }
-
- /** Return the last character position of the current token.
- */
- public int endPos() {
- return endPos;
- }
-
- /** Return the last character position of the previous token.
- */
- public int prevEndPos() {
- return prevEndPos;
+ public Token prevToken() {
+ return prevToken;
}
- /** Return the position where a lexical error occurred;
- */
- public int errPos() {
- return errPos;
- }
-
- /** Set the position where a lexical error occurred;
- */
- public void errPos(int pos) {
- errPos = pos;
- }
-
- /** Return the name of an identifier or token for the current token.
- */
- public Name name() {
- return name;
- }
-
- /** Return the radix of a numeric literal token.
- */
- public int radix() {
- return radix;
- }
-
- /** Has a @deprecated been encountered in last doc comment?
- * This needs to be reset by client with resetDeprecatedFlag.
- */
- public boolean deprecatedFlag() {
- return deprecatedFlag;
- }
-
- public void resetDeprecatedFlag() {
- deprecatedFlag = false;
- }
-
- /**
- * Returns the documentation string of the current token.
- */
- public String docComment() {
- return null;
+ public void nextToken() {
+ prevToken = token;
+ token = tokenizer.readToken();
}
- /**
- * Returns a copy of the input buffer, up to its inputLength.
- * Unicode escape sequences are not translated.
- */
- public char[] getRawCharacters() {
- char[] chars = new char[buflen];
- System.arraycopy(buf, 0, chars, 0, buflen);
- return chars;
- }
-
- /**
- * Returns a copy of a character array subset of the input buffer.
- * The returned array begins at the <code>beginIndex</code> and
- * extends to the character at index <code>endIndex - 1</code>.
- * Thus the length of the substring is <code>endIndex-beginIndex</code>.
- * This behavior is like
- * <code>String.substring(beginIndex, endIndex)</code>.
- * Unicode escape sequences are not translated.
- *
- * @param beginIndex the beginning index, inclusive.
- * @param endIndex the ending index, exclusive.
- * @throws IndexOutOfBounds if either offset is outside of the
- * array bounds
- */
- public char[] getRawCharacters(int beginIndex, int endIndex) {
- int length = endIndex - beginIndex;
- char[] chars = new char[length];
- System.arraycopy(buf, beginIndex, chars, 0, length);
- return chars;
- }
-
- public enum CommentStyle {
- LINE,
- BLOCK,
- JAVADOC,
+ public Token split() {
+ Token[] splitTokens = token.split(tokens);
+ prevToken = splitTokens[0];
+ token = splitTokens[1];
+ return token;
}
- /**
- * Called when a complete comment has been scanned. pos and endPos
- * will mark the comment boundary.
- */
- protected void processComment(CommentStyle style) {
- if (scannerDebug)
- System.out.println("processComment(" + pos
- + "," + endPos + "," + style + ")=|"
- + new String(getRawCharacters(pos, endPos))
- + "|");
+ public LineMap getLineMap() {
+ return tokenizer.getLineMap();
}
- /**
- * Called when a complete whitespace run has been scanned. pos and endPos
- * will mark the whitespace boundary.
- */
- protected void processWhiteSpace() {
- if (scannerDebug)
- System.out.println("processWhitespace(" + pos
- + "," + endPos + ")=|" +
- new String(getRawCharacters(pos, endPos))
- + "|");
+ public int errPos() {
+ return tokenizer.errPos();
}
- /**
- * Called when a line terminator has been processed.
- */
- protected void processLineTerminator() {
- if (scannerDebug)
- System.out.println("processTerminator(" + pos
- + "," + endPos + ")=|" +
- new String(getRawCharacters(pos, endPos))
- + "|");
+ public void errPos(int pos) {
+ tokenizer.errPos(pos);
}
-
- /** Build a map for translating between line numbers and
- * positions in the input.
- *
- * @return a LineMap */
- public Position.LineMap getLineMap() {
- return Position.makeLineMap(buf, buflen, false);
- }
-
}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java Sat Nov 05 00:00:43 2011 -0700
@@ -57,7 +57,7 @@
final Log log;
final Names names;
final Source source;
- final Keywords keywords;
+ final Tokens tokens;
/** Create a new scanner factory. */
protected ScannerFactory(Context context) {
@@ -65,14 +65,14 @@
this.log = Log.instance(context);
this.names = Names.instance(context);
this.source = Source.instance(context);
- this.keywords = Keywords.instance(context);
+ this.tokens = Tokens.instance(context);
}
public Scanner newScanner(CharSequence input, boolean keepDocComments) {
if (input instanceof CharBuffer) {
CharBuffer buf = (CharBuffer) input;
if (keepDocComments)
- return new DocCommentScanner(this, buf);
+ return new Scanner(this, new JavadocTokenizer(this, buf));
else
return new Scanner(this, buf);
} else {
@@ -83,7 +83,7 @@
public Scanner newScanner(char[] input, int inputLength, boolean keepDocComments) {
if (keepDocComments)
- return new DocCommentScanner(this, input, inputLength);
+ return new Scanner(this, new JavadocTokenizer(this, input, inputLength));
else
return new Scanner(this, input, inputLength);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Token.java Thu Nov 03 13:26:57 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.parser;
-
-import java.util.Locale;
-
-import com.sun.tools.javac.api.Formattable;
-import com.sun.tools.javac.api.Messages;
-
-/** An interface that defines codes for Java source tokens
- * returned from lexical analysis.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public enum Token implements Formattable {
- EOF,
- ERROR,
- IDENTIFIER,
- ABSTRACT("abstract"),
- ASSERT("assert"),
- BOOLEAN("boolean"),
- BREAK("break"),
- BYTE("byte"),
- CASE("case"),
- CATCH("catch"),
- CHAR("char"),
- CLASS("class"),
- CONST("const"),
- CONTINUE("continue"),
- DEFAULT("default"),
- DO("do"),
- DOUBLE("double"),
- ELSE("else"),
- ENUM("enum"),
- EXTENDS("extends"),
- FINAL("final"),
- FINALLY("finally"),
- FLOAT("float"),
- FOR("for"),
- GOTO("goto"),
- IF("if"),
- IMPLEMENTS("implements"),
- IMPORT("import"),
- INSTANCEOF("instanceof"),
- INT("int"),
- INTERFACE("interface"),
- LONG("long"),
- NATIVE("native"),
- NEW("new"),
- PACKAGE("package"),
- PRIVATE("private"),
- PROTECTED("protected"),
- PUBLIC("public"),
- RETURN("return"),
- SHORT("short"),
- STATIC("static"),
- STRICTFP("strictfp"),
- SUPER("super"),
- SWITCH("switch"),
- SYNCHRONIZED("synchronized"),
- THIS("this"),
- THROW("throw"),
- THROWS("throws"),
- TRANSIENT("transient"),
- TRY("try"),
- VOID("void"),
- VOLATILE("volatile"),
- WHILE("while"),
- INTLITERAL,
- LONGLITERAL,
- FLOATLITERAL,
- DOUBLELITERAL,
- CHARLITERAL,
- STRINGLITERAL,
- TRUE("true"),
- FALSE("false"),
- NULL("null"),
- LPAREN("("),
- RPAREN(")"),
- LBRACE("{"),
- RBRACE("}"),
- LBRACKET("["),
- RBRACKET("]"),
- SEMI(";"),
- COMMA(","),
- DOT("."),
- ELLIPSIS("..."),
- EQ("="),
- GT(">"),
- LT("<"),
- BANG("!"),
- TILDE("~"),
- QUES("?"),
- COLON(":"),
- EQEQ("=="),
- LTEQ("<="),
- GTEQ(">="),
- BANGEQ("!="),
- AMPAMP("&&"),
- BARBAR("||"),
- PLUSPLUS("++"),
- SUBSUB("--"),
- PLUS("+"),
- SUB("-"),
- STAR("*"),
- SLASH("/"),
- AMP("&"),
- BAR("|"),
- CARET("^"),
- PERCENT("%"),
- LTLT("<<"),
- GTGT(">>"),
- GTGTGT(">>>"),
- PLUSEQ("+="),
- SUBEQ("-="),
- STAREQ("*="),
- SLASHEQ("/="),
- AMPEQ("&="),
- BAREQ("|="),
- CARETEQ("^="),
- PERCENTEQ("%="),
- LTLTEQ("<<="),
- GTGTEQ(">>="),
- GTGTGTEQ(">>>="),
- MONKEYS_AT("@"),
- CUSTOM;
-
- Token() {
- this(null);
- }
- Token(String name) {
- this.name = name;
- }
-
- public final String name;
-
- public String toString() {
- switch (this) {
- case IDENTIFIER:
- return "token.identifier";
- case CHARLITERAL:
- return "token.character";
- case STRINGLITERAL:
- return "token.string";
- case INTLITERAL:
- return "token.integer";
- case LONGLITERAL:
- return "token.long-integer";
- case FLOATLITERAL:
- return "token.float";
- case DOUBLELITERAL:
- return "token.double";
- case ERROR:
- return "token.bad-symbol";
- case EOF:
- return "token.end-of-input";
- case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
- case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
- return "'" + name + "'";
- default:
- return name;
- }
- }
-
- public String getKind() {
- return "Token";
- }
-
- public String toString(Locale locale, Messages messages) {
- return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.parser;
+
+import java.util.Locale;
+
+import com.sun.tools.javac.api.Formattable;
+import com.sun.tools.javac.api.Messages;
+import com.sun.tools.javac.parser.Tokens.Token.Tag;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Names;
+
+/** A class that defines codes/utilities for Java source tokens
+ * returned from lexical analysis.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class Tokens {
+
+ private final Names names;
+
+ /**
+ * Keyword array. Maps name indices to Token.
+ */
+ private final TokenKind[] key;
+
+ /** The number of the last entered keyword.
+ */
+ private int maxKey = 0;
+
+ /** The names of all tokens.
+ */
+ private Name[] tokenName = new Name[TokenKind.values().length];
+
+ public static final Context.Key<Tokens> tokensKey =
+ new Context.Key<Tokens>();
+
+ public static Tokens instance(Context context) {
+ Tokens instance = context.get(tokensKey);
+ if (instance == null)
+ instance = new Tokens(context);
+ return instance;
+ }
+
+ protected Tokens(Context context) {
+ context.put(tokensKey, this);
+ names = Names.instance(context);
+
+ for (TokenKind t : TokenKind.values()) {
+ if (t.name != null)
+ enterKeyword(t.name, t);
+ else
+ tokenName[t.ordinal()] = null;
+ }
+
+ key = new TokenKind[maxKey+1];
+ for (int i = 0; i <= maxKey; i++) key[i] = TokenKind.IDENTIFIER;
+ for (TokenKind t : TokenKind.values()) {
+ if (t.name != null)
+ key[tokenName[t.ordinal()].getIndex()] = t;
+ }
+ }
+
+ private void enterKeyword(String s, TokenKind token) {
+ Name n = names.fromString(s);
+ tokenName[token.ordinal()] = n;
+ if (n.getIndex() > maxKey) maxKey = n.getIndex();
+ }
+
+ /**
+ * Create a new token given a name; if the name corresponds to a token name,
+ * a new token of the corresponding kind is returned; otherwise, an
+ * identifier token is returned.
+ */
+ TokenKind lookupKind(Name name) {
+ return (name.getIndex() > maxKey) ? TokenKind.IDENTIFIER : key[name.getIndex()];
+ }
+
+ TokenKind lookupKind(String name) {
+ return lookupKind(names.fromString(name));
+ }
+
+ /**
+ * This enum defines all tokens used by the javac scanner. A token is
+ * optionally associated with a name.
+ */
+ public enum TokenKind implements Formattable {
+ EOF(),
+ ERROR(),
+ IDENTIFIER(Tag.NAMED),
+ ABSTRACT("abstract"),
+ ASSERT("assert", Tag.NAMED),
+ BOOLEAN("boolean", Tag.NAMED),
+ BREAK("break"),
+ BYTE("byte", Tag.NAMED),
+ CASE("case"),
+ CATCH("catch"),
+ CHAR("char", Tag.NAMED),
+ CLASS("class"),
+ CONST("const"),
+ CONTINUE("continue"),
+ DEFAULT("default"),
+ DO("do"),
+ DOUBLE("double", Tag.NAMED),
+ ELSE("else"),
+ ENUM("enum", Tag.NAMED),
+ EXTENDS("extends"),
+ FINAL("final"),
+ FINALLY("finally"),
+ FLOAT("float", Tag.NAMED),
+ FOR("for"),
+ GOTO("goto"),
+ IF("if"),
+ IMPLEMENTS("implements"),
+ IMPORT("import"),
+ INSTANCEOF("instanceof"),
+ INT("int", Tag.NAMED),
+ INTERFACE("interface"),
+ LONG("long", Tag.NAMED),
+ NATIVE("native"),
+ NEW("new"),
+ PACKAGE("package"),
+ PRIVATE("private"),
+ PROTECTED("protected"),
+ PUBLIC("public"),
+ RETURN("return"),
+ SHORT("short", Tag.NAMED),
+ STATIC("static"),
+ STRICTFP("strictfp"),
+ SUPER("super", Tag.NAMED),
+ SWITCH("switch"),
+ SYNCHRONIZED("synchronized"),
+ THIS("this", Tag.NAMED),
+ THROW("throw"),
+ THROWS("throws"),
+ TRANSIENT("transient"),
+ TRY("try"),
+ VOID("void", Tag.NAMED),
+ VOLATILE("volatile"),
+ WHILE("while"),
+ INTLITERAL(Tag.NUMERIC),
+ LONGLITERAL(Tag.NUMERIC),
+ FLOATLITERAL(Tag.NUMERIC),
+ DOUBLELITERAL(Tag.NUMERIC),
+ CHARLITERAL(Tag.NUMERIC),
+ STRINGLITERAL(Tag.STRING),
+ TRUE("true", Tag.NAMED),
+ FALSE("false", Tag.NAMED),
+ NULL("null", Tag.NAMED),
+ LPAREN("("),
+ RPAREN(")"),
+ LBRACE("{"),
+ RBRACE("}"),
+ LBRACKET("["),
+ RBRACKET("]"),
+ SEMI(";"),
+ COMMA(","),
+ DOT("."),
+ ELLIPSIS("..."),
+ EQ("="),
+ GT(">"),
+ LT("<"),
+ BANG("!"),
+ TILDE("~"),
+ QUES("?"),
+ COLON(":"),
+ EQEQ("=="),
+ LTEQ("<="),
+ GTEQ(">="),
+ BANGEQ("!="),
+ AMPAMP("&&"),
+ BARBAR("||"),
+ PLUSPLUS("++"),
+ SUBSUB("--"),
+ PLUS("+"),
+ SUB("-"),
+ STAR("*"),
+ SLASH("/"),
+ AMP("&"),
+ BAR("|"),
+ CARET("^"),
+ PERCENT("%"),
+ LTLT("<<"),
+ GTGT(">>"),
+ GTGTGT(">>>"),
+ PLUSEQ("+="),
+ SUBEQ("-="),
+ STAREQ("*="),
+ SLASHEQ("/="),
+ AMPEQ("&="),
+ BAREQ("|="),
+ CARETEQ("^="),
+ PERCENTEQ("%="),
+ LTLTEQ("<<="),
+ GTGTEQ(">>="),
+ GTGTGTEQ(">>>="),
+ MONKEYS_AT("@"),
+ CUSTOM;
+
+ public final String name;
+ public final Tag tag;
+
+ TokenKind() {
+ this(null, Tag.DEFAULT);
+ }
+
+ TokenKind(String name) {
+ this(name, Tag.DEFAULT);
+ }
+
+ TokenKind(Tag tag) {
+ this(null, tag);
+ }
+
+ TokenKind(String name, Tag tag) {
+ this.name = name;
+ this.tag = tag;
+ }
+
+ public String toString() {
+ switch (this) {
+ case IDENTIFIER:
+ return "token.identifier";
+ case CHARLITERAL:
+ return "token.character";
+ case STRINGLITERAL:
+ return "token.string";
+ case INTLITERAL:
+ return "token.integer";
+ case LONGLITERAL:
+ return "token.long-integer";
+ case FLOATLITERAL:
+ return "token.float";
+ case DOUBLELITERAL:
+ return "token.double";
+ case ERROR:
+ return "token.bad-symbol";
+ case EOF:
+ return "token.end-of-input";
+ case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
+ case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
+ return "'" + name + "'";
+ default:
+ return name;
+ }
+ }
+
+ public String getKind() {
+ return "Token";
+ }
+
+ public String toString(Locale locale, Messages messages) {
+ return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
+ }
+ }
+
+ /**
+ * This is the class representing a javac token. Each token has several fields
+ * that are set by the javac lexer (i.e. start/end position, string value, etc).
+ */
+ public static class Token {
+
+ /** tags constants **/
+ enum Tag {
+ DEFAULT,
+ NAMED,
+ STRING,
+ NUMERIC;
+ }
+
+ /** The token kind */
+ public final TokenKind kind;
+
+ /** The start position of this token */
+ public final int pos;
+
+ /** The end position of this token */
+ public final int endPos;
+
+ /** Is this token preceeded by a deprecated comment? */
+ public final boolean deprecatedFlag;
+
+ /** Is this token preceeded by a deprecated comment? */
+ public String docComment;
+
+ Token(TokenKind kind, int pos, int endPos,
+ boolean deprecatedFlag) {
+ this.kind = kind;
+ this.pos = pos;
+ this.endPos = endPos;
+ this.deprecatedFlag = deprecatedFlag;
+ checkKind();
+ }
+
+ Token[] split(Tokens tokens) {
+ if (kind.name.length() < 2 || kind.tag != Tag.DEFAULT) {
+ throw new AssertionError("Cant split" + kind);
+ }
+
+ TokenKind t1 = tokens.lookupKind(kind.name.substring(0, 1));
+ TokenKind t2 = tokens.lookupKind(kind.name.substring(1));
+
+ if (t1 == null || t2 == null) {
+ throw new AssertionError("Cant split - bad subtokens");
+ }
+ return new Token[] {
+ new Token(t1, pos, pos + t1.name.length(), deprecatedFlag),
+ new Token(t2, pos + t1.name.length(), endPos, false)
+ };
+ }
+
+ protected void checkKind() {
+ if (kind.tag != Tag.DEFAULT) {
+ throw new AssertionError("Bad token kind - expected " + Tag.STRING);
+ }
+ }
+
+ public Name name() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String stringVal() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int radix() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ final static class NamedToken extends Token {
+ /** The name of this token */
+ public final Name name;
+
+ public NamedToken(TokenKind kind, int pos, int endPos, Name name, boolean deprecatedFlag) {
+ super(kind, pos, endPos, deprecatedFlag);
+ this.name = name;
+ }
+
+ protected void checkKind() {
+ if (kind.tag != Tag.NAMED) {
+ throw new AssertionError("Bad token kind - expected " + Tag.NAMED);
+ }
+ }
+
+ @Override
+ public Name name() {
+ return name;
+ }
+ }
+
+ static class StringToken extends Token {
+ /** The string value of this token */
+ public final String stringVal;
+
+ public StringToken(TokenKind kind, int pos, int endPos, String stringVal, boolean deprecatedFlag) {
+ super(kind, pos, endPos, deprecatedFlag);
+ this.stringVal = stringVal;
+ }
+
+ protected void checkKind() {
+ if (kind.tag != Tag.STRING) {
+ throw new AssertionError("Bad token kind - expected " + Tag.STRING);
+ }
+ }
+
+ @Override
+ public String stringVal() {
+ return stringVal;
+ }
+ }
+
+ final static class NumericToken extends StringToken {
+ /** The 'radix' value of this token */
+ public final int radix;
+
+ public NumericToken(TokenKind kind, int pos, int endPos, String stringVal, int radix, boolean deprecatedFlag) {
+ super(kind, pos, endPos, stringVal, deprecatedFlag);
+ this.radix = radix;
+ }
+
+ protected void checkKind() {
+ if (kind.tag != Tag.NUMERIC) {
+ throw new AssertionError("Bad token kind - expected " + Tag.NUMERIC);
+ }
+ }
+
+ @Override
+ public int radix() {
+ return radix;
+ }
+ }
+
+ public static final Token DUMMY =
+ new Token(TokenKind.ERROR, 0, 0, false);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.parser;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import java.nio.CharBuffer;
+import com.sun.tools.javac.util.Log;
+import static com.sun.tools.javac.util.LayoutCharacters.*;
+
+/** The char reader used by the javac lexer/tokenizer. Returns the sequence of
+ * characters contained in the input stream, handling unicode escape accordingly.
+ * Additionally, it provide features for saving chars into a buffer and to retrieve
+ * them at a later stage.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class UnicodeReader {
+
+ /** The input buffer, index of next character to be read,
+ * index of one past last character in buffer.
+ */
+ protected char[] buf;
+ protected int bp;
+ protected final int buflen;
+
+ /** The current character.
+ */
+ protected char ch;
+
+ /** The buffer index of the last converted unicode character
+ */
+ protected int unicodeConversionBp = -1;
+
+ protected Log log;
+
+ /**
+ * Create a scanner from the input array. This method might
+ * modify the array. To avoid copying the input array, ensure
+ * that {@code inputLength < input.length} or
+ * {@code input[input.length -1]} is a white space character.
+ *
+ * @param fac the factory which created this Scanner
+ * @param input the input, might be modified
+ * @param inputLength the size of the input.
+ * Must be positive and less than or equal to input.length.
+ */
+ protected UnicodeReader(ScannerFactory sf, CharBuffer buffer) {
+ this(sf, JavacFileManager.toArray(buffer), buffer.limit());
+ }
+
+ protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
+ log = sf.log;
+ if (inputLength == input.length) {
+ if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
+ inputLength--;
+ } else {
+ char[] newInput = new char[inputLength + 1];
+ System.arraycopy(input, 0, newInput, 0, input.length);
+ input = newInput;
+ }
+ }
+ buf = input;
+ buflen = inputLength;
+ buf[buflen] = EOI;
+ bp = -1;
+ scanChar();
+ }
+
+ /** Read next character.
+ */
+ protected void scanChar() {
+ if (bp < buflen) {
+ ch = buf[++bp];
+ if (ch == '\\') {
+ convertUnicode();
+ }
+ }
+ }
+
+ /** Convert unicode escape; bp points to initial '\' character
+ * (Spec 3.3).
+ */
+ protected void convertUnicode() {
+ if (ch == '\\' && unicodeConversionBp != bp) {
+ bp++; ch = buf[bp];
+ if (ch == 'u') {
+ do {
+ bp++; ch = buf[bp];
+ } while (ch == 'u');
+ int limit = bp + 3;
+ if (limit < buflen) {
+ int d = digit(bp, 16);
+ int code = d;
+ while (bp < limit && d >= 0) {
+ bp++; ch = buf[bp];
+ d = digit(bp, 16);
+ code = (code << 4) + d;
+ }
+ if (d >= 0) {
+ ch = (char)code;
+ unicodeConversionBp = bp;
+ return;
+ }
+ }
+ log.error(bp, "illegal.unicode.esc");
+ } else {
+ bp--;
+ ch = '\\';
+ }
+ }
+ }
+
+ /** Are surrogates supported?
+ */
+ final static boolean surrogatesSupported = surrogatesSupported();
+ private static boolean surrogatesSupported() {
+ try {
+ Character.isHighSurrogate('a');
+ return true;
+ } catch (NoSuchMethodError ex) {
+ return false;
+ }
+ }
+
+ /** Scan surrogate pairs. If 'ch' is a high surrogate and
+ * the next character is a low surrogate, then put the low
+ * surrogate in 'ch', and return the high surrogate.
+ * otherwise, just return 0.
+ */
+ protected char scanSurrogates() {
+ if (surrogatesSupported && Character.isHighSurrogate(ch)) {
+ char high = ch;
+
+ scanChar();
+
+ if (Character.isLowSurrogate(ch)) {
+ return high;
+ }
+
+ ch = high;
+ }
+
+ return 0;
+ }
+
+ /** Convert an ASCII digit from its base (8, 10, or 16)
+ * to its value.
+ */
+ protected int digit(int pos, int base) {
+ char c = ch;
+ int result = Character.digit(c, base);
+ if (result >= 0 && c > 0x7f) {
+ log.error(pos + 1, "illegal.nonascii.digit");
+ ch = "0123456789abcdef".charAt(result);
+ }
+ return result;
+ }
+
+ protected boolean isUnicode() {
+ return unicodeConversionBp == bp;
+ }
+
+ protected void skipChar() {
+ bp++;
+ }
+
+ protected char peekChar() {
+ return buf[bp + 1];
+ }
+
+ /**
+ * Returns a copy of the input buffer, up to its inputLength.
+ * Unicode escape sequences are not translated.
+ */
+ public char[] getRawCharacters() {
+ char[] chars = new char[buflen];
+ System.arraycopy(buf, 0, chars, 0, buflen);
+ return chars;
+ }
+
+ /**
+ * Returns a copy of a character array subset of the input buffer.
+ * The returned array begins at the <code>beginIndex</code> and
+ * extends to the character at index <code>endIndex - 1</code>.
+ * Thus the length of the substring is <code>endIndex-beginIndex</code>.
+ * This behavior is like
+ * <code>String.substring(beginIndex, endIndex)</code>.
+ * Unicode escape sequences are not translated.
+ *
+ * @param beginIndex the beginning index, inclusive.
+ * @param endIndex the ending index, exclusive.
+ * @throws IndexOutOfBounds if either offset is outside of the
+ * array bounds
+ */
+ public char[] getRawCharacters(int beginIndex, int endIndex) {
+ int length = endIndex - beginIndex;
+ char[] chars = new char[length];
+ System.arraycopy(buf, beginIndex, chars, 0, length);
+ return chars;
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Sat Nov 05 00:00:43 2011 -0700
@@ -1072,9 +1072,9 @@
Assert.checkNonNull(names);
next.put(Names.namesKey, names);
- Keywords keywords = Keywords.instance(context);
- Assert.checkNonNull(keywords);
- next.put(Keywords.keywordsKey, keywords);
+ Tokens tokens = Tokens.instance(context);
+ Assert.checkNonNull(tokens);
+ next.put(Tokens.tokensKey, tokens);
JavaCompiler oldCompiler = JavaCompiler.instance(context);
JavaCompiler nextCompiler = JavaCompiler.instance(next);
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Sat Nov 05 00:00:43 2011 -0700
@@ -1944,6 +1944,55 @@
(use -source 7 or higher to enable strings in switch)
########################################
+# Diagnostics for verbose resolution
+# used by Resolve (debug only)
+########################################
+
+# 0: number, 1: symbol, 2: unused
+compiler.misc.applicable.method.found=\
+ #{0} applicable method found: {1}
+
+# 0: number, 1: symbol, 2: message segment
+compiler.misc.applicable.method.found.1=\
+ #{0} applicable method found: {1}\n\
+ ({2})
+
+# 0: number, 1: symbol, 2: message segment
+compiler.misc.not.applicable.method.found=\
+ #{0} not applicable method found: {1}\n\
+ ({2})
+
+# 0: type
+compiler.misc.full.inst.sig=\
+ fully instantiated to: {0}
+
+# 0: type
+compiler.misc.partial.inst.sig=\
+ partially instantiated to: {0}
+
+# 0: name, 1: symbol, 2: number, 3: MethodResolutionPhase, 4: list of type or message segment, 5: list of type or message segment
+compiler.note.verbose.resolve.multi=\
+ resolving method {0} in type {1} to candidate {2}\n\
+ phase: {3}\n\
+ with actuals: {4}\n\
+ with type-args: {5}\n\
+ candidates:
+
+# 0: name, 1: symbol, 2: unused, 3: MethodResolutionPhase, 4: list of type or message segment, 5: list of type or message segment
+compiler.note.verbose.resolve.multi.1=\
+ erroneous resolution for method {0} in type {1}\n\
+ phase: {3}\n\
+ with actuals: {4}\n\
+ with type-args: {5}\n\
+ candidates:
+
+# 0: symbol, 1: type, 2: type
+compiler.note.deferred.method.inst=\
+ Deferred instantiation of method {0}\n\
+ instantiated signature: {1}\n\
+ target-type: {2}
+
+########################################
# Diagnostics for where clause implementation
# used by the RichDiagnosticFormatter.
########################################
--- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java Sat Nov 05 00:00:43 2011 -0700
@@ -25,11 +25,6 @@
package com.sun.tools.javac.util;
-import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.main.JavacOption;
-import com.sun.tools.javac.main.OptionName;
-import com.sun.tools.javac.main.RecognizedOptions;
-import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
@@ -54,6 +49,15 @@
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
+import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.FSInfo;
+import com.sun.tools.javac.file.Locations;
+import com.sun.tools.javac.main.JavacOption;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.main.RecognizedOptions;
+import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+
/**
* Utility methods for building a filemanager.
* There are no references here to file-system specific objects such as
@@ -63,15 +67,21 @@
protected BaseFileManager(Charset charset) {
this.charset = charset;
byteBufferCache = new ByteBufferCache();
+ locations = createLocations();
}
/**
* Set the context for JavacPathFileManager.
*/
- protected void setContext(Context context) {
+ public void setContext(Context context) {
log = Log.instance(context);
options = Options.instance(context);
classLoaderClass = options.get("procloader");
+ locations.update(log, options, Lint.instance(context), FSInfo.instance(context));
+ }
+
+ protected Locations createLocations() {
+ return new Locations();
}
/**
@@ -88,6 +98,8 @@
protected String classLoaderClass;
+ protected Locations locations;
+
protected Source getSource() {
String sourceName = options.get(OptionName.SOURCE);
Source source = null;
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Sat Nov 05 00:00:43 2011 -0700
@@ -80,7 +80,7 @@
cpString = appendPath(System.getProperty("env.class.path"), cpString);
cpString = appendPath(System.getProperty("java.class.path"), cpString);
cpString = appendPath(docletPath, cpString);
- URL[] urls = com.sun.tools.javac.file.Paths.pathToURLs(cpString);
+ URL[] urls = com.sun.tools.javac.file.Locations.pathToURLs(cpString);
if (docletParentClassLoader == null)
appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
else
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Sat Nov 05 00:00:43 2011 -0700
@@ -39,7 +39,6 @@
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.comp.Annotate;
-import com.sun.tools.javac.parser.DocCommentScanner;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/7102515/T7102515.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,11 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 7102515
+ * @summary javac running very very long and not returning
+ * @compile/fail/ref=T7102515.out -XDrawDiagnostics T7102515.java
+ */
+
+class T7102515 {
+ T7102515 badBinary = new T7102515() + new T7102515();
+ Object badUnary = badBinary++;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/7102515/T7102515.out Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,3 @@
+T7102515.java:9:41: compiler.err.operator.cant.be.applied.1: +, T7102515, T7102515
+T7102515.java:10:32: compiler.err.operator.cant.be.applied: ++, T7102515, null
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T7093325.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7093325
+ * @summary Redundant entry in bytecode exception table
+ */
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.javac.api.JavacTool;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+
+public class T7093325 {
+
+ /** global decls ***/
+
+ // Create a single file manager and reuse it for each compile to save time.
+ static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
+
+ //statistics
+ static int checkCount = 0;
+
+ enum StatementKind {
+ THROW("throw new RuntimeException();", false, false),
+ RETURN_NONEMPTY("System.out.println(); return;", true, false),
+ RETURN_EMPTY("return;", true, true),
+ APPLY("System.out.println();", true, false);
+
+ String stmt;
+ boolean canInline;
+ boolean empty;
+
+ private StatementKind(String stmt, boolean canInline, boolean empty) {
+ this.stmt = stmt;
+ this.canInline = canInline;
+ this.empty = empty;
+ }
+ }
+
+ enum CatchArity {
+ NONE(""),
+ ONE("catch (A a) { #S1 }"),
+ TWO("catch (B b) { #S2 }"),
+ THREE("catch (C c) { #S3 }"),
+ FOUR("catch (D d) { #S4 }");
+
+ String catchStr;
+
+ private CatchArity(String catchStr) {
+ this.catchStr = catchStr;
+ }
+
+ String catchers() {
+ if (this.ordinal() == 0) {
+ return catchStr;
+ } else {
+ return CatchArity.values()[this.ordinal() - 1].catchers() + catchStr;
+ }
+ }
+ }
+
+ public static void main(String... args) throws Exception {
+ for (CatchArity ca : CatchArity.values()) {
+ for (StatementKind stmt0 : StatementKind.values()) {
+ if (ca.ordinal() == 0) {
+ new T7093325(ca, stmt0).compileAndCheck();
+ continue;
+ }
+ for (StatementKind stmt1 : StatementKind.values()) {
+ if (ca.ordinal() == 1) {
+ new T7093325(ca, stmt0, stmt1).compileAndCheck();
+ continue;
+ }
+ for (StatementKind stmt2 : StatementKind.values()) {
+ if (ca.ordinal() == 2) {
+ new T7093325(ca, stmt0, stmt1, stmt2).compileAndCheck();
+ continue;
+ }
+ for (StatementKind stmt3 : StatementKind.values()) {
+ if (ca.ordinal() == 3) {
+ new T7093325(ca, stmt0, stmt1, stmt2, stmt3).compileAndCheck();
+ continue;
+ }
+ for (StatementKind stmt4 : StatementKind.values()) {
+ if (ca.ordinal() == 4) {
+ new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4).compileAndCheck();
+ continue;
+ }
+ for (StatementKind stmt5 : StatementKind.values()) {
+ new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4, stmt5).compileAndCheck();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ System.out.println("Total checks made: " + checkCount);
+ }
+
+ /** instance decls **/
+
+ CatchArity ca;
+ StatementKind[] stmts;
+
+ public T7093325(CatchArity ca, StatementKind... stmts) {
+ this.ca = ca;
+ this.stmts = stmts;
+ }
+
+ void compileAndCheck() throws Exception {
+ final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+ JavaSource source = new JavaSource();
+ JavacTask ct = (JavacTask)tool.getTask(null, fm, null,
+ null, null, Arrays.asList(source));
+ ct.call();
+ verifyBytecode(source);
+ }
+
+ void verifyBytecode(JavaSource source) {
+ checkCount++;
+ boolean lastInlined = false;
+ boolean hasCode = false;
+ int gapsCount = 0;
+ for (int i = 0; i < stmts.length ; i++) {
+ lastInlined = stmts[i].canInline;
+ hasCode = hasCode || !stmts[i].empty;
+ if (lastInlined && hasCode) {
+ hasCode = false;
+ gapsCount++;
+ }
+ }
+ if (!lastInlined) {
+ gapsCount++;
+ }
+
+ //System.out.printf("gaps %d \n %s \n", gapsCount, source.toString());
+
+ File compiledTest = new File("Test.class");
+ try {
+ ClassFile cf = ClassFile.read(compiledTest);
+ if (cf == null) {
+ throw new Error("Classfile not found: " + compiledTest.getName());
+ }
+
+ Method test_method = null;
+ for (Method m : cf.methods) {
+ if (m.getName(cf.constant_pool).equals("test")) {
+ test_method = m;
+ break;
+ }
+ }
+
+ if (test_method == null) {
+ throw new Error("Method test() not found in class Test");
+ }
+
+ Code_attribute code = null;
+ for (Attribute a : test_method.attributes) {
+ if (a.getName(cf.constant_pool).equals(Attribute.Code)) {
+ code = (Code_attribute)a;
+ break;
+ }
+ }
+
+ if (code == null) {
+ throw new Error("Code attribute not found in method test()");
+ }
+
+ int actualGapsCount = 0;
+ for (int i = 0; i < code.exception_table_langth ; i++) {
+ int catchType = code.exception_table[i].catch_type;
+ if (catchType == 0) { //any
+ actualGapsCount++;
+ }
+ }
+
+ if (actualGapsCount != gapsCount) {
+ throw new Error("Bad exception table for test()\n" +
+ "expected gaps: " + gapsCount + "\n" +
+ "found gaps: " + actualGapsCount + "\n" +
+ source);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("error reading " + compiledTest +": " + e);
+ }
+
+ }
+
+ class JavaSource extends SimpleJavaFileObject {
+
+ static final String source_template =
+ "class A extends RuntimeException {} \n" +
+ "class B extends RuntimeException {} \n" +
+ "class C extends RuntimeException {} \n" +
+ "class D extends RuntimeException {} \n" +
+ "class E extends RuntimeException {} \n" +
+ "class Test {\n" +
+ " void test() {\n" +
+ " try { #S0 } #C finally { System.out.println(); }\n" +
+ " }\n" +
+ "}";
+
+ String source;
+
+ public JavaSource() {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ source = source_template.replace("#C", ca.catchers());
+ source = source.replace("#S0", stmts[0].stmt);
+ for (int i = 1; i < ca.ordinal() + 1; i++) {
+ source = source.replace("#S" + i, stmts[i].stmt);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return source;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+}
--- a/langtools/test/tools/javac/api/TestJavacTaskScanner.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/test/tools/javac/api/TestJavacTaskScanner.java Sat Nov 05 00:00:43 2011 -0700
@@ -32,6 +32,7 @@
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.parser.*;
+import com.sun.tools.javac.parser.Tokens.Token;
import com.sun.tools.javac.util.*;
import java.io.*;
import java.net.*;
@@ -93,7 +94,7 @@
check(numTokens, "#Tokens", 1222);
check(numParseTypeElements, "#parseTypeElements", 136);
- check(numAllMembers, "#allMembers", 67);
+ check(numAllMembers, "#allMembers", 52);
}
void check(int value, String name, int expected) {
@@ -206,7 +207,8 @@
public void nextToken() {
super.nextToken();
- System.err.format("Saw token %s (%s)%n", token(), name());
+ Token tk = token();
+ System.err.format("Saw token %s %n", tk.kind);
test.numTokens++;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/depDocComment/DeprecatedDocComment3.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7096014
+ * @summary Javac tokens should retain state
+ * @compile -Xlint -Werror DeprecatedDocComment3.java
+ */
+
+class DeprecatedDocComment3 {
+ static class Foo { }
+
+ ; /** @deprecated */ ;
+
+ static class A {}
+
+ static class B {
+ A a; //not deprecated!
+ }
+}
--- a/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java Sat Nov 05 00:00:43 2011 -0700
@@ -35,7 +35,7 @@
import com.sun.tools.javac.file.*;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.parser.Token;
+import com.sun.tools.javac.parser.Tokens.TokenKind;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
import javax.lang.model.SourceVersion;
@@ -319,7 +319,7 @@
return "modifier";
if (o instanceof KindName)
return "symbol kind";
- if (o instanceof Token)
+ if (o instanceof TokenKind)
return "token";
if (o instanceof Symbol)
return "symbol";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.applicable.method.found
+// key: compiler.note.verbose.resolve.multi
+// options: -XDverboseResolution=applicable,success
+
+class ApplicableMethodFound {
+
+ void m() {}
+
+ { m(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.misc.full.inst.sig
+// options: -XDverboseResolution=applicable,success
+
+class ApplicableMethodFound1 {
+
+ <X> void m(X x) {}
+
+ { m(1); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DeferredMethodInst.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.note.deferred.method.inst
+// key: compiler.misc.partial.inst.sig
+// options: -XDverboseResolution=applicable,success,deferred-inference
+
+class DeferredMethodInst {
+
+ <X> X m() { return null; }
+
+ { Integer i = m(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/FullInstSig.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.misc.full.inst.sig
+// options: -XDverboseResolution=applicable,success
+
+class FullInstSig {
+
+ <X> void m(X x) {}
+
+ { m(1); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.not.applicable.method.found
+// key: compiler.note.verbose.resolve.multi.1
+// key: compiler.err.cant.apply.symbol.1
+// key: compiler.misc.no.conforming.assignment.exists
+// options: -XDverboseResolution=inapplicable,failure
+
+class NotApplicableMethodFound {
+
+ void m(int i) {}
+
+ { m(""); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PartialInstSig.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.applicable.method.found.1
+// key: compiler.note.verbose.resolve.multi
+// key: compiler.misc.partial.inst.sig
+// options: -XDverboseResolution=applicable,success
+
+class PartialInstSig {
+
+ <X> X m() { return null; }
+
+ { m(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.applicable.method.found
+// key: compiler.note.verbose.resolve.multi
+// options: -XDverboseResolution=applicable,success
+
+class VerboseResolveMulti {
+
+ void m() {}
+
+ { m(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.not.applicable.method.found
+// key: compiler.note.verbose.resolve.multi.1
+// key: compiler.err.cant.apply.symbol.1
+// key: compiler.misc.no.conforming.assignment.exists
+// options: -XDverboseResolution=inapplicable,failure
+
+class VerboseResolveMulti1 {
+
+ void m(int i) {}
+
+ { m(""); }
+}
--- a/langtools/test/tools/javac/javazip/Test.sh Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/test/tools/javac/javazip/Test.sh Sat Nov 05 00:00:43 2011 -0700
@@ -47,7 +47,7 @@
;;
CYGWIN* )
FS="/"
- SCR=`pwd | cygpath -d`
+ SCR=`pwd | cygpath -d -f -`
;;
Windows* )
FS="\\"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/Candidate.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@interface Candidate {
+ /**
+ * the candidate position (line/col of the method call for which this candidate
+ * is a potential overload candidate)
+ */
+ Pos pos() default @Pos(userDefined=false);
+ /**
+ * resolution phases for which this candidate is applicable
+ */
+ Phase[] applicable() default { };
+ /**
+ * is this candidate the most specific (in the resolution phases for which it
+ * is also applicable)
+ */
+ boolean mostSpecific() default false;
+ /**
+ * this candidate inferred signature (in the resolution phases for which it
+ * is also applicable, in case it corresponds to a generic method)
+ */
+ String sig() default "";
+}
+
+enum Phase {
+ BASIC("BASIC"),
+ BOX("BOX"),
+ VARARGS("VARARITY");
+
+ final String javacString;
+
+ private Phase(String javacString) {
+ this.javacString = javacString;
+ }
+
+ static Phase fromString(String s) {
+ for (Phase phase : Phase.values()) {
+ if (phase.javacString.equals(s)) {
+ return phase;
+ }
+ }
+ throw new AssertionError("Invalid resolution phase string " + s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/Pos.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target(ElementType.ANNOTATION_TYPE)
+@interface Pos {
+ long line() default -1;
+ long col() default -1;
+ boolean userDefined() default true;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/ResolveHarness.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7098660
+ * @summary Write better overload resolution/inference tests
+ * @library ../lib
+ * @build JavacTestingAbstractProcessor ResolveHarness
+ * @run main ResolveHarness
+ */
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper;
+import com.sun.tools.javac.code.Type.MethodType;
+import com.sun.tools.javac.util.JCDiagnostic;
+
+import java.io.File;
+import java.util.Set;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import static javax.tools.StandardLocation.*;
+
+public class ResolveHarness implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+ static int nerrors = 0;
+
+ static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+ public static void main(String[] args) throws Exception {
+ fm.setLocation(SOURCE_PATH,
+ Arrays.asList(new File(System.getProperty("test.src"), "tests")));
+ for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(JavaFileObject.Kind.SOURCE), true)) {
+ new ResolveHarness(jfo).check();
+ }
+ if (nerrors > 0) {
+ throw new AssertionError("Errors were found");
+ }
+ }
+
+
+ JavaFileObject jfo;
+ DiagnosticProcessor[] diagProcessors;
+ Map<ElementKey, Candidate> candidatesMap = new HashMap<ElementKey, Candidate>();
+ Set<String> declaredKeys = new HashSet<>();
+ List<Diagnostic<? extends JavaFileObject>> diags = new ArrayList<>();
+ List<ElementKey> seenCandidates = new ArrayList<>();
+
+ protected ResolveHarness(JavaFileObject jfo) {
+ this.jfo = jfo;
+ this.diagProcessors = new DiagnosticProcessor[] {
+ new VerboseResolutionNoteProcessor(),
+ new VerboseDeferredInferenceNoteProcessor(),
+ new ErrorProcessor()
+ };
+ }
+
+ protected void check() throws Exception {
+ String[] options = {
+ "-XDshouldStopPolicy=ATTR",
+ "-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference"
+ };
+
+ AbstractProcessor[] processors = { new ResolveCandidateFinder(), null };
+
+ @SuppressWarnings("unchecked")
+ DiagnosticListener<? super JavaFileObject>[] diagListeners =
+ new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) };
+
+ for (int i = 0 ; i < options.length ; i ++) {
+ JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i],
+ Arrays.asList(options[i]), null, Arrays.asList(jfo));
+ if (processors[i] != null) {
+ ct.setProcessors(Collections.singleton(processors[i]));
+ }
+ ct.analyze();
+ }
+
+ //check diags
+ for (Diagnostic<? extends JavaFileObject> diag : diags) {
+ for (DiagnosticProcessor proc : diagProcessors) {
+ if (proc.matches(diag)) {
+ proc.process(diag);
+ break;
+ }
+ }
+ }
+ //check all candidates have been used up
+ for (Map.Entry<ElementKey, Candidate> entry : candidatesMap.entrySet()) {
+ if (!seenCandidates.contains(entry.getKey())) {
+ error("Redundant @Candidate annotation on method " + entry.getKey().elem);
+ }
+ }
+ }
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ diags.add(diagnostic);
+ }
+
+ Candidate getCandidateAtPos(Element methodSym, long line, long col) {
+ Candidate c = candidatesMap.get(new ElementKey(methodSym));
+ if (c != null) {
+ Pos pos = c.pos();
+ if (!pos.userDefined() ||
+ (pos.line() == line && pos.col() == col)) {
+ seenCandidates.add(new ElementKey(methodSym));
+ return c;
+ }
+ } else {
+ error("Missing @Candidate annotation on method " + methodSym);
+ }
+ return null;
+ }
+
+ void checkSig(Candidate c, Element methodSym, MethodType mtype) {
+ if (c.sig().length() > 0 && !c.sig().equals(mtype.toString())) {
+ error("Inferred type mismatch for method: " + methodSym);
+ }
+ }
+
+ protected void error(String msg) {
+ nerrors++;
+ System.err.printf("Error occurred while checking file: %s\nreason: %s\n", jfo.getName(), msg);
+ }
+
+ /**
+ * Base class for diagnostic processor. It provides methods for matching and
+ * processing a given diagnostic object (overridden by subclasses).
+ */
+ abstract class DiagnosticProcessor {
+
+ List<String> codes;
+ Diagnostic.Kind kind;
+
+ public DiagnosticProcessor(Kind kind, String... codes) {
+ this.codes = Arrays.asList(codes);
+ this.kind = kind;
+ }
+
+ abstract void process(Diagnostic<? extends JavaFileObject> diagnostic);
+
+ boolean matches(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return (codes.isEmpty() || codes.contains(diagnostic.getCode())) &&
+ diagnostic.getKind() == kind;
+ }
+
+ JCDiagnostic asJCDiagnostic(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (diagnostic instanceof JCDiagnostic) {
+ return (JCDiagnostic)diagnostic;
+ } else if (diagnostic instanceof DiagnosticSourceUnwrapper) {
+ return ((DiagnosticSourceUnwrapper)diagnostic).d;
+ } else {
+ throw new AssertionError("Cannot convert diagnostic to JCDiagnostic: " + diagnostic.getClass().getName());
+ }
+ }
+
+ List<JCDiagnostic> subDiagnostics(Diagnostic<? extends JavaFileObject> diagnostic) {
+ JCDiagnostic diag = asJCDiagnostic(diagnostic);
+ if (diag instanceof JCDiagnostic.MultilineDiagnostic) {
+ return ((JCDiagnostic.MultilineDiagnostic)diag).getSubdiagnostics();
+ } else {
+ throw new AssertionError("Cannot extract subdiagnostics: " + diag.getClass().getName());
+ }
+ }
+ }
+
+ /**
+ * Processor for verbose resolution notes generated by javac. The processor
+ * checks that the diagnostic is associated with a method declared by
+ * a class annotated with the special @TraceResolve marker annotation. If
+ * that's the case, all subdiagnostics (one for each resolution candidate)
+ * are checked against the corresponding @Candidate annotations, using
+ * a VerboseCandidateSubdiagProcessor.
+ */
+ class VerboseResolutionNoteProcessor extends DiagnosticProcessor {
+
+ VerboseResolutionNoteProcessor() {
+ super(Kind.NOTE,
+ "compiler.note.verbose.resolve.multi",
+ "compiler.note.verbose.resolve.multi.1");
+ }
+
+ @Override
+ void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+ Element siteSym = getSiteSym(diagnostic);
+ if (siteSym.getAnnotation(TraceResolve.class) == null) {
+ return;
+ }
+ int candidateIdx = 0;
+ for (JCDiagnostic d : subDiagnostics(diagnostic)) {
+ boolean isMostSpecific = candidateIdx++ == mostSpecific(diagnostic);
+ VerboseCandidateSubdiagProcessor subProc =
+ new VerboseCandidateSubdiagProcessor(isMostSpecific, phase(diagnostic), success(diagnostic));
+ if (subProc.matches(d)) {
+ subProc.process(d);
+ } else {
+ throw new AssertionError("Bad subdiagnostic: " + d.getCode());
+ }
+ }
+ }
+
+ Element getSiteSym(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return (Element)asJCDiagnostic(diagnostic).getArgs()[1];
+ }
+
+ int mostSpecific(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return success(diagnostic) ?
+ (Integer)asJCDiagnostic(diagnostic).getArgs()[2] : -1;
+ }
+
+ boolean success(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return diagnostic.getCode().equals("compiler.note.verbose.resolve.multi");
+ }
+
+ Phase phase(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return Phase.fromString(asJCDiagnostic(diagnostic).getArgs()[3].toString());
+ }
+ }
+
+ /**
+ * Processor for verbose resolution subdiagnostic notes generated by javac.
+ * The processor checks that the details of the overload candidate
+ * match against the info contained in the corresponding @Candidate
+ * annotation (if any).
+ */
+ class VerboseCandidateSubdiagProcessor extends DiagnosticProcessor {
+
+ boolean mostSpecific;
+ Phase phase;
+ boolean success;
+
+ public VerboseCandidateSubdiagProcessor(boolean mostSpecific, Phase phase, boolean success) {
+ super(Kind.OTHER,
+ "compiler.misc.applicable.method.found",
+ "compiler.misc.applicable.method.found.1",
+ "compiler.misc.not.applicable.method.found");
+ this.mostSpecific = mostSpecific;
+ this.phase = phase;
+ this.success = success;
+ }
+
+ @Override
+ void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+ Element methodSym = methodSym(diagnostic);
+ Candidate c = getCandidateAtPos(methodSym,
+ asJCDiagnostic(diagnostic).getLineNumber(),
+ asJCDiagnostic(diagnostic).getColumnNumber());
+ if (c == null) {
+ return; //nothing to check
+ }
+
+ if (c.applicable().length == 0 && c.mostSpecific()) {
+ error("Inapplicable method cannot be most specific " + methodSym);
+ }
+
+ if (isApplicable(diagnostic) != Arrays.asList(c.applicable()).contains(phase)) {
+ error("Invalid candidate's applicability " + methodSym);
+ }
+
+ if (success) {
+ for (Phase p : c.applicable()) {
+ if (phase.ordinal() < p.ordinal()) {
+ error("Invalid phase " + p + " on method " + methodSym);
+ }
+ }
+ }
+
+ if (Arrays.asList(c.applicable()).contains(phase)) { //applicable
+ if (c.mostSpecific() != mostSpecific) {
+ error("Invalid most specific value for method " + methodSym);
+ }
+ MethodType mtype = getSig(diagnostic);
+ if (mtype != null) {
+ checkSig(c, methodSym, mtype);
+ }
+ }
+ }
+
+ boolean isApplicable(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return !diagnostic.getCode().equals("compiler.misc.not.applicable.method.found");
+ }
+
+ Element methodSym(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return (Element)asJCDiagnostic(diagnostic).getArgs()[1];
+ }
+
+ MethodType getSig(Diagnostic<? extends JavaFileObject> diagnostic) {
+ JCDiagnostic details = (JCDiagnostic)asJCDiagnostic(diagnostic).getArgs()[2];
+ if (details == null) {
+ return null;
+ } else if (details instanceof JCDiagnostic) {
+ return details.getCode().equals("compiler.misc.full.inst.sig") ?
+ (MethodType)details.getArgs()[0] : null;
+ } else {
+ throw new AssertionError("Bad diagnostic arg: " + details);
+ }
+ }
+ }
+
+ /**
+ * Processor for verbose deferred inference notes generated by javac. The
+ * processor checks that the inferred signature for a given generic method
+ * call corresponds to the one (if any) declared in the @Candidate annotation.
+ */
+ class VerboseDeferredInferenceNoteProcessor extends DiagnosticProcessor {
+
+ public VerboseDeferredInferenceNoteProcessor() {
+ super(Kind.NOTE, "compiler.note.deferred.method.inst");
+ }
+
+ @Override
+ void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+ Element methodSym = methodSym(diagnostic);
+ Candidate c = getCandidateAtPos(methodSym,
+ asJCDiagnostic(diagnostic).getLineNumber(),
+ asJCDiagnostic(diagnostic).getColumnNumber());
+ MethodType sig = sig(diagnostic);
+ if (c != null && sig != null) {
+ checkSig(c, methodSym, sig);
+ }
+ }
+
+ Element methodSym(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return (Element)asJCDiagnostic(diagnostic).getArgs()[0];
+ }
+
+ MethodType sig(Diagnostic<? extends JavaFileObject> diagnostic) {
+ return (MethodType)asJCDiagnostic(diagnostic).getArgs()[1];
+ }
+ }
+
+ /**
+ * Processor for all error diagnostics; if the error key is not declared in
+ * the test file header, the processor reports an error.
+ */
+ class ErrorProcessor extends DiagnosticProcessor {
+
+ public ErrorProcessor() {
+ super(Diagnostic.Kind.ERROR);
+ }
+
+ @Override
+ void process(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (!declaredKeys.contains(diagnostic.getCode())) {
+ error("Unexpected compilation error key '" + diagnostic.getCode() + "'");
+ }
+ }
+ }
+
+ @SupportedAnnotationTypes({"Candidate","TraceResolve"})
+ class ResolveCandidateFinder extends JavacTestingAbstractProcessor {
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver())
+ return true;
+
+ TypeElement traceResolveAnno = elements.getTypeElement("TraceResolve");
+ TypeElement candidateAnno = elements.getTypeElement("Candidate");
+
+ if (!annotations.contains(traceResolveAnno)) {
+ error("no @TraceResolve annotation found in test class");
+ }
+
+ if (!annotations.contains(candidateAnno)) {
+ error("no @candidate annotation found in test class");
+ }
+
+ for (Element elem: roundEnv.getElementsAnnotatedWith(traceResolveAnno)) {
+ TraceResolve traceResolve = elem.getAnnotation(TraceResolve.class);
+ declaredKeys.addAll(Arrays.asList(traceResolve.keys()));
+ }
+
+ for (Element elem: roundEnv.getElementsAnnotatedWith(candidateAnno)) {
+ candidatesMap.put(new ElementKey(elem), elem.getAnnotation(Candidate.class));
+ }
+ return true;
+ }
+ }
+
+ class ElementKey {
+
+ String key;
+ Element elem;
+
+ public ElementKey(Element elem) {
+ this.elem = elem;
+ this.key = computeKey(elem);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ElementKey) {
+ ElementKey other = (ElementKey)obj;
+ return other.key.equals(key);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
+
+ String computeKey(Element e) {
+ StringBuilder buf = new StringBuilder();
+ while (e != null) {
+ buf.append(e.toString());
+ e = e.getEnclosingElement();
+ }
+ buf.append(jfo.getName());
+ return buf.toString();
+ }
+
+ @Override
+ public String toString() {
+ return "Key{"+key+"}";
+ }
+ }
+
+ class DiagnosticHandler implements DiagnosticListener<JavaFileObject> {
+
+ boolean shouldRecordDiags;
+
+ DiagnosticHandler(boolean shouldRecordDiags) {
+ this.shouldRecordDiags = shouldRecordDiags;
+ }
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (shouldRecordDiags)
+ diags.add(diagnostic);
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/TraceResolve.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@interface TraceResolve {
+ String[] keys() default {};
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/BoxedReturnTypeInference.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class BoxedReturnTypeInference {
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Byte", mostSpecific=true)
+ static <B> B m_byte() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Short", mostSpecific=true)
+ static <S> S m_short() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Integer", mostSpecific=true)
+ static <I> I m_int() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Long", mostSpecific=true)
+ static <L> L m_long() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Float", mostSpecific=true)
+ static <F> F m_float() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Double", mostSpecific=true)
+ static <D> D m_double() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Character", mostSpecific=true)
+ static <C> C m_char() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Boolean", mostSpecific=true)
+ static <Z> Z m_bool() { return null; }
+
+ {
+ Byte b = m_byte();
+ Short s = m_short();
+ Integer i = m_int();
+ Long l = m_long();
+ Float f = m_float();
+ Double d = m_double();
+ Character c= m_char();
+ Boolean z = m_bool();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverInferred.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class PrimitiveOverReference {
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_byte(byte b) {}
+ @Candidate
+ static void m_byte(Byte b) {}
+ @Candidate
+ static <B> void m_byte(B b) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_short(short s) {}
+ @Candidate
+ static void m_short(Short s) {}
+ @Candidate
+ static <S> void m_short(S s) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_int(int i) {}
+ @Candidate
+ static void m_int(Integer i) {}
+ @Candidate
+ static <I> void m_int(I i) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_long(long l) {}
+ @Candidate
+ static void m_long(Long l) {}
+ @Candidate
+ static <L> void m_long(L l) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_float(float f) {}
+ @Candidate
+ static void m_float(Float f) {}
+ @Candidate
+ static <F> void m_float(F f) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_double(double d) {}
+ @Candidate
+ static void m_double(Double d) {}
+ @Candidate
+ static <D> void m_double(D d) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_char(char c) {}
+ @Candidate
+ static void m_char(Character c) {}
+ @Candidate
+ static <C> void m_char(C c) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_bool(boolean z) {}
+ @Candidate
+ static void m_bool(Boolean z) {}
+ @Candidate
+ static <Z> void m_bool(Z z) {}
+
+ {
+ m_byte((byte)0);
+ m_short((short)0);
+ m_int(0);
+ m_long(0L);
+ m_float(0.0f);
+ m_double(0.0);
+ m_char('?');
+ m_bool(false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverVarargs.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class PrimitiveOverReference {
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_byte(byte b) {}
+ @Candidate
+ static void m_byte(Byte b) {}
+ @Candidate
+ static void m_byte(byte... b) {}
+ @Candidate
+ static void m_byte(Byte... b) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_short(short s) {}
+ @Candidate
+ static void m_short(Short s) {}
+ @Candidate
+ static void m_short(short... s) {}
+ @Candidate
+ static void m_short(Short... s) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_int(int i) {}
+ @Candidate
+ static void m_int(Integer i) {}
+ @Candidate
+ static void m_int(int... i) {}
+ @Candidate
+ static void m_int(Integer... i) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_long(long l) {}
+ @Candidate
+ static void m_long(Long l) {}
+ @Candidate
+ static void m_long(long... l) {}
+ @Candidate
+ static void m_long(Long... l) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_float(float f) {}
+ @Candidate
+ static void m_float(Float f) {}
+ @Candidate
+ static void m_float(float... f) {}
+ @Candidate
+ static void m_float(Float... f) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_double(double d) {}
+ @Candidate
+ static void m_double(Double d) {}
+ @Candidate
+ static void m_double(double... d) {}
+ @Candidate
+ static void m_double(Double... d) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_char(char c) {}
+ @Candidate
+ static void m_char(Character c) {}
+ @Candidate
+ static void m_char(char... c) {}
+ @Candidate
+ static void m_char(Character... c) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_bool(boolean z) {}
+ @Candidate
+ static void m_bool(Boolean z) {}
+ @Candidate
+ static void m_bool(boolean... z) {}
+ @Candidate
+ static void m_bool(Boolean... z) {}
+
+ {
+ m_byte((byte)0);
+ m_short((short)0);
+ m_int(0);
+ m_long(0L);
+ m_float(0.0f);
+ m_double(0.0);
+ m_char('?');
+ m_bool(false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve(keys={"compiler.err.ref.ambiguous"})
+class PrimitiveOverReferenceVarargsAmbiguous {
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_byte(byte... b) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_byte(Byte... b) {}
+
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_short(short... s) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_short(Short... s) {}
+
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_int(int... i) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_int(Integer... i) {}
+
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_long(long... l) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_long(Long... l) {}
+
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_float(float... f) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_float(Float... f) {}
+
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_double(double... d) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_double(Double... d) {}
+
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_char(char... c) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_char(Character... c) {}
+
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_bool(boolean... z) {}
+ @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+ static void m_bool(Boolean... z) {}
+
+ {
+ m_byte((byte)0);
+ m_short((short)0);
+ m_int(0);
+ m_long(0L);
+ m_float(0.0f);
+ m_double(0.0);
+ m_char('?');
+ m_bool(false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverload.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class PrimitiveOverload {
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_byte(byte b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_byte(short b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_byte(int b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_byte(long b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_byte(float b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_byte(double b) {}
+
+ @Candidate
+ static void m_short(byte b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_short(short b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_short(int b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_short(long b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_short(float b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_short(double b) {}
+
+ @Candidate
+ static void m_int(byte b) {}
+ @Candidate
+ static void m_int(short b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_int(int b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_int(long b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_int(float b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_int(double b) {}
+
+ @Candidate
+ static void m_long(byte b) {}
+ @Candidate
+ static void m_long(short b) {}
+ @Candidate
+ static void m_long(int b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_long(long b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_long(float b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_long(double b) {}
+
+ @Candidate
+ static void m_float(byte b) {}
+ @Candidate
+ static void m_float(short b) {}
+ @Candidate
+ static void m_float(int b) {}
+ @Candidate
+ static void m_float(long b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_float(float b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_float(double b) {}
+
+ @Candidate
+ static void m_double(byte b) {}
+ @Candidate
+ static void m_double(short b) {}
+ @Candidate
+ static void m_double(int b) {}
+ @Candidate
+ static void m_double(long b) {}
+ @Candidate
+ static void m_double(float b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_double(double b) {}
+
+ {
+ m_byte((byte)0);
+ m_short((short)0);
+ m_int(0);
+ m_long(0L);
+ m_float(0.0f);
+ m_double(0.0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/PrimitiveReturnTypeInference.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class PrimitiveReturnTypeInference {
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Byte", mostSpecific=true)
+ static <B> B m_byte() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Short", mostSpecific=true)
+ static <S> S m_short() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Integer", mostSpecific=true)
+ static <I> I m_int() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Long", mostSpecific=true)
+ static <L> L m_long() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Float", mostSpecific=true)
+ static <F> F m_float() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Double", mostSpecific=true)
+ static <D> D m_double() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Character", mostSpecific=true)
+ static <C> C m_char() { return null; }
+
+ @Candidate(applicable=Phase.BASIC, sig="()java.lang.Boolean", mostSpecific=true)
+ static <Z> Z m_bool() { return null; }
+
+ {
+ byte b = m_byte();
+ short s = m_short();
+ int i = m_int();
+ long l = m_long();
+ float f = m_float();
+ double d = m_double();
+ char c= m_char();
+ boolean z = m_bool();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverInferred.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class PrimitiveOverInferred {
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_byte(Byte b) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Byte)void")
+ static <B> void m_byte(B b) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_short(Short s) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Short)void")
+ static <S> void m_short(S s) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_int(Integer i) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Integer)void")
+ static <I> void m_int(I i) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_long(Long l) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Long)void")
+ static <L> void m_long(L l) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_float(Float f) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Float)void")
+ static <F> void m_float(F f) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_double(Double d) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Double)void")
+ static <D> void m_double(D d) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_char(Character c) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Character)void")
+ static <C> void m_char(C c) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_bool(Boolean z) {}
+ @Candidate(applicable=Phase.BOX, sig="(java.lang.Boolean)void")
+ static <Z> void m_bool(Z z) {}
+
+ {
+ m_byte((byte)0);
+ m_short((short)0);
+ m_int(0);
+ m_long(0L);
+ m_float(0.0f);
+ m_double(0.0);
+ m_char('?');
+ m_bool(false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverVarargs.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class ReferenceOverVarargs {
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_byte(Byte b) {}
+ @Candidate
+ static void m_byte(byte... b) {}
+ @Candidate
+ static void m_byte(Byte... b) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_short(Short s) {}
+ @Candidate
+ static void m_short(short... s) {}
+ @Candidate
+ static void m_short(Short... s) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_int(Integer i) {}
+ @Candidate
+ static void m_int(int... i) {}
+ @Candidate
+ static void m_int(Integer... i) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_long(Long l) {}
+ @Candidate
+ static void m_long(long... l) {}
+ @Candidate
+ static void m_long(Long... l) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_float(Float f) {}
+ @Candidate
+ static void m_float(float... f) {}
+ @Candidate
+ static void m_float(Float... f) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_double(Double d) {}
+ @Candidate
+ static void m_double(double... d) {}
+ @Candidate
+ static void m_double(Double... d) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_char(Character c) {}
+ @Candidate
+ static void m_char(char... c) {}
+ @Candidate
+ static void m_char(Character... c) {}
+
+ @Candidate(applicable=Phase.BOX, mostSpecific=true)
+ static void m_bool(Boolean z) {}
+ @Candidate
+ static void m_bool(boolean... z) {}
+ @Candidate
+ static void m_bool(Boolean... z) {}
+
+ {
+ m_byte((byte)0);
+ m_short((short)0);
+ m_int(0);
+ m_long(0L);
+ m_float(0.0f);
+ m_double(0.0);
+ m_char('?');
+ m_bool(false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverload.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@TraceResolve
+class ReferenceOverload {
+
+ static class A {}
+ static class B extends A {}
+ static class C extends B {}
+ static class D extends C {}
+ static class E extends D {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_A(A a) {}
+ @Candidate
+ static void m_A(B a) {}
+ @Candidate
+ static void m_A(C a) {}
+ @Candidate
+ static void m_A(D a) {}
+ @Candidate
+ static void m_A(E a) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_B(A b) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_B(B b) {}
+ @Candidate
+ static void m_B(C b) {}
+ @Candidate
+ static void m_B(D b) {}
+ @Candidate
+ static void m_B(E b) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_C(A c) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_C(B c) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_C(C c) {}
+ @Candidate
+ static void m_C(D c) {}
+ @Candidate
+ static void m_C(E c) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_D(A d) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_D(B d) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_D(C d) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_D(D d) {}
+ @Candidate
+ static void m_D(E d) {}
+
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_E(A e) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_E(B e) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_E(C e) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=false)
+ static void m_E(D e) {}
+ @Candidate(applicable=Phase.BASIC, mostSpecific=true)
+ static void m_E(E e) {}
+
+ {
+ m_A((A)null);
+ m_B((B)null);
+ m_C((C)null);
+ m_D((D)null);
+ m_E((E)null);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/tree/DocCommentToplevelTest.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7096014
+ * @summary Javac tokens should retain state
+ */
+
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
+import com.sun.tools.javac.tree.JCTree;
+
+import java.net.URI;
+import java.util.*;
+import javax.tools.*;
+
+
+public class DocCommentToplevelTest {
+
+ enum PackageKind {
+ HAS_PKG("package pkg;"),
+ NO_PKG("");
+
+ String pkgStr;
+
+ PackageKind(String pkgStr) {
+ this.pkgStr = pkgStr;
+ }
+ }
+
+ enum ImportKind {
+ ZERO(""),
+ ONE("import java.lang.*;"),
+ TWO("import java.lang.*; import java.util.*;");
+
+ String importStr;
+
+ ImportKind(String importStr) {
+ this.importStr = importStr;
+ }
+ }
+
+ enum ModifierKind {
+ DEFAULT(""),
+ PUBLIC("public");
+
+ String modStr;
+
+ ModifierKind(String modStr) {
+ this.modStr = modStr;
+ }
+ }
+
+ enum ToplevelDocKind {
+ HAS_DOC("/** Toplevel! */"),
+ NO_DOC("");
+
+ String docStr;
+
+ ToplevelDocKind(String docStr) {
+ this.docStr = docStr;
+ }
+ }
+
+ static int errors;
+ static int checks;
+
+ public static void main(String... args) throws Exception {
+ //create default shared JavaCompiler - reused across multiple compilations
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+ for (PackageKind pk : PackageKind.values()) {
+ for (ImportKind ik : ImportKind.values()) {
+ for (ModifierKind mk1 : ModifierKind.values()) {
+ for (ModifierKind mk2 : ModifierKind.values()) {
+ for (ToplevelDocKind tdk : ToplevelDocKind.values()) {
+ new DocCommentToplevelTest(pk, ik, mk1, mk2, tdk).run(comp, fm);
+ }
+ }
+ }
+ }
+ }
+
+ if (errors > 0)
+ throw new AssertionError(errors + " errors found");
+
+ System.out.println(checks + " checks were made");
+ }
+
+ PackageKind pk;
+ ImportKind ik;
+ ModifierKind mk1;
+ ModifierKind mk2;
+ ToplevelDocKind tdk;
+ JavaSource source;
+
+ DocCommentToplevelTest(PackageKind pk, ImportKind ik, ModifierKind mk1, ModifierKind mk2, ToplevelDocKind tdk) {
+ this.pk = pk;
+ this.ik = ik;
+ this.mk1 = mk1;
+ this.mk2 = mk2;
+ this.tdk = tdk;
+ source = new JavaSource();
+ }
+
+ void run(JavaCompiler comp, JavaFileManager fm) throws Exception {
+ JavacTask task = (JavacTask)comp.getTask(null, fm, null, Arrays.asList("-printsource"), null, Arrays.asList(source));
+ for (CompilationUnitTree cu: task.parse()) {
+ check(cu);
+ }
+ }
+
+ void check(CompilationUnitTree cu) {
+ checks++;
+
+ new TreeScanner<ClassTree,Void>() {
+
+ Map<JCTree, String> docComments;
+
+ @Override
+ public ClassTree visitCompilationUnit(CompilationUnitTree node, Void unused) {
+ docComments = ((JCTree.JCCompilationUnit)node).docComments;
+ boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC &&
+ (pk != PackageKind.NO_PKG || ik != ImportKind.ZERO);
+ boolean foundComment = docComments.get(node) != null;
+ if (expectedComment != foundComment) {
+ error("Unexpected comment " + docComments.get(node) + " on toplevel");
+ }
+ return super.visitCompilationUnit(node, null);
+ }
+
+ @Override
+ public ClassTree visitClass(ClassTree node, Void unused) {
+ boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC &&
+ pk == PackageKind.NO_PKG && ik == ImportKind.ZERO &&
+ node.getSimpleName().toString().equals("First");
+ boolean foundComment = docComments.get(node) != null;
+ if (expectedComment != foundComment) {
+ error("Unexpected comment " + docComments.get(node) + " on class " + node.getSimpleName());
+ }
+ return super.visitClass(node, unused);
+ }
+ }.scan(cu, null);
+ }
+
+ void error(String msg) {
+ System.err.println("Error: " + msg);
+ System.err.println("Source: " + source.source);
+ errors++;
+ }
+
+ class JavaSource extends SimpleJavaFileObject {
+
+ String template = "#D\n#P\n#I\n" +
+ "#M1 class First { }\n" +
+ "#M2 class Second { }\n";
+
+ String source;
+
+ public JavaSource() {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ source = template.replace("#P", pk.pkgStr)
+ .replace("#I", ik.importStr)
+ .replace("#M1", mk1.modStr)
+ .replace("#M2", mk2.modStr)
+ .replace("#D", tdk.docStr);
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/7097436/T7097436.java Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 7097436
+ * @summary ClassCastException occurs in assignment expressions without any heap pollutions
+ * @compile/fail/ref=T7097436.out -Xlint:varargs -Werror -XDrawDiagnostics T7097436.java
+ */
+
+import java.util.List;
+
+class T7097436 {
+ @SafeVarargs
+ static void m(List<String>... ls) {
+ Object o = ls; //warning
+ Object[] oArr = ls; //warning
+ String s = ls; // no warning
+ Integer[] iArr = ls; // no warning
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/7097436/T7097436.out Sat Nov 05 00:00:43 2011 -0700
@@ -0,0 +1,6 @@
+T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls
+T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls
+T7097436.java:15:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List<java.lang.String>[], java.lang.String
+T7097436.java:16:26: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List<java.lang.String>[], java.lang.Integer[]
+2 errors
+2 warnings
--- a/langtools/test/tools/javac/varargs/warning/Warn5.java Thu Nov 03 13:26:57 2011 -0700
+++ b/langtools/test/tools/javac/varargs/warning/Warn5.java Sat Nov 05 00:00:43 2011 -0700
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6993978
+ * @bug 6993978 7097436
* @summary Project Coin: Annotation to reduce varargs warnings
* @author mcimadamore
* @run main Warn5
@@ -31,8 +31,8 @@
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;
import java.net.URI;
-import java.util.ArrayList;
import java.util.Arrays;
+import java.util.EnumSet;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
@@ -95,7 +95,6 @@
METHOD("void m"),
CONSTRUCTOR("Test");
-
String name;
MethodKind(String name) {
@@ -155,7 +154,124 @@
}
}
- static class JavaSource extends SimpleJavaFileObject {
+ enum WarningKind {
+ UNSAFE_BODY,
+ UNSAFE_DECL,
+ MALFORMED_SAFEVARARGS,
+ REDUNDANT_SAFEVARARGS;
+ }
+
+ // Create a single file manager and reuse it for each compile to save time.
+ static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
+
+ public static void main(String... args) throws Exception {
+ for (SourceLevel sourceLevel : SourceLevel.values()) {
+ for (XlintOption xlint : XlintOption.values()) {
+ for (TrustMe trustMe : TrustMe.values()) {
+ for (SuppressLevel suppressLevel : SuppressLevel.values()) {
+ for (ModifierKind modKind : ModifierKind.values()) {
+ for (MethodKind methKind : MethodKind.values()) {
+ for (SignatureKind sig : SignatureKind.values()) {
+ for (BodyKind body : BodyKind.values()) {
+ new Warn5(sourceLevel,
+ xlint,
+ trustMe,
+ suppressLevel,
+ modKind,
+ methKind,
+ sig,
+ body).test();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ final SourceLevel sourceLevel;
+ final XlintOption xlint;
+ final TrustMe trustMe;
+ final SuppressLevel suppressLevel;
+ final ModifierKind modKind;
+ final MethodKind methKind;
+ final SignatureKind sig;
+ final BodyKind body;
+ final JavaSource source;
+ final DiagnosticChecker dc;
+
+ public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) {
+ this.sourceLevel = sourceLevel;
+ this.xlint = xlint;
+ this.trustMe = trustMe;
+ this.suppressLevel = suppressLevel;
+ this.modKind = modKind;
+ this.methKind = methKind;
+ this.sig = sig;
+ this.body = body;
+ this.source = new JavaSource();
+ this.dc = new DiagnosticChecker();
+ }
+
+ void test() throws Exception {
+ final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+ JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
+ Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source));
+ ct.analyze();
+ check();
+ }
+
+ void check() {
+
+ EnumSet<WarningKind> expectedWarnings = EnumSet.noneOf(WarningKind.class);
+
+ if (sourceLevel == SourceLevel.JDK_7 &&
+ trustMe == TrustMe.TRUST &&
+ suppressLevel != SuppressLevel.VARARGS &&
+ xlint != XlintOption.NONE &&
+ sig.isVarargs && !sig.isReifiableArg && body.hasAliasing &&
+ (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE))) {
+ expectedWarnings.add(WarningKind.UNSAFE_BODY);
+ }
+
+ if (sourceLevel == SourceLevel.JDK_7 &&
+ trustMe == TrustMe.DONT_TRUST &&
+ sig.isVarargs &&
+ !sig.isReifiableArg &&
+ xlint == XlintOption.ALL) {
+ expectedWarnings.add(WarningKind.UNSAFE_DECL);
+ }
+
+ if (sourceLevel == SourceLevel.JDK_7 &&
+ trustMe == TrustMe.TRUST &&
+ (!sig.isVarargs ||
+ (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD))) {
+ expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS);
+ }
+
+ if (sourceLevel == SourceLevel.JDK_7 &&
+ trustMe == TrustMe.TRUST &&
+ xlint != XlintOption.NONE &&
+ suppressLevel != SuppressLevel.VARARGS &&
+ (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) &&
+ sig.isVarargs &&
+ sig.isReifiableArg) {
+ expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS);
+ }
+
+ if (!expectedWarnings.containsAll(dc.warnings) ||
+ !dc.warnings.containsAll(expectedWarnings)) {
+ throw new Error("invalid diagnostics for source:\n" +
+ source.getCharContent(true) +
+ "\nOptions: " + xlint.getXlintOption() +
+ "\nExpected warnings: " + expectedWarnings +
+ "\nFound warnings: " + dc.warnings);
+ }
+ }
+
+ class JavaSource extends SimpleJavaFileObject {
String template = "import com.sun.tools.javac.api.*;\n" +
"import java.util.List;\n" +
@@ -167,12 +283,11 @@
String source;
- public JavaSource(TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
- MethodKind methKind, SignatureKind meth, BodyKind body) {
+ public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = template.replace("#T", trustMe.anno).
replace("#S", suppressLevel.getSuppressAnno()).
- replace("#M", meth.getSignature(modKind, methKind)).
+ replace("#M", sig.getSignature(modKind, methKind)).
replace("#B", body.body);
}
@@ -182,117 +297,34 @@
}
}
- public static void main(String... args) throws Exception {
- for (SourceLevel sourceLevel : SourceLevel.values()) {
- for (XlintOption xlint : XlintOption.values()) {
- for (TrustMe trustMe : TrustMe.values()) {
- for (SuppressLevel suppressLevel : SuppressLevel.values()) {
- for (ModifierKind modKind : ModifierKind.values()) {
- for (MethodKind methKind : MethodKind.values()) {
- for (SignatureKind sig : SignatureKind.values()) {
- for (BodyKind body : BodyKind.values()) {
- test(sourceLevel,
- xlint,
- trustMe,
- suppressLevel,
- modKind,
- methKind,
- sig,
- body);
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- // Create a single file manager and reuse it for each compile to save time.
- static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
-
- static void test(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel,
- ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) throws Exception {
- final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
- JavaSource source = new JavaSource(trustMe, suppressLevel, modKind, methKind, sig, body);
- DiagnosticChecker dc = new DiagnosticChecker();
- JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
- Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source));
- ct.analyze();
- check(sourceLevel, dc, source, xlint, trustMe,
- suppressLevel, modKind, methKind, sig, body);
- }
-
- static void check(SourceLevel sourceLevel, DiagnosticChecker dc, JavaSource source,
- XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
- MethodKind methKind, SignatureKind meth, BodyKind body) {
+ class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
- boolean hasPotentiallyUnsafeBody = sourceLevel == SourceLevel.JDK_7 &&
- trustMe == TrustMe.TRUST &&
- suppressLevel != SuppressLevel.VARARGS &&
- xlint != XlintOption.NONE &&
- meth.isVarargs && !meth.isReifiableArg && body.hasAliasing &&
- (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE));
-
- boolean hasPotentiallyPollutingDecl = sourceLevel == SourceLevel.JDK_7 &&
- trustMe == TrustMe.DONT_TRUST &&
- meth.isVarargs &&
- !meth.isReifiableArg &&
- xlint == XlintOption.ALL;
-
- boolean hasMalformedAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
- trustMe == TrustMe.TRUST &&
- (!meth.isVarargs ||
- (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD));
-
- boolean hasRedundantAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
- trustMe == TrustMe.TRUST &&
- xlint != XlintOption.NONE &&
- suppressLevel != SuppressLevel.VARARGS &&
- (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) &&
- meth.isVarargs &&
- meth.isReifiableArg;
-
- if (hasPotentiallyUnsafeBody != dc.hasPotentiallyUnsafeBody ||
- hasPotentiallyPollutingDecl != dc.hasPotentiallyPollutingDecl ||
- hasMalformedAnnoInDecl != dc.hasMalformedAnnoInDecl ||
- hasRedundantAnnoInDecl != dc.hasRedundantAnnoInDecl) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nOptions: " + xlint.getXlintOption() +
- "\nExpected potentially unsafe body warning: " + hasPotentiallyUnsafeBody +
- "\nExpected potentially polluting decl warning: " + hasPotentiallyPollutingDecl +
- "\nExpected malformed anno error: " + hasMalformedAnnoInDecl +
- "\nExpected redundant anno warning: " + hasRedundantAnnoInDecl +
- "\nFound potentially unsafe body warning: " + dc.hasPotentiallyUnsafeBody +
- "\nFound potentially polluting decl warning: " + dc.hasPotentiallyPollutingDecl +
- "\nFound malformed anno error: " + dc.hasMalformedAnnoInDecl +
- "\nFound redundant anno warning: " + dc.hasRedundantAnnoInDecl);
- }
- }
-
- static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean hasPotentiallyUnsafeBody = false;
- boolean hasPotentiallyPollutingDecl = false;
- boolean hasMalformedAnnoInDecl = false;
- boolean hasRedundantAnnoInDecl = false;
+ EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class);
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
if (diagnostic.getCode().contains("unsafe.use.varargs.param")) {
- hasPotentiallyUnsafeBody = true;
+ setWarning(WarningKind.UNSAFE_BODY);
} else if (diagnostic.getCode().contains("redundant.trustme")) {
- hasRedundantAnnoInDecl = true;
+ setWarning(WarningKind.REDUNDANT_SAFEVARARGS);
}
} else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
diagnostic.getCode().contains("varargs.non.reifiable.type")) {
- hasPotentiallyPollutingDecl = true;
+ setWarning(WarningKind.UNSAFE_DECL);
} else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
diagnostic.getCode().contains("invalid.trustme")) {
- hasMalformedAnnoInDecl = true;
+ setWarning(WarningKind.MALFORMED_SAFEVARARGS);
}
}
+
+ void setWarning(WarningKind wk) {
+ if (!warnings.add(wk)) {
+ throw new AssertionError("Duplicate warning of kind " + wk + " in source:\n" + source);
+ }
+ }
+
+ boolean hasWarning(WarningKind wk) {
+ return warnings.contains(wk);
+ }
}
}