udpate jdt.core to I20220414-1800
- incl. freshly generated block in PublicScanner
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
index 42e5eac..b224014 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -312,6 +312,8 @@
return JavaCore.VERSION_16;
} else if(rawVersion.startsWith("17")) {
return JavaCore.VERSION_17;
+ } else if(rawVersion.startsWith("18")) {
+ return JavaCore.VERSION_18;
} else {
throw new RuntimeException("unknown javac version: " + rawVersion);
}
@@ -509,6 +511,20 @@
return 0200;
}
}
+ if (version == JavaCore.VERSION_18) {
+ if ("18-ea".equals(rawVersion)) {
+ return 0000;
+ }
+ if ("18".equals(rawVersion)) {
+ return 0000;
+ }
+ if ("18.0.1".equals(rawVersion)) {
+ return 0100;
+ }
+ if ("18.0.2".equals(rawVersion)) {
+ return 0200;
+ }
+ }
throw new RuntimeException("unknown raw javac version: " + rawVersion);
}
// returns 0L if everything went fine; else the lower word contains the
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index 2f90961..8bfd1e7 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -34,6 +34,7 @@
* Jesper Steen Moller - Contributions for
* bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code
* bug 407297 - [1.8][compiler] Control generation of parameter names by option
+ * bug 413873 - Warning "Method can be static" on method referencing a non-static inner class
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -13384,4 +13385,28 @@
template = template.replace("15", CompilerOptions.getLatestVersion());
assertEquals("configure.source is not updated", template, output);
}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=413873
+public void test413873() {
+ this.runConformTest(
+ new String[] {
+ "OuterClass.java",
+ "public class OuterClass<T> {\n" +
+ " private final class InnerClass {\n" +
+ " }\n" +
+ "\n" +
+ " private InnerClass foo(final InnerClass object) {\n" +
+ " return object;\n" +
+ " }\n" +
+ " \n" +
+ " public void doStuff() {\n" +
+ " foo(new InnerClass());\n" +
+ " }\n" +
+ "}"
+ },
+ "\"" + OUTPUT_DIR + File.separator + "OuterClass.java\""
+ + " -1.6 -warn:all-static-method -proc:none -d none",
+ "",
+ "",
+ true);
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
index bcda3c9..59aeb0c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2021 IBM Corporation and others.
+ * Copyright (c) 2016, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -5634,4 +5634,257 @@
"2 problems (2 errors)\n",
false);
}
+ /*
+ * Test that reference to a binary package that is exported in a module
+ * but doesn't have a corresponding resource or .class files is reported.
+ */
+ public void testBug522472a() {
+ File outputDirectory = new File(OUTPUT_DIR);
+ Util.flushDirectoryContent(outputDirectory);
+ String out = "bin";
+ String directory = OUTPUT_DIR + File.separator + "src";
+ File srcDir = new File(directory);
+ String moduleLoc = directory + File.separator + "mod.one";
+ List<String> files = new ArrayList<>();
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.one { \n" +
+ " exports x.y.z;\n" +
+ " exports a.b.c;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "x" + File.separator + "y" + File.separator + "z",
+ "X.java",
+ "package x.y.z;\n");
+ writeFileCollecting(files, moduleLoc + File.separator + "a" + File.separator + "b" + File.separator + "c",
+ "A.java",
+ "package a.b.c;\n" +
+ "public class A {}");
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+ .append(" -9 ")
+ .append(" -classpath \"")
+ .append(Util.getJavaClassLibsAsString())
+ .append("\" ")
+ .append(" --module-source-path " + "\"" + directory + "\" ");
+
+ runConformModuleTest(files,
+ buffer,
+ "",
+ "",
+ false);
+
+ Util.flushDirectoryContent(srcDir);
+ files.clear();
+ moduleLoc = directory + File.separator + "mod.two";
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.two { \n" +
+ " requires mod.one;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "r",
+ "Main.java",
+ "package p.q.r;\n" +
+ "import a.b.c.*;\n" +
+ "import x.y.z.*;\n" +
+ "public class Main {"
+ + "}");
+ buffer = new StringBuffer();
+ buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+ .append(" -9 ")
+ .append(" -classpath \"")
+ .append(Util.getJavaClassLibsAsString())
+ .append("\" ")
+ .append(" --module-path " + "\"" + OUTPUT_DIR + File.separator + out + "\" ")
+ .append(" --module-source-path " + "\"" + directory + "\" ");
+ runConformModuleTest(files,
+ buffer,
+ "",
+ "----------\n"
+ + "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/p/q/r/Main.java (at line 2)\n"
+ + " import a.b.c.*;\n"
+ + " ^^^^^\n"
+ + "The import a.b.c is never used\n"
+ + "----------\n"
+ + "2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/p/q/r/Main.java (at line 3)\n"
+ + " import x.y.z.*;\n"
+ + " ^^^^^\n"
+ + "The import x.y.z is never used\n"
+ + "----------\n"
+ + "2 problems (2 warnings)\n",
+ false,
+ "package conflict");
+ }
+ /*
+ * Same as above test case, but two binary modules export the package, without any .class files
+ */
+ public void testBug522472b() {
+ File outputDirectory = new File(OUTPUT_DIR);
+ Util.flushDirectoryContent(outputDirectory);
+ String out = "bin";
+ String directory = OUTPUT_DIR + File.separator + "src";
+ File srcDir = new File(directory);
+ String moduleLoc = directory + File.separator + "mod.one";
+ List<String> files = new ArrayList<>();
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.one { \n" +
+ " exports x.y.z;\n" +
+ " exports a.b.c;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "x" + File.separator + "y" + File.separator + "z",
+ "X.java",
+ "package x.y.z;\n");
+ writeFileCollecting(files, moduleLoc + File.separator + "a" + File.separator + "b" + File.separator + "c",
+ "A.java",
+ "package a.b.c;\n" +
+ "public class A {}");
+
+ moduleLoc = directory + File.separator + "mod.one.a";
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.one.a { \n" +
+ " exports x.y.z;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "x" + File.separator + "y" + File.separator + "z",
+ "X.java",
+ "package x.y.z;\n");
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+ .append(" -9 ")
+ .append(" -classpath \"")
+ .append(Util.getJavaClassLibsAsString())
+ .append("\" ")
+ .append(" --module-source-path " + "\"" + directory + "\" ");
+
+ runConformModuleTest(files,
+ buffer,
+ "",
+ "",
+ false);
+
+ Util.flushDirectoryContent(srcDir);
+ files.clear();
+ moduleLoc = directory + File.separator + "mod.two";
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.two { \n" +
+ " requires mod.one;\n" +
+ " requires mod.one.a;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "r",
+ "Main.java",
+ "package p.q.r;\n" +
+ "import a.b.c.*;\n" +
+ "import x.y.z.*;\n" +
+ "public class Main {"
+ + "}");
+ buffer = new StringBuffer();
+ buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+ .append(" -9 ")
+ .append(" -classpath \"")
+ .append(Util.getJavaClassLibsAsString())
+ .append("\" ")
+ .append(" --module-path " + "\"" + OUTPUT_DIR + File.separator + out + "\" ")
+ .append(" --module-source-path " + "\"" + directory + "\" ");
+ runNegativeModuleTest(files,
+ buffer,
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/module-info.java (at line 2)\n" +
+ " requires mod.one;\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The package x.y.z is accessible from more than one module: mod.one, mod.one.a\n" +
+ "----------\n" +
+ "2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/module-info.java (at line 3)\n" +
+ " requires mod.one.a;\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The package x.y.z is accessible from more than one module: mod.one, mod.one.a\n" +
+ "----------\n" +
+ "----------\n" +
+ "3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/p/q/r/Main.java (at line 3)\n" +
+ " import x.y.z.*;\n" +
+ " ^^^^^\n" +
+ "The import x.y.z cannot be resolved\n" +
+ "----------\n" +
+ "3 problems (3 errors)\n",
+ false,
+ "package conflict");
+ }
+ public void testBug522472d() {
+ File outputDirectory = new File(OUTPUT_DIR);
+ Util.flushDirectoryContent(outputDirectory);
+ String out = "bin";
+ String directory = OUTPUT_DIR + File.separator + "src";
+ String moduleLoc = directory + File.separator + "mod.one";
+ List<String> files = new ArrayList<>();
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.one { \n" +
+ " exports x.y.z;\n" +
+ " exports a.b.c;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "x" + File.separator + "y" + File.separator + "z",
+ "X.java",
+ "package x.y.z;\n");
+ writeFileCollecting(files, moduleLoc + File.separator + "a" + File.separator + "b" + File.separator + "c",
+ "A.java",
+ "package a.b.c;\n" +
+ "public class A {}");
+
+ moduleLoc = directory + File.separator + "mod.one.a";
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.one.a { \n" +
+ " exports x.y.z;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "x" + File.separator + "y" + File.separator + "z",
+ "X.java",
+ "package x.y.z;\n");
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+ .append(" -9 ")
+ .append(" -classpath \"")
+ .append(Util.getJavaClassLibsAsString())
+ .append("\" ")
+ .append(" --module-source-path " + "\"" + directory + "\" ");
+
+ moduleLoc = directory + File.separator + "mod.two";
+ writeFileCollecting(files, moduleLoc,
+ "module-info.java",
+ "module mod.two { \n" +
+ " requires mod.one;\n" +
+ " requires mod.one.a;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "r",
+ "Main.java",
+ "package p.q.r;\n" +
+ "import a.b.c.*;\n" +
+ "import x.y.z.*;\n" +
+ "public class Main {"
+ + "}");
+
+ runNegativeModuleTest(files,
+ buffer,
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/module-info.java (at line 2)\n" +
+ " requires mod.one;\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The package x.y.z is accessible from more than one module: mod.one, mod.one.a\n" +
+ "----------\n" +
+ "2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/module-info.java (at line 3)\n" +
+ " requires mod.one.a;\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The package x.y.z is accessible from more than one module: mod.one, mod.one.a\n" +
+ "----------\n" +
+ "----------\n" +
+ "3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/p/q/r/Main.java (at line 3)\n" +
+ " import x.y.z.*;\n" +
+ " ^^^^^\n" +
+ "The package x.y.z is accessible from more than one module: mod.one, mod.one.a\n" +
+ "----------\n" +
+ "3 problems (3 errors)\n",
+ false,
+ "conflict");
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
index 8dc580b..593becf 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
@@ -6585,10 +6585,10 @@
"}\n"
},
"----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " this(Z::new);\n" +
- " ^^^^^^\n" +
- "No enclosing instance of the type X.Y is accessible in scope\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " interface I {\n" +
+ " ^\n" +
+ "No enclosing instance of type X.Y is available due to some intermediate constructor invocation\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=406586, [1.8][compiler] Missing error about unavailable enclosing instance
@@ -6608,10 +6608,10 @@
"}\n"
},
"----------\n" +
- "1. ERROR in X.java (at line 8)\n" +
- " I i = Y::new;\n" +
- " ^^^^^^\n" +
- "No enclosing instance of the type X is accessible in scope\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " interface I {\n" +
+ " ^\n" +
+ "No enclosing instance of type X is accessible. Must qualify the allocation with an enclosing instance of type X (e.g. x.new A() where x is an instance of X).\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=401989, [1.8][compiler] hook lambda expressions into "can be static" analysis
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PreviewFeatureTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PreviewFeatureTest.java
index be0f9c1..d7ace63 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PreviewFeatureTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PreviewFeatureTest.java
@@ -12,11 +12,15 @@
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
+import java.io.File;
+import java.io.IOException;
import java.util.Map;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.JavaFeature;
+import org.eclipse.jdt.core.tests.util.Util;
import junit.framework.Test;
@@ -45,6 +49,54 @@
}
return options;
}
+ private String[] getClasspathWithPreviewAPI() {
+ File libDir = new File(LIB_DIR);
+ Util.delete(libDir); // make sure we recycle the libs
+ libDir.mkdirs();
+ String jarPath = LIB_DIR + "/lib1.jar";
+ try {
+ Util.createJar(
+ new String[] {
+ "jdk/internal/javac/PreviewFeature.java",
+ "package jdk.internal.javac;\n"
+ + "import java.lang.annotation.*;\n"
+ + "@Target({ElementType.METHOD,\n"
+ + " ElementType.CONSTRUCTOR,\n"
+ + " ElementType.FIELD,\n"
+ + " ElementType.PACKAGE,\n"
+ + " ElementType.MODULE,\n"
+ + " ElementType.TYPE})\n"
+ + "@Retention(RetentionPolicy.CLASS)\n"
+ + "public @interface PreviewFeature {\n"
+ + " public Feature feature();\n"
+ + " public enum Feature {\n"
+ + " /**\n"
+ + " * A key for testing.\n"
+ + " */\n"
+ + " TEST;\n"
+ + " }\n"
+ + "}",
+ "p/ABC.java",
+ "package p;\n"
+ + "import jdk.internal.javac.PreviewFeature;\n"
+ + "@PreviewFeature(feature=PreviewFeature.Feature.TEST)\n"
+ + "public class ABC {\n"
+ + " @PreviewFeature(feature=PreviewFeature.Feature.TEST)\n"
+ + " public void doSomething() {}\n"
+ + "}"
+ },
+ jarPath,
+ JavaCore.VERSION_9);
+ } catch (IOException e) {
+ // ignore
+ }
+ String [] javaClassLibs = Util.getJavaClassLibs();
+ int javaClassLibsLength;
+ String [] xClassLibs = new String[(javaClassLibsLength = javaClassLibs.length) + 1];
+ System.arraycopy(javaClassLibs, 0, xClassLibs, 0, javaClassLibsLength);
+ xClassLibs[javaClassLibsLength] = jarPath;
+ return xClassLibs;
+ }
/*
* Preview API, --enable-preview=false, SuppressWarning=No
*/
@@ -52,6 +104,7 @@
if (this.complianceLevel >= ClassFileConstants.JDK17) {
return;
}
+ String[] classLibs = getClasspathWithPreviewAPI();
Map<String, String> options = getCompilerOptions();
String old = options.get(CompilerOptions.OPTION_EnablePreviews);
options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
@@ -59,16 +112,14 @@
runNegativeTest(
new String[] {
"X.java",
- "import javax.lang.model.element.Modifier;\n"+
+ "import p.*;\n"+
"public class X {\n"+
- " Zork z = null;\n" +
- "public Modifier getModifier() {\n"+
- " return Modifier.SEALED;\n"+
- " }\n"+
- " public Class<?>[] getPermittedClasses() {\n"+
- " return this.getClass().getPermittedSubclasses();\n"+
- " }\n"+
- "}\n",
+ " Zork z = null;\n" +
+ " ABC abc = null;\n" +
+ " public void foo () {\n"+
+ " (new ABC()).doSomething();\n"+
+ " }\n"+
+ "}\n",
},
"----------\n" +
"1. ERROR in X.java (at line 3)\n" +
@@ -76,17 +127,12 @@
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n" +
- "2. WARNING in X.java (at line 5)\n" +
- " return Modifier.SEALED;\n" +
- " ^^^^^^^^^^^^^^^\n" +
- "You are using an API that is part of a preview feature and may be removed in future\n" +
- "----------\n" +
- "3. WARNING in X.java (at line 8)\n" +
- " return this.getClass().getPermittedSubclasses();\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "2. WARNING in X.java (at line 6)\n" +
+ " (new ABC()).doSomething();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"You are using an API that is part of a preview feature and may be removed in future\n" +
"----------\n",
- null,
+ classLibs,
true,
options);
} finally {
@@ -103,20 +149,19 @@
Map<String, String> options = getCompilerOptions();
String old = options.get(CompilerOptions.OPTION_EnablePreviews);
options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
+ String[] classLibs = getClasspathWithPreviewAPI();
try {
runNegativeTest(
new String[] {
"X.java",
- "import javax.lang.model.element.Modifier;\n"+
+ "import p.*;\n"+
"@SuppressWarnings(\"preview\")\n"+
"public class X {\n"+
" Zork z = null;\n" +
- "public Modifier getModifier() {\n"+
- " return Modifier.SEALED;\n"+
- " }\n"+
- " public Class<?>[] getPermittedClasses() {\n"+
- " return this.getClass().getPermittedSubclasses();\n"+
- " }\n"+
+ " ABC abc = null;\n" +
+ " public void foo () {\n"+
+ " (new ABC()).doSomething();\n"+
+ " }\n"+
"}\n",
},
"----------\n" +
@@ -125,7 +170,7 @@
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n",
- null,
+ classLibs,
true,
options);
} finally {
@@ -141,19 +186,18 @@
Map<String, String> options = getCompilerOptions();
String old = options.get(CompilerOptions.OPTION_EnablePreviews);
options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ String[] classLibs = getClasspathWithPreviewAPI();
try {
runNegativeTest(
new String[] {
"X.java",
- "import javax.lang.model.element.Modifier;\n"+
+ "import p.*;\n"+
"public class X {\n"+
" Zork z = null;\n" +
- "public Modifier getModifier() {\n"+
- " return Modifier.SEALED;\n"+
- " }\n"+
- " public Class<?>[] getPermittedClasses() {\n"+
- " return this.getClass().getPermittedSubclasses();\n"+
- " }\n"+
+ " ABC abc = null;\n" +
+ " public void foo () {\n"+
+ " (new ABC()).doSomething();\n"+
+ " }\n"+
"}\n",
},
"----------\n" +
@@ -162,7 +206,7 @@
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n",
- null,
+ classLibs,
true,
options);
} finally {
@@ -178,20 +222,19 @@
Map<String, String> options = getCompilerOptions();
String old = options.get(CompilerOptions.OPTION_EnablePreviews);
options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ String[] classLibs = getClasspathWithPreviewAPI();
try {
runNegativeTest(
new String[] {
"X.java",
- "import javax.lang.model.element.Modifier;\n"+
+ "import p.*;\n"+
"@SuppressWarnings(\"preview\")\n"+
"public class X {\n"+
" Zork z = null;\n" +
- "public Modifier getModifier() {\n"+
- " return Modifier.SEALED;\n"+
- " }\n"+
- " public Class<?>[] getPermittedClasses() {\n"+
- " return this.getClass().getPermittedSubclasses();\n"+
- " }\n"+
+ " ABC abc = null;\n" +
+ " public void foo () {\n"+
+ " (new ABC()).doSomething();\n"+
+ " }\n"+
"}\n",
},
"----------\n" +
@@ -200,7 +243,7 @@
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n",
- null,
+ classLibs,
true,
options);
} finally {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PublicScannerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PublicScannerTest.java
new file mode 100644
index 0000000..7f41f28
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PublicScannerTest.java
@@ -0,0 +1,334 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Andrey Loskutov and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Andrey Loskutov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.core.compiler.ITerminalSymbols;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.core.util.PublicScanner;
+
+import junit.framework.Test;
+
+/**
+ * Test that validates {@link Scanner} and {@link PublicScanner} use of tokens.
+ */
+@SuppressWarnings({ "rawtypes" })
+public class PublicScannerTest extends AbstractRegressionTest {
+
+ private Map<Integer, String> ttValueToName;
+ private Map<String, Integer> ttNameToValue;
+ private Field[] ttFields;
+ private Map<Integer, String> tsValueToName;
+ private Map<String, Integer> tsNameToValue;
+ private Field[] tsFields;
+ private MyPublicScanner ps;
+
+ /**
+ * Replacement map for tokens that shouldn't be exposed to clients
+ * Key is the token, value is the replacement token
+ */
+ static final Map<Integer, Integer> SYNTHETIC_REPLACE_TOKENS;
+
+ /**
+ * Replacement list for tokens that shouldn't be exposed to clients and scanner should
+ * skip to next token
+ */
+ static final List<Integer> SYNTHETIC_SKIP_TOKENS;
+
+ /**
+ * List of tokens that shouldn't be exposed to clients because they can never be
+ * produced without declaring the source to be "module-info.java".
+ */
+ static final List<Integer> MODULE_TOKENS;
+
+ static {
+ Map<Integer, Integer> map = new HashMap<>();
+ map.put(TerminalTokens.TokenNameAT308DOTDOTDOT, TerminalTokens.TokenNameAT);
+ map.put(TerminalTokens.TokenNameAT308, TerminalTokens.TokenNameAT);
+//{ObjectTeams:
+ map.put(TerminalTokens.TokenNameATOT, TerminalTokens.TokenNameAT);
+// SH}
+ SYNTHETIC_REPLACE_TOKENS = Collections.unmodifiableMap(map);
+
+ List<Integer> list = new ArrayList<>();
+ list.add(TerminalTokens.TokenNameBeginCaseElement);
+ list.add(TerminalTokens.TokenNameBeginCaseExpr);
+ list.add(TerminalTokens.TokenNameBeginIntersectionCast);
+ list.add(TerminalTokens.TokenNameBeginLambda);
+ list.add(TerminalTokens.TokenNameBeginTypeArguments);
+ list.add(TerminalTokens.TokenNameElidedSemicolonAndRightBrace);
+ SYNTHETIC_SKIP_TOKENS = Collections.unmodifiableList(list);
+
+ list = new ArrayList<>();
+ list.add(TerminalTokens.TokenNamemodule);
+ list.add(TerminalTokens.TokenNamerequires);
+ list.add(TerminalTokens.TokenNameexports);
+ list.add(TerminalTokens.TokenNameto);
+ list.add(TerminalTokens.TokenNameopen);
+ list.add(TerminalTokens.TokenNameopens);
+ list.add(TerminalTokens.TokenNameprovides);
+ list.add(TerminalTokens.TokenNamewith);
+ list.add(TerminalTokens.TokenNametransitive);
+ list.add(TerminalTokens.TokenNameuses);
+ MODULE_TOKENS = Collections.unmodifiableList(list);
+ }
+
+ public PublicScannerTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return buildAllCompliancesTestSuite(testClass());
+ }
+
+ public static Class testClass() {
+ return PublicScannerTest.class;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.ttValueToName = new TreeMap<>();
+ this.ttNameToValue = new TreeMap<>();
+ this.ttFields = TerminalTokens.class.getFields();
+ for (Field field : this.ttFields) {
+ this.ttValueToName.put(field.getInt(null), field.getName());
+ this.ttNameToValue.put(field.getName(), field.getInt(null));
+ }
+ if(this.ttValueToName.size() != this.ttNameToValue.size()) {
+ this.ttNameToValue.keySet().removeAll(this.ttValueToName.values());
+ fail("TerminalTokens constants use already defined values: " + this.ttNameToValue.keySet());
+ }
+ this.tsValueToName = new TreeMap<>();
+ this.tsNameToValue = new TreeMap<>();
+ this.tsFields = ITerminalSymbols.class.getFields();
+ for (Field field : this.tsFields) {
+ this.tsValueToName.put(field.getInt(null), field.getName());
+ this.tsNameToValue.put(field.getName(), field.getInt(null));
+ }
+ if(this.tsValueToName.size() != this.tsNameToValue.size()) {
+ this.tsNameToValue.keySet().removeAll(this.tsValueToName.values());
+ fail("ITerminalSymbols constants use already defined values: " + this.tsNameToValue.keySet());
+ }
+ this.ps = new MyPublicScanner();
+ }
+
+ /**
+ * Tests that all constants defined in @link {@link TerminalTokens} are properly handled by {@link PublicScanner#getNextToken()}
+ */
+ public void testGetNextToken() throws Exception {
+ Set<Entry<String, Integer>> entrySet = this.ttNameToValue.entrySet();
+ for (Entry<String, Integer> entry : entrySet) {
+ this.ps.reset();
+ String fieldName = entry.getKey();
+ Integer fieldValue = entry.getValue();
+ if (MODULE_TOKENS.contains(fieldValue)) {
+ continue;
+ }
+ this.ps.setNextToken(fieldValue);
+ int nextToken = -1;
+ try {
+ nextToken = this.ps.getNextToken();
+ } catch (InvalidInputException e) {
+ fail("Scanner.getNextToken() returns token unknown by PublicScanner: " + fieldName);
+ }
+
+ if(this.tsNameToValue.containsKey(fieldName)) {
+ int actual = ITerminalSymbols.class.getField(fieldName).getInt(null);
+ assertEquals("getNextToken() returns value not specified in ITerminalSymbols for token " + fieldName, actual, nextToken);
+ assertEquals(1, this.ps.nextTokenCalls);
+ } else {
+ Integer value = TerminalTokens.class.getField(fieldName).getInt(null);
+ if(SYNTHETIC_SKIP_TOKENS.contains(value)){
+ assertEquals(2, this.ps.nextTokenCalls);
+ } else {
+ assertEquals(1, this.ps.nextTokenCalls);
+ Integer target = SYNTHETIC_REPLACE_TOKENS.get(value);
+ if(target == null) {
+ fail("TerminalTokens." + fieldName + " should be added to ITerminalSymbols or SYNTHETIC_*_TOKENS in PublicScannerTest*!");
+ } else {
+ String replaceName = this.ttValueToName.get(target);
+ Integer replaceValue = this.tsNameToValue.get(replaceName);
+ assertEquals("getNextToken() returns unexpected value for " + fieldName, nextToken, replaceValue.intValue());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests that all constants defined in {@link TerminalTokens} are either defined in {@link ITerminalSymbols}
+ * or defined in {@link #SYNTHETIC_REPLACE_TOKENS}, or {@link #SYNTHETIC_SKIP_TOKENS}, or {@link #MODULE_TOKENS}
+ * and no constants defined in {@link ITerminalSymbols} are missing in {@link TerminalTokens}
+ */
+ public void testTokensAndSymbolsSync() throws Exception {
+ Set<Entry<String, Integer>> entrySet = this.tsNameToValue.entrySet();
+ for (Entry<String, Integer> entry : entrySet) {
+ String fieldName = entry.getKey();
+ if (!this.ttNameToValue.containsKey(fieldName)) {
+ fail("ITerminalSymbols." + fieldName + " does not exist in TerminalTokens");
+ }
+ }
+ entrySet = this.ttNameToValue.entrySet();
+ for (Entry<String, Integer> entry : entrySet) {
+ String fieldName = entry.getKey();
+ if(this.tsNameToValue.containsKey(fieldName)) {
+ // OK, constant present
+ } else {
+ Integer value = TerminalTokens.class.getField(fieldName).getInt(null);
+ if(SYNTHETIC_SKIP_TOKENS.contains(value) || MODULE_TOKENS.contains(value)){
+ // OK, constant present
+ } else {
+ Integer target = SYNTHETIC_REPLACE_TOKENS.get(value);
+ if(target != null) {
+ // OK, constant present
+ } else {
+ fail("TerminalTokens." + fieldName + " should be added to ITerminalSymbols or SYNTHETIC_*_TOKENS in PublicScannerTest*!");
+ }
+ }
+ }
+ }
+ }
+
+ class MyPublicScanner extends PublicScanner {
+ MyScanner delegate;
+ int nextTokenCalls;
+ boolean inNextCall;
+
+ public MyPublicScanner() {
+ super(false /* comment */,
+ false /* whitespace */,
+ false /* nls */,
+ ClassFileConstants.JDK17 /* sourceLevel */,
+ ClassFileConstants.JDK17 /* complianceLevel */,
+ null/* taskTag */,
+ null/* taskPriorities */,
+ true /* taskCaseSensitive */,
+ true,
+ true);
+ }
+
+ @Override
+ protected Scanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
+ boolean checkNonExternalizedStringLiterals, long sourceLevel, long complianceLevel1, char[][] taskTags,
+ char[][] taskPriorities, boolean isTaskCaseSensitive, boolean isPreviewEnabled) {
+ MyScanner myScanner = new MyScanner(tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, sourceLevel,
+ complianceLevel1, taskTags, taskPriorities, isTaskCaseSensitive, isPreviewEnabled);
+ this.delegate = myScanner;
+ return myScanner;
+ }
+
+ void setNextToken(int next) {
+ this.delegate.next = next;
+ }
+
+ void reset() {
+ this.delegate.next = -1;
+ this.nextTokenCalls = 0;
+ }
+
+ @Override
+ public int getNextToken() throws InvalidInputException {
+ this.nextTokenCalls ++;
+ if (this.inNextCall) {
+ return this.delegate.next;
+ } else {
+ this.inNextCall = true;
+ }
+ try {
+ return super.getNextToken();
+ } finally {
+ this.inNextCall = false;
+ }
+ }
+ }
+
+
+ class MyScanner extends Scanner {
+ int next;
+ public MyScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
+ boolean checkNonExternalizedStringLiterals, long sourceLevel, long complianceLevel, char[][] taskTags,
+ char[][] taskPriorities, boolean isTaskCaseSensitive, boolean isPreviewEnabled) {
+ super(tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, sourceLevel,
+ complianceLevel, taskTags, taskPriorities, isTaskCaseSensitive, isPreviewEnabled);
+ this.next = -1;
+ }
+
+ @Override
+ public int getNextToken() throws InvalidInputException {
+ return this.next;
+ }
+ }
+
+ /**
+ * Run this if {@link TerminalTokens} is updated and the test fails - that generates the body of the
+ * switch in the {@link PublicScanner#getNextToken()}
+ */
+ public static void main(String[] args) throws Exception {
+ printGeneratedSwitchForPublicScanner();
+ }
+
+ private static void printGeneratedSwitchForPublicScanner() throws Exception {
+ Map<Integer, String> valueToName = new TreeMap<>();
+ Map<String, Integer> nameToValue = new TreeMap<>();
+ Field[] ttFields = TerminalTokens.class.getFields();
+ for (Field field : ttFields) {
+ valueToName.put(field.getInt(null), field.getName());
+ nameToValue.put(field.getName(), field.getInt(null));
+ }
+
+ Field[] tsFields = ITerminalSymbols.class.getFields();
+ Set<String> ttNames = nameToValue.keySet();
+ Set<String> tsSet = Arrays.asList(tsFields).stream().map(x -> x.getName()).collect(Collectors.toSet());
+ StringBuilder sb = new StringBuilder();
+ String ident = "\t\t\t";
+ for (String ttName : ttNames) {
+ if(tsSet.contains(ttName)) {
+ sb.append(ident + "case TerminalTokens." + ttName + " : nextToken = ITerminalSymbols." + ttName + "; break;\n");
+ } else {
+ Integer value = TerminalTokens.class.getField(ttName).getInt(null);
+ if (MODULE_TOKENS.contains(value)) {
+ continue;
+ }
+ if(SYNTHETIC_SKIP_TOKENS.contains(value)){
+ sb.append(ident + "case TerminalTokens." + ttName + " : nextToken = getNextToken(); break;\n");
+ } else {
+ Integer target = SYNTHETIC_REPLACE_TOKENS.get(value);
+ if(target == null) {
+ sb.append("// TODO: add constant " + ttName + " to ITerminalSymbols or update SYNTHETIC_*_TOKENS in PublicScannerTest!\n");
+ sb.append("// case TerminalTokens." + ttName + " : nextToken = ITerminalSymbols." + ttName + "; break;\n");
+ } else {
+ String replaceName = valueToName.get(target);
+ sb.append(ident + "case TerminalTokens." + ttName + " : nextToken = ITerminalSymbols." + replaceName + "; break;\n");
+ }
+ }
+ }
+ }
+ System.out.println(sb);
+ }
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java
index 4403508..bb953ea 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java
@@ -13,8 +13,6 @@
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
-import junit.framework.Test;
-
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IScanner;
@@ -23,7 +21,8 @@
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
-import org.eclipse.jdt.internal.core.util.PublicScanner;
+
+import junit.framework.Test;
@SuppressWarnings({ "rawtypes" })
public class ScannerTest extends AbstractRegressionTest {
@@ -198,7 +197,7 @@
try {
scanner.getNextToken();
} catch (InvalidInputException e) {
- assertEquals("Wrong message", PublicScanner.ILLEGAL_HEXA_LITERAL, e.getMessage());
+ assertEquals("Wrong message", Scanner.ILLEGAL_HEXA_LITERAL, e.getMessage());
}
}
@@ -885,7 +884,7 @@
} catch (InvalidInputException e) {
buffer.append(scanner.getRawTokenSource());
assertEquals("Unexpected contents", "\"a\\u000D\"", String.valueOf(buffer));
- assertEquals("Wrong exception", PublicScanner.INVALID_CHAR_IN_STRING, e.getMessage());
+ assertEquals("Wrong exception", Scanner.INVALID_CHAR_IN_STRING, e.getMessage());
}
}
@@ -914,7 +913,7 @@
} catch (InvalidInputException e) {
buffer.append(scanner.getRawTokenSource());
assertEquals("Unexpected contents", "\"\\u004Ca\\u000D\"", String.valueOf(buffer));
- assertEquals("Wrong exception", PublicScanner.INVALID_CHAR_IN_STRING, e.getMessage());
+ assertEquals("Wrong exception", Scanner.INVALID_CHAR_IN_STRING, e.getMessage());
}
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=112223
@@ -942,7 +941,7 @@
} catch (InvalidInputException e) {
buffer.append(scanner.getRawTokenSource());
assertEquals("Unexpected contents", "\"\\u004Ca\\u000D\\u0022", String.valueOf(buffer));
- assertEquals("Wrong exception", PublicScanner.INVALID_CHAR_IN_STRING, e.getMessage());
+ assertEquals("Wrong exception", Scanner.INVALID_CHAR_IN_STRING, e.getMessage());
}
}
@@ -1582,4 +1581,213 @@
fail("Should have accepted \\s");
}
}
+
+ public void testSealed() {
+ char[] source = ("sealed class X { }").toCharArray();
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "17", "17", false);
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length - 1);
+ try {
+ int token = scanner.getNextToken();
+ assertEquals("Wrong token", ITerminalSymbols.TokenNameRestrictedIdentifiersealed, token);
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testPermits() {
+ char[] source = ("sealed class X permits Y { }").toCharArray();
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "17", "17", false);
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length - 1);
+ try {
+ int token;
+ while ((token = scanner.getNextToken()) != ITerminalSymbols.TokenNameEOF) {
+ switch (token) {
+ case ITerminalSymbols.TokenNameclass:
+ case ITerminalSymbols.TokenNameWHITESPACE:
+ case ITerminalSymbols.TokenNameIdentifier:
+ case ITerminalSymbols.TokenNameRestrictedIdentifiersealed:
+ break;
+ case ITerminalSymbols.TokenNameRestrictedIdentifierpermits:
+ return; // success
+ default:
+ fail("Unexpected token "+token);
+ }
+ }
+ fail("TokenNameRestrictedIdentifierpermits was not detected");
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+ public void testNonSealed() {
+ char[] source = ("non-sealed class X { }").toCharArray();
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "17", "17", false);
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length - 1);
+ try {
+ int token = scanner.getNextToken();
+ assertEquals("Wrong token", ITerminalSymbols.TokenNamenon_sealed, token);
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testNonSealedNOK() { // insufficient compliance level
+ char[] source = ("non-sealed class X { }").toCharArray();
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "15", "15", false);
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length - 1);
+ try {
+ int token = scanner.getNextToken();
+ assertEquals("Wrong token", ITerminalSymbols.TokenNameIdentifier, token);
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testRestrictedIdentifierYield() {
+ char[] source = ("class X {\n" +
+ " int m(int i) {\n" +
+ " return switch (i) { case 0 -> { yield 13; } default -> 0 }\n" +
+ " }\n" +
+ "}\n").toCharArray();
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "17", "17", false);
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length - 1);
+ try {
+ int token;
+ while ((token = scanner.getNextToken()) != ITerminalSymbols.TokenNameEOF) {
+ switch (token) {
+ case ITerminalSymbols.TokenNameclass:
+ case ITerminalSymbols.TokenNameWHITESPACE:
+ case ITerminalSymbols.TokenNameLBRACE:
+ case ITerminalSymbols.TokenNameint:
+ case ITerminalSymbols.TokenNameIdentifier:
+ case ITerminalSymbols.TokenNameLPAREN:
+ case ITerminalSymbols.TokenNameRPAREN:
+ case ITerminalSymbols.TokenNamereturn:
+ case ITerminalSymbols.TokenNameswitch:
+ case ITerminalSymbols.TokenNamecase:
+ case ITerminalSymbols.TokenNameIntegerLiteral:
+ case ITerminalSymbols.TokenNameARROW:
+ break;
+ case ITerminalSymbols.TokenNameRestrictedIdentifierYield:
+ return; // success
+ default:
+ fail("Unexpected token "+token);
+ }
+ }
+ fail("TokenNameRestrictedIdentifierYield was not detected");
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testYieldNOK() { // insufficient context
+ String source = "class X {\n" +
+ " int m(int i) {\n" +
+ " return switch (i) { case 0 -> { yield 13; } default -> 0 }\n" +
+ " }\n" +
+ "}\n";
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "15", "15", false);
+ scanner.setSource(source.toCharArray());
+ scanner.resetTo(source.indexOf("yield")-1, source.length() - 1); // start directly at "yield"
+ try {
+ int token;
+ while ((token = scanner.getNextToken()) != ITerminalSymbols.TokenNameEOF) {
+ switch (token) {
+ case ITerminalSymbols.TokenNameIdentifier:
+ case ITerminalSymbols.TokenNameWHITESPACE:
+ case ITerminalSymbols.TokenNameIntegerLiteral:
+ break;
+ case ITerminalSymbols.TokenNameSEMICOLON: // past the word 'yield'
+ return; // success
+ default:
+ fail("Unexpected token "+token);
+ }
+ }
+ fail("TokenNameSEMICOLON was not detected");
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+ public void testRecord() {
+ char[] source = ("record Point {int x, int y}").toCharArray();
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "16", "16", false);
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length - 1);
+ try {
+ int token = scanner.getNextToken();
+ assertEquals("Wrong token", ITerminalSymbols.TokenNameRestrictedIdentifierrecord, token);
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+ // here the internal scanner could theoretically produce TokenNameAt308, which, however, doesn't happen without an active parser
+ @SuppressWarnings("deprecation")
+ public void testAt308() {
+ char[] source = ("class X<@Marker T> { }").toCharArray();
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "17", "17", false);
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length - 1);
+ try {
+ int token;
+ while ((token = scanner.getNextToken()) != ITerminalSymbols.TokenNameEOF) {
+ switch (token) {
+ case ITerminalSymbols.TokenNameclass:
+ case ITerminalSymbols.TokenNameWHITESPACE:
+ case ITerminalSymbols.TokenNameIdentifier:
+ case ITerminalSymbols.TokenNameLESS:
+ break;
+ case ITerminalSymbols.TokenNameAT:
+ return; // success
+ default:
+ fail("Unexpected token "+token);
+ }
+ }
+ fail("TokenNameAT was not detected");
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
+
+
+ @SuppressWarnings("deprecation")
+ public void testModule() { // insufficient context, all module words are identifiers
+ String source =
+ "open module m1 {\n" +
+ " requires p1.m2;\n" +
+ " requires transitive p1.m3;\n" +
+ " exports p2;\n" +
+ "}\n";
+ IScanner scanner = ToolFactory.createScanner(false, true, false, "9", "9", false);
+ scanner.setSource(source.toCharArray());
+ scanner.resetTo(0, source.length() - 1);
+ try {
+ int token;
+ while ((token = scanner.getNextToken()) != ITerminalSymbols.TokenNameEOF) {
+ switch (token) {
+ case ITerminalSymbols.TokenNameIdentifier:
+ case ITerminalSymbols.TokenNameWHITESPACE:
+ case ITerminalSymbols.TokenNameLBRACE:
+ case ITerminalSymbols.TokenNameRBRACE:
+ case ITerminalSymbols.TokenNameDOT:
+ case ITerminalSymbols.TokenNameSEMICOLON:
+ break;
+ default:
+ fail("Unexpected token "+token);
+ }
+ }
+ } catch (InvalidInputException e) {
+ assertTrue(false);
+ }
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
index 71464a2..0d72471 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
@@ -2275,6 +2275,37 @@
null,true,
new String[]{"-Ddummy"});
}
+ public void testbug566155() {
+ // method reference must be compiled as an implicit lambda expression
+ // else it cannot be serialized correctly
+ this.runConformTest(new String[] {
+ "OuterClass.java",
+ "import java.io.*;\n"+
+ "import java.util.function.Supplier;\n"+
+ "\n"+
+ "public class OuterClass implements Serializable {\n"+
+ "\n"+
+ " private static final long serialVersionUID = 5390565572939096897L;\n"+
+ " public Supplier<OuterClass.InnerClass> supplier;\n"+
+ "\n"+
+ " @SuppressWarnings(\"unchecked\")\n"+
+ " public OuterClass() {\n"+
+ " this.supplier = (Supplier<OuterClass.InnerClass> & Serializable) InnerClass::new;\n"+
+ " }\n"+
+ "\n"+
+ " public class InnerClass implements Serializable {\n"+
+ " private static final long serialVersionUID = 2478179807896338433L;\n"+
+ " public InnerClass() {\n"+
+ " }\n"+
+ " }\n"+
+ "\n"+
+ "}\n"
+ }, "");
+ String expectedOutput =
+ "lambda$1()LOuterClass$InnerClass;\n";
+ String data = printLambdaMethods(OUTPUT_DIR + File.separator + "OuterClass.class");
+ checkExpected(expectedOutput,data);
+ }
// ---
private void checkExpected(String expected, String actual) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
index ff99a82..ed8db86 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
@@ -67,6 +67,7 @@
standardTests.add(ProblemConstructorTest.class);
standardTests.add(ProblemTypeAndMethodTest.class);
standardTests.add(ScannerTest.class);
+ standardTests.add(PublicScannerTest.class);
standardTests.add(SwitchTest.class);
standardTests.add(TryStatementTest.class);
standardTests.add(UtilTest.class);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
index b9f9454..c682c68 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
@@ -1073,6 +1073,7 @@
return !file.exists() && getParentChildFile(file) == null;
}
public static boolean isMacOS() {
+ // Alternative: "macosx".equals(System.getProperty("osgi.os"))
return System.getProperty("os.name").indexOf("Mac") != -1;
}
/**
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index b9047b8..02e79e0 100644
--- a/org.eclipse.jdt.core.tests.model/pom.xml
+++ b/org.eclipse.jdt.core.tests.model/pom.xml
@@ -34,7 +34,7 @@
<artifactId>tycho-surefire-plugin</artifactId>
<version>${tycho.version}</version>
<configuration>
- <argLine>-Djdt.default.test.compliance=1.8 ${tycho.surefire.argLine}</argLine>
+ <argLine>-Xmx1G -Djdt.default.test.compliance=1.8 ${tycho.surefire.argLine}</argLine>
<includes>
<include>org/eclipse/jdt/core/tests/model/AllJavaModelTests.class</include>
<include>org/eclipse/jdt/core/tests/dom/RunAllTests.class</include>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
index 38c524d..7978d04 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
@@ -25,7 +25,11 @@
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.stream.Collectors;
import org.eclipse.core.internal.resources.CharsetDeltaJob;
@@ -525,6 +529,8 @@
protected ILogListener logListener;
protected ILog log;
+ protected static boolean systemConfigReported;
+
public AbstractJavaModelTests(String name) {
super(name);
@@ -3648,7 +3654,14 @@
description.setAutoBuilding(false);
getWorkspace().setDescription(description);
}
+
+ if (!systemConfigReported) {
+ printSystemEnv();
+ systemConfigReported = true;
+ }
+ printMemoryUse();
}
+
@Override
protected void setUp () throws Exception {
super.setUp();
@@ -3659,6 +3672,56 @@
}
logInfo("SETUP " + getName());
}
+
+ private static void printSystemEnv() {
+ Set<Entry<String, String>> set = new TreeMap<>(System.getenv()).entrySet();
+ StringBuilder sb = new StringBuilder("\n###################### System environment ######################\n");
+ for (Entry<String, String> entry : set) {
+ sb.append(" ").append(entry.getKey()).append("=").append(entry.getValue()).append("\n");
+ }
+
+ sb.append("\n###################### System properties ######################\n");
+ Set<Entry<String, String>> props = getPropertiesSafe();
+ for (Entry<String, String> entry : props) {
+ sb.append(" ").append(entry.getKey()).append("=").append(entry.getValue()).append("\n");
+ }
+ String env = sb.toString();
+ System.out.println(env);
+ logInfo(env);
+ }
+
+ private static void printMemoryUse() {
+ System.gc();
+ System.runFinalization();
+ System.gc();
+ System.runFinalization();
+ long nax = Runtime.getRuntime().maxMemory();
+ long total = Runtime.getRuntime().totalMemory();
+ long free = Runtime.getRuntime().freeMemory();
+ long used = total - free;
+ System.out.print("\n########### Memory usage reported by JVM ########");
+ System.out.printf(Locale.GERMAN, "%n%,16d bytes max heap", nax);
+ System.out.printf(Locale.GERMAN, "%n%,16d bytes heap allocated", total);
+ System.out.printf(Locale.GERMAN, "%n%,16d bytes free heap", free);
+ System.out.printf(Locale.GERMAN, "%n%,16d bytes used heap", used);
+ System.out.println("\n#################################################\n");
+ }
+
+ /**
+ * Retrieves properties safely. In case if someone tries to change the properties set
+ * while iterating over the collection, we repeat the procedure till this
+ * works without an error.
+ */
+ private static Set<Entry<String, String>> getPropertiesSafe() {
+ try {
+ return new TreeMap<>(System.getProperties().entrySet().stream()
+ .collect(Collectors.toMap(e -> String.valueOf(e.getKey()),
+ e -> String.valueOf(e.getValue())))).entrySet();
+ } catch (Exception e) {
+ return getPropertiesSafe();
+ }
+ }
+
protected void sortElements(IJavaElement[] elements) {
Util.Comparer comparer = new Util.Comparer() {
public int compare(Object a, Object b) {
@@ -3929,6 +3992,9 @@
ILog log = plugin.getLog();
Status status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, errorMessage, e);
log.log(status);
+ } else {
+ System.out.println(errorMessage);
+ e.printStackTrace(System.out);
}
}
@@ -3936,6 +4002,8 @@
Plugin plugin = JavaCore.getPlugin();
if (plugin != null) {
plugin.getLog().log(new Status(IStatus.INFO, JavaCore.PLUGIN_ID, message));
+ } else {
+ System.out.println(message);
}
}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java
index 47aa1e2..3787075 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java
@@ -3624,7 +3624,7 @@
JavaCore.VERSION_1_4);
createFile("/P/lib2.jar", "");
startDeltas();
- if ("macosx".equals(System.getProperty("osgi.os"))) {
+ if (Util.isMacOS()) {
// necessary for filesystems with timestamps only upto seconds (eg. Mac)
// "lib1.jar" was created above and is modified below.
Thread.sleep(2000);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
index b0e1172..d61ce7b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2020 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -26447,4 +26447,27 @@
"A[TYPE_REF]{A, , LA;, null, null, 56}",
requestor.getResults());
}
+/**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=578815
+ * @throws IOException
+ */
+public void testCompletionConstructorsForSubTypes() throws JavaModelException, IOException {
+ ICompilationUnit cu= getCompilationUnit("Completion", "src", "", "CompletionConstructorsForSubTypes.java");
+ String str = cu.getSource();
+ String completeBehind = "new ";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, false, false, true, true);
+ requestor.allowAllRequiredProposals();
+ cu.codeComplete(cursorLocation, requestor, new NullProgressMonitor());
+
+ assertEquals(
+ "CompletionConstructorsForSubTypes[CONSTRUCTOR_INVOCATION]{(), LCompletionConstructorsForSubTypes;, ()V, CompletionConstructorsForSubTypes, null, 55}\n" +
+ " CompletionConstructorsForSubTypes[TYPE_REF]{CompletionConstructorsForSubTypes, , LCompletionConstructorsForSubTypes;, null, null, 55}\n" +
+ "CompletionConstructorsForSubTypes2[CONSTRUCTOR_INVOCATION]{(), LCompletionConstructorsForSubTypes2;, ()V, CompletionConstructorsForSubTypes2, null, 75}\n" +
+ " CompletionConstructorsForSubTypes2[TYPE_REF]{CompletionConstructorsForSubTypes2, , LCompletionConstructorsForSubTypes2;, null, null, 75}\n" +
+ "CompletionConstructorsForSubTypes1[ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION]{(), LCompletionConstructorsForSubTypes1;, ()V, CompletionConstructorsForSubTypes1, null, 82}\n" +
+ " CompletionConstructorsForSubTypes1[TYPE_REF]{CompletionConstructorsForSubTypes1, , LCompletionConstructorsForSubTypes1;, null, null, 82}",
+ requestor.getResults());
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
index d1d56c5..d4143d5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
@@ -1159,7 +1159,7 @@
String completeBehind = "p.get";
int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
- assertResults("getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<*>;, null, null, getClass, null, [186, 189], " + (R_DEFAULT + R_EXPECTED_TYPE + 30) + "}\n" +
+ assertResults("getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<*>;, null, null, getClass, null, [186, 189], " + (R_DEFAULT + R_PACKAGE_EXPECTED_TYPE + 30) + "}\n" +
"getLastName[METHOD_REF]{getLastName(), LPerson;, ()Ljava.lang.String;, null, null, getLastName, null, [186, 189], " + (R_DEFAULT + R_EXACT_EXPECTED_TYPE + 30) + "}", requestor.getResults());
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=428735, [1.8][assist] Missing completion proposals inside lambda body expression - other than first token
@@ -1913,7 +1913,7 @@
String completeBehind = "so.tr";
int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
- assertResults("trim[METHOD_REF]{trim(), Ljava.lang.String;, ()Ljava.lang.String;, null, null, trim, null, [237, 239], " + (R_DEFAULT + R_EXPECTED_TYPE + 30) + "}", requestor.getResults());
+ assertResults("trim[METHOD_REF]{trim(), Ljava.lang.String;, ()Ljava.lang.String;, null, null, trim, null, [237, 239], " + (R_DEFAULT + R_PACKAGE_EXPECTED_TYPE + 30) + "}", requestor.getResults());
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=435682, [1.8] content assist not working inside lambda expression
public void test435682a() throws JavaModelException {
@@ -6262,9 +6262,9 @@
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (J)V, wait, (millis), 55}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (JI)V, wait, (millis, nanos), 55}\n"
+ "equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 80}\n"
- + "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<*>;, getClass, null, 80}\n"
+ "hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 80}\n"
- + "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 80}\n"
+ + "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<*>;, getClass, null, 85}\n"
+ + "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 85}\n"
+ "clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 90}",
result);
}
@@ -6297,11 +6297,11 @@
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, ()V, wait, null, 55}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (J)V, wait, (millis), 55}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (JI)V, wait, (millis, nanos), 55}\n"
- + "boo[METHOD_REF]{boo(), LBug577883$Int;, ()Ljava.lang.Integer;, boo, null, 80}\n"
+ "equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 80}\n"
- + "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<*>;, getClass, null, 80}\n"
+ "hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 80}\n"
- + "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 80}\n"
+ + "boo[METHOD_REF]{boo(), LBug577883$Int;, ()Ljava.lang.Integer;, boo, null, 85}\n"
+ + "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<*>;, getClass, null, 85}\n"
+ + "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 85}\n"
+ "clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 90}",
result);
}
@@ -6483,11 +6483,11 @@
int cursorLocation = str.indexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
String result = requestor.getResults();
- assertResults("LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, ()V, LinkedHashMap, null, 76}\n"
- + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (I)V, LinkedHashMap, (arg0), 76}\n"
- + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (IF)V, LinkedHashMap, (arg0, arg1), 76}\n"
- + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (IFZ)V, LinkedHashMap, (arg0, arg1, arg2), 76}\n"
- + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (Ljava.util.Map<+TK;+TV;>;)V, LinkedHashMap, (arg0), 76}", result);
+ assertResults("LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, ()V, LinkedHashMap, null, 81}\n"
+ + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (I)V, LinkedHashMap, (arg0), 81}\n"
+ + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (IF)V, LinkedHashMap, (arg0, arg1), 81}\n"
+ + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (IFZ)V, LinkedHashMap, (arg0, arg1, arg2), 81}\n"
+ + "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (Ljava.util.Map<+TK;+TV;>;)V, LinkedHashMap, (arg0), 81}", result);
requestor = new CompletionTestsRequestor2(true);
requestor.setAllowsRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF, true);
@@ -6499,4 +6499,29 @@
result = requestor.getResults();
assertResults("", result);
}
+ public void testBug564875() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/X.java",
+ "import java.util.List;\n" +
+ "class Person {\n" +
+ " String getLastName() { return null; }\n" +
+ " Person getLastPerson() { return null; }\n" +
+ "}\n" +
+ "public class X {\n" +
+ " void test1 (List<Person> people) {\n" +
+ " people.stream().forEach(p -> System.out.println(p.get)); \n" +
+ " }\n" +
+ "}\n");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
+ requestor.allowAllRequiredProposals();
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "p.get";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+ assertResults("getLastPerson[METHOD_REF]{getLastPerson(), LPerson;, ()LPerson;, null, null, getLastPerson, null, [229, 232], "+ (R_DEFAULT+R_EXPECTED_TYPE+30)+"}\n"
+ + "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<*>;, null, null, getClass, null, [229, 232], "+(R_DEFAULT+R_PACKAGE_EXPECTED_TYPE+30)+"}\n"
+ + "getLastName[METHOD_REF]{getLastName(), LPerson;, ()Ljava.lang.String;, null, null, getLastName, null, [229, 232], "+(R_DEFAULT+R_EXACT_EXPECTED_TYPE+30)+"}", requestor.getResults());
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests_1_5.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests_1_5.java
index 44b9319..0609941 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests_1_5.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests_1_5.java
@@ -7617,7 +7617,7 @@
result.proposals);
} else {
assertResults(
- "Test<ZT>[TYPE_REF]{Test, test0232, Ltest0232.Test<TZT;>;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXPECTED_TYPE) + "}",
+ "Test<ZT>[TYPE_REF]{Test, test0232, Ltest0232.Test<TZT;>;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_PACKAGE_EXPECTED_TYPE) + "}",
result.proposals);
}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index be6e238..c20f98b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -19,6 +19,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
@@ -60,6 +61,7 @@
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.tests.model.ContainerInitializer.ITestInitializer;
import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.core.util.ExternalAnnotationUtil;
@@ -119,6 +121,76 @@
}
}
+ /**
+ * Initializer for a container that may provide a mix of entries, some of which are "self-annotating",
+ * i.e., contain .eea files for their own classes.
+ */
+ static class TestCustomContainerInitializer implements ContainerInitializer.ITestInitializer {
+
+ /** Use this container name in test projects. */
+ private static final String CONTAINER_NAME = "org.eclipse.jdt.core.tests.model.TEST_CONTAINER";
+
+ List<String> allEntries;
+ Map<String,String> elementAnnotationPaths;
+
+ /**
+ * @param elementsAndAnnotationPaths each pair of entries in this array defines one classpath entry:
+ * <ul>
+ * <li>1st string specifies the path,
+ * <li>if 2nd string is "self" than the entry is "self-annotating".
+ * {@code null} is a legal value to signal "not self-annotating"
+ * </ul>
+ */
+ public TestCustomContainerInitializer(String... elementsAndAnnotationPaths) {
+ this.allEntries = new ArrayList<>();
+ this.elementAnnotationPaths = new HashMap<>();
+ for (int i = 0; i < elementsAndAnnotationPaths.length; i+=2) {
+ String entryPath = elementsAndAnnotationPaths[i];
+ this.allEntries.add(entryPath);
+ String annotsPath = elementsAndAnnotationPaths[i+1];
+ if ("self".equals(annotsPath))
+ this.elementAnnotationPaths.put(entryPath, entryPath);
+ }
+ }
+
+ static class TestContainer implements IClasspathContainer {
+ IPath path;
+ IClasspathEntry[] entries;
+ TestContainer(IPath path, IClasspathEntry[] entries){
+ this.path = path;
+ this.entries = entries;
+ }
+ public IPath getPath() { return this.path; }
+ public IClasspathEntry[] getClasspathEntries() { return this.entries; }
+ public String getDescription() { return this.path.toString(); }
+ public int getKind() { return 0; }
+ }
+
+ @Override
+ public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
+ List<IClasspathEntry> entries = new ArrayList<>();
+ for (String entryPath : this.allEntries) {
+ IClasspathAttribute[] extraAttributes;
+ String elementAnnotationPath = this.elementAnnotationPaths.get(entryPath);
+ if (elementAnnotationPath != null)
+ extraAttributes = externalAnnotationExtraAttributes(elementAnnotationPath);
+ else
+ extraAttributes = ClasspathEntry.NO_EXTRA_ATTRIBUTES;
+ entries.add(JavaCore.newLibraryEntry(new Path(entryPath), null, null,
+ ClasspathEntry.NO_ACCESS_RULES, extraAttributes, false/*not exported*/));
+ }
+ JavaCore.setClasspathContainer(
+ new Path(CONTAINER_NAME),
+ new IJavaProject[]{ project },
+ new IClasspathContainer[] { new TestContainer(new Path(CONTAINER_NAME), entries.toArray(IClasspathEntry[]::new)) },
+ null);
+ }
+ @Override
+ public boolean allowFailureContainer() {
+ return false;
+ }
+ }
+
static class LogListener implements ILogListener {
List<IStatus> loggedStatus = new ArrayList<>();
public void logging(IStatus status, String plugin) {
@@ -3108,4 +3180,133 @@
7, 11
});
}
+
+ public void testMixedElementAndContainerAnnotation() throws Exception {
+ myCreateJavaProject("PrjTest");
+ String projectLoc = this.project.getProject().getLocation().toString();
+ ITestInitializer prev = ContainerInitializer.initializer;
+ ContainerInitializer.setInitializer(new TestCustomContainerInitializer(projectLoc+"/lib1.jar", "self", projectLoc+"/lib2.jar", null));
+ try {
+
+ // jar with external annotations for its own class
+ Util.createJar(new String[] {
+ "lib/pgen/CGen.java",
+ "package lib.pgen;\n" +
+ "public class CGen {\n" +
+ " public String get(String in) { return in; }\n" +
+ "}\n"
+ },
+ new String[] {
+ "lib/pgen/CGen.eea",
+ "class lib/pgen/CGen\n" +
+ "\n" +
+ "get\n" +
+ " (Ljava/lang/String;)Ljava/lang/String;\n" +
+ " (L1java/lang/String;)L1java/lang/String;\n",
+ },
+ projectLoc+"/lib1.jar",
+ "1.8");
+ Util.createJar(new String[] {
+ "lib2/C2.java",
+ "package lib2;\n" +
+ "public class C2 {\n" +
+ " public String get2(Exception in) { return in.toString(); }\n" +
+ "}\n"
+ },
+ projectLoc+"/lib2.jar",
+ "1.8");
+ IClasspathEntry containerEntry = JavaCore.newContainerEntry(
+ new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER"),
+ null,
+ new IClasspathAttribute[] {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, "/PrjTest/annots")
+ },
+ false);
+ addClasspathEntry(this.project, containerEntry);
+
+ createFileInProject("annots/lib2", "C2.eea",
+ "class lib2/C2\n" +
+ "\n" +
+ "get2\n" +
+ " (Ljava/lang/Exception;)Ljava/lang/String;\n" +
+ " (L1java/lang/Exception;)L1java/lang/String;\n");
+
+ createFileInProject("src/p", "Use.java",
+ "package p;\n" +
+ "import lib.pgen.CGen;\n" +
+ "import lib2.C2;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class Use {\n" +
+ " public @NonNull String test(CGen c) {\n" +
+ " String s = c.get(null);\n" + // problem here (7)
+ " return s;\n" + // no problem here
+ " }\n" +
+ " public @NonNull String test2(C2 c) {\n" +
+ " String s = c.get2(null);\n" + // problem here (11)
+ " return s;\n" + // no problem here
+ " }\n" +
+ "}\n");
+
+
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = this.project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ sortMarkers(markers);
+ assertMarkers("Unexpected markers",
+ "Null type mismatch: required '@NonNull Exception' but the provided value is null\n" +
+ "Null type mismatch: required '@NonNull String' but the provided value is null",
+ markers);
+
+ ICompilationUnit unit = JavaCore.createCompilationUnitFrom(this.project.getProject().getFile("src/p/Use.java")).getWorkingCopy(null);
+ CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertProblems(problems,
+ new String[] {
+ "Pb(910) Null type mismatch: required '@NonNull String' but the provided value is null",
+ "Pb(910) Null type mismatch: required '@NonNull Exception' but the provided value is null"
+ },
+ new int[] {
+ 7, 11
+ });
+ } finally {
+ ContainerInitializer.setInitializer(prev);
+ }
+ }
+ public void testAnnotatedSourceSharesOutputFolder() throws CoreException {
+ IJavaProject prj1 = null;
+ myCreateJavaProject("Prj1");
+ addSourceFolderWithExternalAnnotations(this.project, "/Prj1/src-gen", null, "/Prj1/annot-gen");
+ prj1 = this.project;
+ try {
+ createFileInProject("annot-gen/pgen", "CGen.eea",
+ "class pgen/CGen\n" +
+ "\n" +
+ "get\n" +
+ " (Ljava/lang/String;)Ljava/lang/String;\n" +
+ " (L1java/lang/String;)L1java/lang/String;\n");
+
+ createFileInProject("src-gen/pgen", "CGen.java",
+ "package pgen;\n" +
+ "public class CGen {\n" +
+ " public String get(String in) { return in; }\n" +
+ "}\n");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+ createFileInProject("src/pgen", "CImpl.java",
+ "package pgen;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class CImpl extends CGen {\n" +
+ " public @NonNull String get(@NonNull String in) { return in; }\n" +
+ "}\n");
+ ICompilationUnit unit = JavaCore.createCompilationUnitFrom(this.project.getProject().getFile("src/pgen/CImpl.java")).getWorkingCopy(null);
+ CompilationUnit reconciled = unit.reconcile(AST.getJLSLatest(), true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertNoProblems(problems);
+ this.project.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+ IMarker[] markers = this.project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ assertNoMarkers(markers);
+ } finally {
+ if (prj1 != null)
+ prj1.getProject().delete(true, true , null);
+ }
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests_1_5.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests_1_5.java
index b2b8f99..f814807 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests_1_5.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests_1_5.java
@@ -3002,4 +3002,53 @@
deleteProject("P0125");
}
}
+
+public void testBrokenSwitch0() throws JavaModelException {
+ ICompilationUnit cu = getWorkingCopy("/Resolve/src/Test.java",
+ "interface ILog {\n" +
+ " void log(String status);\n" +
+ "}\n" +
+ "public class Test {\n" +
+ " private static ILog test() {\n" +
+ " return new ILog() {\n" +
+ " @Override\n" +
+ " public void log(String status) {\n" +
+ " switch (status.length()) { // here\n" +
+ " case\n" +
+ " }\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ "}\n");
+ IJavaElement[] elements = codeSelect(cu, "length()", "length");
+ assertElementsEqual(
+ "Unexpected elements",
+ "length() [in String [in String.class [in java.lang [in "+ getExternalJCLPathString("1.5") + "]]]]",
+ elements);
+}
+
+public void testBrokenSwitch1() throws JavaModelException {
+ ICompilationUnit cu = getWorkingCopy("/Resolve/src/Test.java",
+ "interface ILog {\n" +
+ " void log(String status);\n" +
+ "}\n" +
+ "public class Test {\n" +
+ " private static ILog test() {\n" +
+ " return new ILog() {\n" +
+ " @Override\n" +
+ " public void log(String status) {\n" +
+ " Boolean severity = Boolean.FALSE;" +
+ " switch (status.length()) { // here\n" +
+ " case\n" +
+ " }\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ "}\n");
+ IJavaElement[] elements = codeSelect(cu, "length()", "length");
+ assertElementsEqual(
+ "Unexpected elements",
+ "length() [in String [in String.class [in java.lang [in "+ getExternalJCLPathString("1.5") + "]]]]",
+ elements);
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes.java b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes.java
new file mode 100644
index 0000000..7389c9d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes.java
@@ -0,0 +1,5 @@
+public class CompletionConstructorsForSubTypes {
+ public void test() {
+ CompletionConstructorsForSubTypes1 i = new
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes1.java b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes1.java
new file mode 100644
index 0000000..51e5fa4
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes1.java
@@ -0,0 +1,2 @@
+public interface CompletionConstructorsForSubTypes1 {
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes2.java b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes2.java
new file mode 100644
index 0000000..6dc4d9b
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/CompletionConstructorsForSubTypes2.java
@@ -0,0 +1,2 @@
+public class CompletionConstructorsForSubTypes2 implements CompletionConstructorsForSubTypes1 {
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/.settings/.api_filters b/org.eclipse.jdt.core/.settings/.api_filters
index 905fdaa..00fbc54 100644
--- a/org.eclipse.jdt.core/.settings/.api_filters
+++ b/org.eclipse.jdt.core/.settings/.api_filters
@@ -8,8 +8,6 @@
<message_argument value="16"/>
</message_arguments>
</filter>
- </resource>
- <resource path="dom/org/eclipse/jdt/core/dom/AST.java" type="org.eclipse.jdt.core.dom.AST">
<filter comment="For new java version" id="388194388">
<message_arguments>
<message_argument value="org.eclipse.jdt.core.dom.AST"/>
@@ -18,20 +16,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="dom/org/eclipse/jdt/core/dom/AbstractTagElement.java" type="org.eclipse.jdt.core.dom.AbstractTagElement">
- <filter id="576725006">
- <message_arguments>
- <message_argument value="IDocElement"/>
- <message_argument value="TagProperty"/>
- </message_arguments>
- </filter>
- <filter id="576778288">
- <message_arguments>
- <message_argument value="ASTNode"/>
- <message_argument value="TagProperty"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="dom/org/eclipse/jdt/core/dom/ASTNode.java" type="org.eclipse.jdt.core.dom.ASTNode">
<filter comment="adjust constants after additions in JDT" id="388194388">
<message_arguments>
@@ -146,6 +130,20 @@
</message_arguments>
</filter>
</resource>
+ <resource path="dom/org/eclipse/jdt/core/dom/AbstractTagElement.java" type="org.eclipse.jdt.core.dom.AbstractTagElement">
+ <filter id="576725006">
+ <message_arguments>
+ <message_argument value="IDocElement"/>
+ <message_argument value="TagProperty"/>
+ </message_arguments>
+ </filter>
+ <filter id="576778288">
+ <message_arguments>
+ <message_argument value="ASTNode"/>
+ <message_argument value="TagProperty"/>
+ </message_arguments>
+ </filter>
+ </resource>
<resource path="formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java" type="org.eclipse.jdt.core.formatter.CodeFormatter">
<filter comment="adjust constants after additions in JDT" id="388194388">
<message_arguments>
@@ -155,4 +153,18 @@
</message_arguments>
</filter>
</resource>
+ <resource path="model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java" type="org.eclipse.jdt.core.compiler.ITerminalSymbols">
+ <filter comment="token 'readonly' has long been deprecated as it is not supported" id="405864542">
+ <message_arguments>
+ <message_argument value="org.eclipse.jdt.core.compiler.ITerminalSymbols"/>
+ <message_argument value="TokenNamereadonly"/>
+ </message_arguments>
+ </filter>
+ <filter comment="result was never detected as a token by the scanner" id="405864542">
+ <message_arguments>
+ <message_argument value="org.eclipse.jdt.core.compiler.ITerminalSymbols"/>
+ <message_argument value="TokenNameresult"/>
+ </message_arguments>
+ </filter>
+ </resource>
</component>
diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
index 7b46414..f03eb03 100644
--- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
@@ -78,7 +78,7 @@
org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer;x-internal:=true,
org.eclipse.objectteams.otdt.internal.core.compiler.util;x-internal:=true,
org.eclipse.objectteams.otdt.internal.core.util;x-internal:=true
-Require-Bundle: org.eclipse.core.resources;bundle-version="[3.14.0,4.0.0)",
+Require-Bundle: org.eclipse.core.resources;bundle-version="[3.17.0,4.0.0)",
org.eclipse.core.runtime;bundle-version="[3.13.0,4.0.0)",
org.eclipse.core.filesystem;bundle-version="[1.7.0,2.0.0)",
org.eclipse.text;bundle-version="[3.6.0,4.0.0)",
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index b44aeb5..590ea04 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -19,6 +19,7 @@
* Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions
* Microsoft Corporation - Contribution for bug 575562 - improve completion search performance
* Bug 578817 - skip the ignored types before creating CompletionProposals
+ * Microsoft Corporation - Contribution for bug 578815 - more candidates when completion after new keyword for an interface
*******************************************************************************/
package org.eclipse.jdt.internal.codeassist;
@@ -5097,12 +5098,16 @@
if((this.expectedTypesFilter & SUBTYPE) != 0
&& (proposalType.erasure().isCompatibleWith(this.expectedTypes[i].erasure()))) {
- if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) &&
- CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) {
- return R_EXACT_EXPECTED_TYPE;
+ if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) ) {
+ if(CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName()))
+ return R_EXACT_EXPECTED_TYPE;
+ if(!CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName()) &&
+ proposalType.qualifiedPackageName().length !=0)
+ return R_PACKAGE_EXPECTED_TYPE;
}
relevance = R_EXPECTED_TYPE;
+
}
if((this.expectedTypesFilter & SUPERTYPE) != 0
&& this.expectedTypes[i].isCompatibleWith(proposalType)) {
@@ -12474,6 +12479,8 @@
if (isEmptyPrefix && !this.assistNodeIsAnnotation) {
if (!proposeConstructor) {
findTypesFromExpectedTypes(token, scope, typesFound, proposeType, proposeConstructor);
+ } else {
+ findConstructorsFromSubTypes(scope, typesFound);
}
} else {
if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
@@ -12556,6 +12563,144 @@
}
}
+ /**
+ * Find all the constructors of the expected types' sub types.
+ */
+ private void findConstructorsFromSubTypes(Scope scope, ObjectVector typesFound) {
+ SearchPattern pattern = null;
+ for (TypeBinding typeBinding : this.expectedTypes) {
+ if (typeBinding == null || !typeBinding.isInterface()) {
+ continue;
+ }
+ if (pattern == null) {
+ pattern = SearchPattern.createPattern(String.valueOf(typeBinding.qualifiedPackageName()) +
+ "." + String.valueOf(typeBinding.qualifiedSourceName()), //$NON-NLS-1$
+ IJavaSearchConstants.CLASS, IJavaSearchConstants.IMPLEMENTORS,
+ SearchPattern.R_EXACT_MATCH);
+ } else {
+ pattern = SearchPattern.createOrPattern(pattern, SearchPattern.createPattern(String.valueOf(
+ typeBinding.qualifiedPackageName()) + "." + String.valueOf(typeBinding.qualifiedSourceName()), //$NON-NLS-1$
+ IJavaSearchConstants.CLASS, IJavaSearchConstants.IMPLEMENTORS,
+ SearchPattern.R_EXACT_MATCH));
+ }
+ }
+ if (pattern == null) {
+ return;
+ }
+
+ List<IType> types = new ArrayList<>();
+ IJavaSearchScope searchScope = SearchEngine.createJavaSearchScope(new IJavaElement[] {this.javaProject});
+ SearchRequestor searchRequstor = new SearchRequestor() {
+ @Override
+ public void acceptSearchMatch(SearchMatch match) {
+ Object element = match.getElement();
+ if (!(element instanceof IType)) {
+ return;
+ }
+ types.add((IType) element);
+ }
+ };
+ try {
+ new SearchEngine().search(pattern,
+ new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() },
+ searchScope,
+ searchRequstor,
+ null
+ );
+ } catch (CoreException e) {
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ }
+
+ checkCancel();
+
+ for (IType type : types) {
+ ReferenceBinding typeBinding = this.lookupEnvironment.getType(CharOperation.splitOn('.', type.getFullyQualifiedName().toCharArray()));
+ if (typeBinding == null) {
+ continue;
+ }
+
+ int accessibility = IAccessRule.K_ACCESSIBLE;
+ if(typeBinding.hasRestrictedAccess()) {
+ AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(typeBinding);
+ if(accessRestriction != null) {
+ switch (accessRestriction.getProblemId()) {
+ case IProblem.ForbiddenReference:
+ if (this.options.checkForbiddenReference) {
+ continue;
+ }
+ accessibility = IAccessRule.K_NON_ACCESSIBLE;
+ break;
+ case IProblem.DiscouragedReference:
+ if (this.options.checkDiscouragedReference) {
+ continue;
+ }
+ accessibility = IAccessRule.K_DISCOURAGED;
+ break;
+ }
+ }
+ }
+
+ if (typesFound.contains(typeBinding)) continue;
+
+ typesFound.add(typeBinding);
+
+ if (this.assistNodeIsExtendedType && typeBinding.isFinal()) continue;
+ if (this.assistNodeIsInterfaceExcludingAnnotation && typeBinding.isAnnotationType()) continue;
+ if(this.assistNodeIsClass) {
+ if(!typeBinding.isClass()) continue;
+ } else if(this.assistNodeIsInterface) {
+ if(!typeBinding.isInterface() && !typeBinding.isAnnotationType()) continue;
+ } else if (this.assistNodeIsAnnotation) {
+ if(!typeBinding.isAnnotationType()) continue;
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal(typeBinding);
+ relevance += R_EXACT_EXPECTED_TYPE; // all found types are sub-types
+ relevance += computeRelevanceForQualification(false);
+ relevance += computeRelevanceForRestrictions(accessibility);
+
+ if (typeBinding.isAnnotationType()) {
+ relevance += computeRelevanceForAnnotation();
+ relevance += computeRelevanceForAnnotationTarget(typeBinding);
+ } else if (typeBinding.isInterface()) {
+ relevance += computeRelevanceForInterface();
+ } else if(typeBinding.isClass()){
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForException(typeBinding.sourceName);
+ }
+
+ if (!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
+ boolean isQualified = false;
+ if (!this.insideQualifiedReference && !typeBinding.isMemberType()) {
+ char[] packageName = typeBinding.qualifiedPackageName();
+ char[] typeName = typeBinding.sourceName();
+ if (mustQualifyType(packageName, typeName, null, typeBinding.modifiers)) {
+ isQualified = true;
+ }
+ }
+ findConstructors(
+ typeBinding,
+ null,
+ scope,
+ FakeInvocationSite,
+ false,
+ null,
+ null,
+ null,
+ false,
+ false,
+ isQualified,
+ relevance
+ );
+ }
+ }
+ }
+
private int getTypesMatchRule() {
int matchRule = SearchPattern.R_PREFIX_MATCH;
if (this.options.camelCaseMatch)
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
index 6e43a84..9ef6f05 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
@@ -31,6 +31,7 @@
int R_EXACT_NAME = 4;
int R_VOID = -5;
int R_EXPECTED_TYPE = 20;
+ int R_PACKAGE_EXPECTED_TYPE = 25;
int R_EXACT_EXPECTED_TYPE = 30;
int R_INTERFACE = 20;
int R_CLASS = 20;
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index c809b6c..4cce843 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -173,14 +173,14 @@
int info = topKnownElementInfo(SELECTION_OR_ASSIST_PARSER);
nextElement : switch (kind) {
case K_BETWEEN_CASE_AND_COLONORARROW :
- if(this.expressionPtr > 0) {
+ if(this.expressionPtr >= info && info > -1) {
SwitchStatement switchStatement = new SwitchStatement();
- switchStatement.expression = this.expressionStack[this.expressionPtr - 1];
+ switchStatement.expression = this.expressionStack[info]; // info is pointer to top expr when encountering 'case'
if(this.astLengthPtr > -1 && this.astPtr > -1) {
int length = this.astLengthStack[this.astLengthPtr];
int newAstPtr = this.astPtr - length;
ASTNode firstNode = this.astStack[newAstPtr + 1];
- if(length != 0 && firstNode.sourceStart > switchStatement.expression.sourceEnd) {
+ if(length != 0 && firstNode instanceof Statement && firstNode.sourceStart > switchStatement.expression.sourceEnd) {
switchStatement.statements = new Statement[length + 1];
System.arraycopy(
this.astStack,
@@ -1361,7 +1361,7 @@
if (isInsideMethod() || isInsideFieldInitialization()) {
switch (token) {
case TokenNamecase :
- pushOnElementStack(K_BETWEEN_CASE_AND_COLONORARROW);
+ pushOnElementStack(K_BETWEEN_CASE_AND_COLONORARROW, this.expressionPtr);
break;
case TokenNameCOMMA :
switch (topKnownElementKind(SELECTION_OR_ASSIST_PARSER)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index f355226..2a75295 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -27,6 +27,7 @@
* Bug 466713 - Null Annotations: NullPointerException using <int @Nullable []> as Type Param
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 378674 - "The method can be declared as static" is wrong
+ * bug 413873 - Warning "Method can be static" on method referencing a non-static inner class
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -48,6 +49,7 @@
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
@@ -163,7 +165,17 @@
// nullity and mark as assigned
analyseArguments(classScope.environment(), flowInfo, this.arguments, this.binding);
- if (this.binding.declaringClass instanceof MemberTypeBinding && !this.binding.declaringClass.isStatic()) {
+ boolean hasMemberTypeParameter = false;
+ if (this.binding.parameters != null && this.arguments != null) {
+ int length = Math.min(this.binding.parameters.length, this.arguments.length);
+ for (int i = 0; i < length; i++) {
+ if (this.binding.parameters[i] instanceof ParameterizedTypeBinding) {
+ hasMemberTypeParameter = true;
+ break;
+ }
+ }
+ }
+ if (this.binding.declaringClass instanceof MemberTypeBinding && !this.binding.declaringClass.isStatic() || hasMemberTypeParameter) {
// method of a non-static member type can't be static.
this.bits &= ~ASTNode.CanBeStatic;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index 1dee15b..aaee28e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -277,7 +277,7 @@
private boolean shouldGenerateImplicitLambda(BlockScope currentScope) {
// these cases are either too complicated, impossible to handle or result in significant code duplication
return (this.binding.isVarargs() ||
- (isConstructorReference() && this.receiverType.syntheticOuterLocalVariables() != null && this.shouldCaptureInstance) ||
+ (isConstructorReference() && (this.receiverType.syntheticOuterLocalVariables() != null || this.shouldCaptureInstance)) ||
this.requiresBridges() || // bridges.
!isDirectCodeGenPossible());
// To fix: We should opt for direct code generation wherever possible.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/BranchLabel.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/BranchLabel.java
index 6651738..5a2082e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/BranchLabel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/BranchLabel.java
@@ -160,11 +160,11 @@
}
public int forwardReferenceCount() {
- if (this.delegate != null) this.delegate.forwardReferenceCount();
+ if (this.delegate != null) return this.delegate.forwardReferenceCount();
return this.forwardReferenceCount;
}
public int[] forwardReferences() {
- if (this.delegate != null) this.delegate.forwardReferences();
+ if (this.delegate != null) return this.delegate.forwardReferences();
return this.forwardReferences;
}
public void initialize(CodeStream stream) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index 6ffd4e8..c6e0349 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -1618,6 +1618,11 @@
updateScanContext(token);
}
if (this.activeParser == null) { // anybody interested in the grammatical structure of the program should have registered.
+ if (token != TokenNameWHITESPACE) {
+ this.lookBack[0] = this.lookBack[1];
+ this.lookBack[1] = token;
+ this.multiCaseLabelComma = false;
+ }
return token;
}
if (token == TokenNameLPAREN || token == TokenNameLESS || token == TokenNameAT || token == TokenNameARROW) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
index 1e573c7..78e8b37 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
@@ -449,8 +449,9 @@
complianceLevelValue,
null/*taskTags*/,
null/*taskPriorities*/,
- true/*taskCaseSensitive*/);
- scanner.recordLineSeparator = recordLineSeparator;
+ true/*taskCaseSensitive*/,
+ true/*isPreviewEnabled*/,
+ recordLineSeparator);
return scanner;
}
@@ -506,8 +507,9 @@
complianceLevelValue,
null/*taskTags*/,
null/*taskPriorities*/,
- true/*taskCaseSensitive*/);
- scanner.recordLineSeparator = recordLineSeparator;
+ true/*taskCaseSensitive*/,
+ true/*isPreviewEnabled*/,
+ recordLineSeparator);
return scanner;
}
@@ -591,8 +593,10 @@
if (sourceLevelValue == 0) sourceLevelValue = ClassFileConstants.JDK1_3; // fault-tolerance
long complianceLevelValue = CompilerOptions.versionToJdkLevel(complianceLevel);
if (complianceLevelValue == 0) complianceLevelValue = ClassFileConstants.JDK1_4; // fault-tolerance
- scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/,sourceLevelValue /*sourceLevel*/, complianceLevelValue, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/, enablePreview);
- scanner.recordLineSeparator = recordLineSeparator;
+ scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace,
+ false/*nls*/,sourceLevelValue /*sourceLevel*/, complianceLevelValue,
+ null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/,
+ enablePreview, recordLineSeparator);
return scanner;
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
index 60b8a6d..b2b913a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
@@ -192,6 +192,27 @@
*/
int TokenNameCOLON_COLON = 406;
+ /** @since 3.30 */
+ int TokenNameNotAToken = 408;
+
+ /** @since 3.30 */
+ int TokenNameRestrictedIdentifierYield = 409;
+
+ /** @since 3.30 */
+ int TokenNameRestrictedIdentifierpermits = 410;
+
+ /** @since 3.30 */
+ int TokenNameRestrictedIdentifierrecord = 411;
+
+ /** @since 3.30 */
+ int TokenNameRestrictedIdentifiersealed = 412;
+
+ /** @since 3.30 */
+ int TokenNameSingleQuoteStringLiteral = 413;
+
+ /** @since 3.30 */
+ int TokenNamenon_sealed = 414;
+
//{ObjectTeams: mirrored from auto-generated TerminalTokens.java. Note: the values here must be constant across Eclipse-versions, so do not simply copy the identifiers!
// Take values from 5000 upwards
int
@@ -203,7 +224,6 @@
TokenNamewith = 5005,
TokenNameteam = 5006,
TokenNameas = 5007,
- TokenNameresult = 5008,
TokenNamereplace = 5009,
TokenNameafter = 5010,
TokenNamebefore = 5011,
@@ -214,10 +234,5 @@
TokenNameset = 5017,
TokenNamewhen = 5018,
TokenNameprecedence = 5019;
- /**
- * @deprecated Modifier 'readonly' is no longer recognized. It was never truly supported.
- */
- @Deprecated
- int TokenNamereadonly = 5015;
// carp}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
index bca0333..89a3930 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -15,12 +15,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
@@ -560,7 +562,11 @@
if (oldurl == null && newurl == null) {
pathHasChanged = false;
} else if (oldurl != null && newurl != null) {
- pathHasChanged = !(newurl.equals(oldurl));
+ try {
+ pathHasChanged = !Objects.equals(newurl.toURI(),oldurl.toURI());
+ } catch (URISyntaxException e) {
+ // ignore
+ }
} else if (oldurl != null) {
indexManager.removeIndex(newPath);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
index 4a443f0..2bc5c30 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
@@ -361,7 +361,7 @@
int lenRefer = referringExtraAttributes.length;
if (lenRefer > 0) {
int lenEntry = combinedAttributes.length;
- if (referringEntry.path.isPrefixOf(this.path)) {
+ if (referringEntry.path.isPrefixOf(this.path) || referringEntry.getEntryKind() == CPE_CONTAINER) {
// consider prefix location as less specific, put to back (e.g.: referring to a library via a project):
System.arraycopy(combinedAttributes, 0, combinedAttributes=new IClasspathAttribute[lenEntry+lenRefer], 0, lenEntry);
System.arraycopy(referringExtraAttributes, 0, combinedAttributes, lenEntry, lenRefer);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index d3a43f1..ca9a7c2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -19,6 +19,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
@@ -52,11 +53,13 @@
final boolean isOnModulePath;
static class PackageCacheEntry {
+ WeakReference<ZipFile> zipFile;
long lastModified;
long fileSize;
SimpleSet packageSet;
- PackageCacheEntry(long lastModified, long fileSize, SimpleSet packageSet) {
+ PackageCacheEntry(ZipFile zipFile, long lastModified, long fileSize, SimpleSet packageSet) {
+ this.zipFile = new WeakReference<>(zipFile);
this.lastModified = lastModified;
this.fileSize = fileSize;
this.packageSet = packageSet;
@@ -84,15 +87,19 @@
protected SimpleSet findPackageSet() {
String zipFileName = this.zipFilename;
PackageCacheEntry cacheEntry = (PackageCacheEntry) PackageCache.get(zipFileName);
+ if(cacheEntry != null && cacheEntry.zipFile.get() == this.zipFile) {
+ return cacheEntry.packageSet;
+ }
long timestamp = this.lastModified();
long fileSize = new File(zipFileName).length();
if (cacheEntry != null && cacheEntry.lastModified == timestamp && cacheEntry.fileSize == fileSize) {
+ cacheEntry.zipFile = new WeakReference<ZipFile>(this.zipFile);
return cacheEntry.packageSet;
}
final SimpleSet packageSet = new SimpleSet(41);
packageSet.add(""); //$NON-NLS-1$
readJarContent(packageSet);
- PackageCache.put(zipFileName, new PackageCacheEntry(timestamp, fileSize, packageSet));
+ PackageCache.put(zipFileName, new PackageCacheEntry(this.zipFile, timestamp, fileSize, packageSet));
return packageSet;
}
protected String readJarContent(final SimpleSet packageSet) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedReader.java
index cd56d74..811477a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedReader.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedReader.java
@@ -100,13 +100,17 @@
* @see CompressedWriter#writeIntInRange(int, int)
**/
public int readIntInRange(int range) throws IOException {
- if (range < 0 || range > 0xFFFF) {
+ if (range < 0 || range > 0xFFFFFF) {
return this.in.readInt();
} else {
if (range <= 0xFF) {
return Byte.toUnsignedInt(this.in.readByte());
- } else {
+ } else if (range <= 0xFFFF) {
return Short.toUnsignedInt(this.in.readShort());
+ } else {
+ byte b = this.in.readByte();
+ short s = this.in.readShort();
+ return ((s << 8 | (b & 0xff))) & 0xffffff;
}
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedWriter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedWriter.java
index 1b298bf..8bd6fb7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedWriter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompressedWriter.java
@@ -105,7 +105,7 @@
**/
public void writeIntInRange(int v, int range) throws IOException {
// => typically(0<range<256) only one byte per int
- if (range < 0 || range > 0xFFFF) {
+ if (range < 0 || range > 0xFFFFFF) {
this.out.writeInt(v);
} else {
if (v >= range) {
@@ -116,8 +116,11 @@
}
if (range <= 0xFF) {
this.out.writeByte(v);
- } else {
+ } else if (range <= 0xFFFF) {
this.out.writeShort(v);
+ } else {
+ this.out.writeByte(v);
+ this.out.writeShort(v >>> 8);
}
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index ebe1678..03a261d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -381,13 +381,28 @@
// do nothing, probably a non module project
}
}
- // collect the output folders, skipping duplicates
+ // collect the output folders, skipping, or merging duplicates
next : for (int i = 0, l = this.sourceLocations.length; i < l; i++) {
ClasspathMultiDirectory md = this.sourceLocations[i];
IPath outputPath = md.binaryFolder.getFullPath();
+ String eeaPath = md.externalAnnotationPath;
for (int j = 0; j < i; j++) { // compare against previously walked source folders
- if (outputPath.equals(this.sourceLocations[j].binaryFolder.getFullPath())) {
- md.hasIndependentOutputFolder = this.sourceLocations[j].hasIndependentOutputFolder;
+ ClasspathMultiDirectory previousMd = this.sourceLocations[j];
+ if (outputPath.equals(previousMd.binaryFolder.getFullPath())) {
+ if ((eeaPath == null) != (previousMd.externalAnnotationPath == null) // one has eeaPath other doesn't ?
+ && md.isOnModulePath == previousMd.isOnModulePath
+ && md.accessRuleSet == previousMd.accessRuleSet)
+ {
+ // only relevant difference between md and previousMd is a non-conflicting eea-path, so unify into one entry *with* eea-path:
+ if (eeaPath == null)
+ eeaPath = previousMd.externalAnnotationPath;
+ int prev = outputFolders.indexOf(previousMd);
+ if (prev != -1) {
+ outputFolders.set(prev, new ClasspathDirectory(md.binaryFolder, true, md.accessRuleSet, new Path(eeaPath), md.isOnModulePath));
+ continue next;
+ }
+ }
+ md.hasIndependentOutputFolder = previousMd.hasIndependentOutputFolder;
continue next;
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index 96441aa..013c2cb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -80,7 +80,7 @@
private StringSet structurallyChangedTypes;
public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
-public static final byte VERSION = 0x0025;
+public static final byte VERSION = 0x0026;
static final byte SOURCE_FOLDER = 1;
static final byte BINARY_FOLDER = 2;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
index 5ea6358..aae3012 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
@@ -10,4433 +10,320 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Fraunhofer FIRST - extended API and implementation
- * Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core.util;
-import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.parser.NLSTag;
-import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
-import org.eclipse.jdt.internal.compiler.util.CharDeduplication;
-import org.eclipse.jdt.internal.compiler.util.Util;
+/**
+ * This class acts as a facade to the internal Scanner implementation and delegates
+ * all the work to the internal Scanner instance.
+ *
+ * <p>
+ * <b>Note for maintainers</b>
+ * No additional logic should be added here except adopting NON-API constants
+ * returned by {@link #getNextToken()} from {@link TerminalTokens} to {@link ITerminalSymbols}.
+ */
public class PublicScanner implements IScanner, ITerminalSymbols {
- @SuppressWarnings("deprecation")
- private static final int InternalTokenNameIdentifier = TokenNameIdentifier;
+ private final Scanner delegate;
- //public int newIdentCount = 0;
+ public PublicScanner(
+ boolean tokenizeComments,
+ boolean tokenizeWhiteSpace,
+ boolean checkNonExternalizedStringLiterals,
+ long sourceLevel,
+ long complianceLevel,
+ char[][] taskTags,
+ char[][] taskPriorities,
+ boolean isTaskCaseSensitive,
+ boolean isPreviewEnabled,
+ boolean recordLineSeparator) {
- /* APIs ares
- - getNextToken() which return the current type of the token
- (this value is not memorized by the scanner)
- - getCurrentTokenSource() which provides with the token "REAL" source
- (aka all unicode have been transformed into a correct char)
- - sourceStart gives the position into the stream
- - currentPosition-1 gives the sourceEnd position into the stream
- */
- public long sourceLevel;
- public long complianceLevel;
- public boolean previewEnabled;
+ this.delegate = createScanner(tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, sourceLevel,
+ complianceLevel, taskTags, taskPriorities, isTaskCaseSensitive, isPreviewEnabled);
+ this.delegate.recordLineSeparator = recordLineSeparator;
+ }
- // 1.4 feature
- public boolean useAssertAsAnIndentifier = false;
- //flag indicating if processed source contains occurrences of keyword assert
- public boolean containsAssertKeyword = false;
+ protected Scanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace,
+ boolean checkNonExternalizedStringLiterals, long sourceLevel, long complianceLevel, char[][] taskTags,
+ char[][] taskPriorities, boolean isTaskCaseSensitive, boolean isPreviewEnabled) {
+ return new Scanner(tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals,
+ sourceLevel, complianceLevel, taskTags, taskPriorities, isTaskCaseSensitive, isPreviewEnabled);
+ }
- // 1.5 feature
- public boolean useEnumAsAnIndentifier = false;
+ @Override
+ public int getCurrentTokenEndPosition(){
+ return this.delegate.getCurrentTokenEndPosition();
+ }
-//{ObjectTeams: the scanner is now quite stateful:
- // a master switch to turn off all OT keywords:
- public boolean parsePureJavaOnly = false;
- // experimental switch, set to true if you encounter problems with the scanner:
- public boolean parseOTJonly = true;
+ @Override
+ public char[] getCurrentTokenSource() {
+ return this.delegate.getCurrentTokenSource();
+ }
- // general switch for std-Java vs. OT/J
- protected boolean _isOTSource = this.parseOTJonly; // initialized also in setSource().
- /** Fully enable OT/J keywords. */
- public void enterOTSource() {
- this._isOTSource = true;
- this._teamKeywordSeen = false; // not needed any more
- }
+ @Override
+ public final char[] getRawTokenSource() {
+ return this.delegate.getRawTokenSource();
+ }
- // within the body of a base predicate "base" is not a keyword
- protected boolean _forceBaseIsIdentifier = false;
- // seen 'team' but no 'class'/'interface' yet -> 'base' could still be an imported package name.
- protected boolean _teamKeywordSeen = false;
- // directly after 'import' 'base' is always a keyword/modifier:
- protected boolean _atStartOfImport = false;
- public void forceBaseIsIdentifier() {
- this._forceBaseIsIdentifier = true;
- }
- public void restoreBaseKeyword() {
- this._forceBaseIsIdentifier = false;
- }
- protected boolean baseIsKeyword(boolean atStartOfImport) {
- if (this.parsePureJavaOnly)
- return false;
- // "base" keyword may appear before 'class' header of containing
- // team/role has been consumed.
- if (this.currentCharacter == '.')
- atStartOfImport = false;
- return (this._isOTSource || atStartOfImport) && !this._forceBaseIsIdentifier;
- }
+ @Override
+ public int getCurrentTokenStartPosition(){
+ return this.delegate.startPosition;
+ }
- // remember if the previous token was a callin/callout symbol ...
- protected boolean _calloutSeen = false;
- protected boolean _callinSeen = false;
- // ... or the "precedence" keyword
- protected boolean _precedenceSeen = false;
+ /*
+ * Search the source position corresponding to the end of a given line number
+ *
+ * Line numbers are 1-based, and relative to the scanner initialPosition.
+ * Character positions are 0-based.
+ *
+ * In case the given line number is inconsistent, answers -1.
+ */
+ @Override
+ public final int getLineEnd(int lineNumber) {
+ return this.delegate.getLineEnd(lineNumber);
+ }
- // after a '.' even 'team' can be an identifier:
- private int _dotSeen = 0; // 0: no, 1: previos, 2: this token
+ @Override
+ public final int[] getLineEnds() {
+ return this.delegate.getLineEnds();
+ }
- public void resetOTFlags() {
- this._isOTSource = this.parseOTJonly;
- this._teamKeywordSeen = false;
- this._forceBaseIsIdentifier = false;
- this._callinSeen = false;
- this._calloutSeen = false;
- }
+ /**
+ * Search the source position corresponding to the beginning of a given line number
+ *
+ * Line numbers are 1-based, and relative to the scanner initialPosition.
+ * Character positions are 0-based.
+ *
+ * e.g. getLineStart(1) --> 0 indicates that the first line starts at character 0.
+ *
+ * In case the given line number is inconsistent, answers -1.
+ *
+ * @param lineNumber int
+ * @return int
+ */
+ @Override
+ public final int getLineStart(int lineNumber) {
+ return this.delegate.getLineStart(lineNumber);
+ }
- /**
- * Check whether a given terminal token is currently enabled.
- * Some keywords can be disabled:
- * (base) as callin playedBy precedence tsuper when with
- * Only within a join point query:
- * # .. elementof
- * Some keyworkds can only be disabled by parsePureJavaOnly:
- * team within
- */
- public boolean isTokenEnabled(int sym) {
- switch (sym) {
- case TokenNameteam:
- case TokenNamewithin:
- return !this.parsePureJavaOnly;
+ @Override
+ public int getNextToken() throws InvalidInputException {
+ int nextToken = this.delegate.getNextToken();
+ int symbol = translateTokenToTerminalSymbol(nextToken);
+ return symbol;
+ }
- case TokenNamebase:
- return baseIsKeyword(false);
- case TokenNameas:
- case TokenNameBINDIN:
- case TokenNameBINDOUT:
- case TokenNamecallin:
- case TokenNameplayedBy:
- case TokenNameprecedence:
- case TokenNametsuper:
- case TokenNamewhen:
- case TokenNamewith:
- return this._isOTSource;
- }
- return true;
- }
-// SH}
-
- public boolean recordLineSeparator = false;
- public char currentCharacter;
- public int startPosition;
- public int currentPosition;
- public int initialPosition, eofPosition;
- // after this position eof are generated instead of real token from the source
-
- public boolean skipComments = false;
- public boolean tokenizeComments = false;
- public boolean tokenizeWhiteSpace = false;
-
- //source should be viewed as a window (aka a part)
- //of a entire very large stream
- public char source[];
-
- //unicode support
- public char[] withoutUnicodeBuffer;
- public int withoutUnicodePtr; //when == 0 ==> no unicode in the current token
- public boolean unicodeAsBackSlash = false;
-
- public boolean scanningFloatLiteral = false;
-
- //support for /** comments
- public final static int COMMENT_ARRAYS_SIZE = 30;
- public int[] commentStops = new int[COMMENT_ARRAYS_SIZE];
- public int[] commentStarts = new int[COMMENT_ARRAYS_SIZE];
- public int[] commentTagStarts = new int[COMMENT_ARRAYS_SIZE];
- public int commentPtr = -1; // no comment test with commentPtr value -1
- protected int lastCommentLinePosition = -1;
-
- // task tag support
- public char[][] foundTaskTags = null;
- public char[][] foundTaskMessages;
- public char[][] foundTaskPriorities = null;
- public int[][] foundTaskPositions;
- public int foundTaskCount = 0;
- public char[][] taskTags = null;
- public char[][] taskPriorities = null;
- public boolean isTaskCaseSensitive = true;
-
- //diet parsing support - jump over some method body when requested
- public boolean diet = false;
-
- //support for the poor-line-debuggers ....
- //remember the position of the cr/lf
- public int[] lineEnds = new int[250];
- public int linePtr = -1;
- public boolean wasAcr = false;
-
- public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$
-
- public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$
- public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$
- public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant"; //$NON-NLS-1$
- public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$
- public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$
- public static final String INVALID_TEXTBLOCK = "Invalid_Textblock"; //$NON-NLS-1$
- public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$
- public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$
- public static final String INVALID_LOW_SURROGATE = "Invalid_Low_Surrogate"; //$NON-NLS-1$
- public static final String INVALID_HIGH_SURROGATE = "Invalid_High_Surrogate"; //$NON-NLS-1$
-
- public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$
- public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
- public static final String UNTERMINATED_TEXT_BLOCK = "Unterminated_Text_Block"; //$NON-NLS-1$
- public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
- public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
- public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$
- private static final int[] EMPTY_LINE_ENDS = Util.EMPTY_INT_ARRAY;
-
- public static final String INVALID_BINARY = "Invalid_Binary_Literal"; //$NON-NLS-1$
- public static final String BINARY_LITERAL_NOT_BELOW_17 = "Binary_Literal_Not_Below_17"; //$NON-NLS-1$
- public static final String ILLEGAL_HEXA_LITERAL = "Illegal_Hexa_Literal"; //$NON-NLS-1$
- public static final String INVALID_UNDERSCORE = "Invalid_Underscore"; //$NON-NLS-1$
- public static final String UNDERSCORES_IN_LITERALS_NOT_BELOW_17 = "Underscores_In_Literals_Not_Below_17"; //$NON-NLS-1$`
-
- // support for detecting non-externalized string literals
- public static final char[] TAG_PREFIX= "//$NON-NLS-".toCharArray(); //$NON-NLS-1$
- public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length;
- public static final char TAG_POSTFIX= '$';
- public static final int TAG_POSTFIX_LENGTH= 1;
- private NLSTag[] nlsTags = null;
- protected int nlsTagsPtr;
- public boolean checkNonExternalizedStringLiterals;
-
- protected int lastPosition;
-
- // generic support
- public boolean returnOnlyGreater = false;
-
- public boolean insideRecovery = false;
-
- public static final int RoundBracket = 0;
- public static final int SquareBracket = 1;
- public static final int CurlyBracket = 2;
- public static final int BracketKinds = 3;
-
- // extended unicode support
- public static final int LOW_SURROGATE_MIN_VALUE = 0xDC00;
- public static final int HIGH_SURROGATE_MIN_VALUE = 0xD800;
- public static final int HIGH_SURROGATE_MAX_VALUE = 0xDBFF;
- public static final int LOW_SURROGATE_MAX_VALUE = 0xDFFF;
-
- // text block support - 13
- /* package */ int rawStart = -1;
-
- private CharDeduplication deduplication = CharDeduplication.getThreadLocalInstance();
-
-public PublicScanner() {
- this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
-}
-
-public PublicScanner(
- boolean tokenizeComments,
- boolean tokenizeWhiteSpace,
- boolean checkNonExternalizedStringLiterals,
- long sourceLevel,
- long complianceLevel,
- char[][] taskTags,
- char[][] taskPriorities,
- boolean isTaskCaseSensitive) {
- this(tokenizeComments,
- tokenizeWhiteSpace,
- checkNonExternalizedStringLiterals,
- sourceLevel,
- complianceLevel,
- taskTags,
- taskPriorities,
- isTaskCaseSensitive,
- true);
-}
-public PublicScanner(
- boolean tokenizeComments,
- boolean tokenizeWhiteSpace,
- boolean checkNonExternalizedStringLiterals,
- long sourceLevel,
- long complianceLevel,
- char[][] taskTags,
- char[][] taskPriorities,
- boolean isTaskCaseSensitive,
- boolean previewEnabled) {
-
- this.eofPosition = Integer.MAX_VALUE;
- this.tokenizeComments = tokenizeComments;
- this.tokenizeWhiteSpace = tokenizeWhiteSpace;
- this.sourceLevel = sourceLevel;
- this.complianceLevel = complianceLevel;
- this.previewEnabled = previewEnabled;
- this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
- if (taskTags != null) {
- int taskTagsLength = taskTags.length;
- int length = taskTagsLength;
- if (taskPriorities != null) {
- int taskPrioritiesLength = taskPriorities.length;
- if (taskPrioritiesLength != taskTagsLength) {
- if (taskPrioritiesLength > taskTagsLength) {
- System.arraycopy(taskPriorities, 0, (taskPriorities = new char[taskTagsLength][]), 0, taskTagsLength);
- } else {
- System.arraycopy(taskTags, 0, (taskTags = new char[taskPrioritiesLength][]), 0, taskPrioritiesLength);
- length = taskPrioritiesLength;
- }
- }
- int[] initialIndexes = new int[length];
- for (int i = 0; i < length; i++) {
- initialIndexes[i] = i;
- }
- Util.reverseQuickSort(taskTags, 0, length - 1, initialIndexes);
- char[][] temp = new char[length][];
- for (int i = 0; i < length; i++) {
- temp[i] = taskPriorities[initialIndexes[i]];
- }
- this.taskPriorities = temp;
- } else {
- Util.reverseQuickSort(taskTags, 0, length - 1);
+ /**
+ * Translates internal generated constants from {@link TerminalTokens} to public constants defined in
+ * {@link ITerminalSymbols}.
+ * <p>
+ * There is PublicScannerTest that validates the translation and can generate switch body for this method
+ * on changes in Scanner / TerminalTokens.
+ * <p>
+ * Note for maintainers: new tokens from {@link TerminalTokens} should be added to {@link ITerminalSymbols} with
+ * <b>adopted</b> numerical values (they differ in each interface).
+ */
+ @Deprecated // uses deprecated TerminalTokensIdentifier
+ private int translateTokenToTerminalSymbol(int nextToken) throws InvalidInputException {
+ switch (nextToken) {
+ case TerminalTokens.TokenNameAND : nextToken = ITerminalSymbols.TokenNameAND; break;
+ case TerminalTokens.TokenNameAND_AND : nextToken = ITerminalSymbols.TokenNameAND_AND; break;
+ case TerminalTokens.TokenNameAND_EQUAL : nextToken = ITerminalSymbols.TokenNameAND_EQUAL; break;
+ case TerminalTokens.TokenNameARROW : nextToken = ITerminalSymbols.TokenNameARROW; break;
+ case TerminalTokens.TokenNameAT : nextToken = ITerminalSymbols.TokenNameAT; break;
+ case TerminalTokens.TokenNameAT308 : nextToken = ITerminalSymbols.TokenNameAT; break;
+ case TerminalTokens.TokenNameAT308DOTDOTDOT : nextToken = ITerminalSymbols.TokenNameAT; break;
+ case TerminalTokens.TokenNameATOT : nextToken = ITerminalSymbols.TokenNameAT; break;
+ case TerminalTokens.TokenNameBINDIN : nextToken = ITerminalSymbols.TokenNameBINDIN; break;
+ case TerminalTokens.TokenNameBINDOUT : nextToken = ITerminalSymbols.TokenNameBINDOUT; break;
+ case TerminalTokens.TokenNameBeginCaseElement : nextToken = getNextToken(); break;
+ case TerminalTokens.TokenNameBeginCaseExpr : nextToken = getNextToken(); break;
+ case TerminalTokens.TokenNameBeginIntersectionCast : nextToken = getNextToken(); break;
+ case TerminalTokens.TokenNameBeginLambda : nextToken = getNextToken(); break;
+ case TerminalTokens.TokenNameBeginTypeArguments : nextToken = getNextToken(); break;
+ case TerminalTokens.TokenNameCALLOUT_OVERRIDE : nextToken = ITerminalSymbols.TokenNameCALLOUT_OVERRIDE; break;
+ case TerminalTokens.TokenNameCOLON : nextToken = ITerminalSymbols.TokenNameCOLON; break;
+ case TerminalTokens.TokenNameCOLON_COLON : nextToken = ITerminalSymbols.TokenNameCOLON_COLON; break;
+ case TerminalTokens.TokenNameCOMMA : nextToken = ITerminalSymbols.TokenNameCOMMA; break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK : nextToken = ITerminalSymbols.TokenNameCOMMENT_BLOCK; break;
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC : nextToken = ITerminalSymbols.TokenNameCOMMENT_JAVADOC; break;
+ case TerminalTokens.TokenNameCOMMENT_LINE : nextToken = ITerminalSymbols.TokenNameCOMMENT_LINE; break;
+ case TerminalTokens.TokenNameCharacterLiteral : nextToken = ITerminalSymbols.TokenNameCharacterLiteral; break;
+ case TerminalTokens.TokenNameDIVIDE : nextToken = ITerminalSymbols.TokenNameDIVIDE; break;
+ case TerminalTokens.TokenNameDIVIDE_EQUAL : nextToken = ITerminalSymbols.TokenNameDIVIDE_EQUAL; break;
+ case TerminalTokens.TokenNameDOT : nextToken = ITerminalSymbols.TokenNameDOT; break;
+ case TerminalTokens.TokenNameDoubleLiteral : nextToken = ITerminalSymbols.TokenNameDoubleLiteral; break;
+ case TerminalTokens.TokenNameELLIPSIS : nextToken = ITerminalSymbols.TokenNameELLIPSIS; break;
+ case TerminalTokens.TokenNameEOF : nextToken = ITerminalSymbols.TokenNameEOF; break;
+ case TerminalTokens.TokenNameEQUAL : nextToken = ITerminalSymbols.TokenNameEQUAL; break;
+ case TerminalTokens.TokenNameEQUAL_EQUAL : nextToken = ITerminalSymbols.TokenNameEQUAL_EQUAL; break;
+ case TerminalTokens.TokenNameERROR : nextToken = ITerminalSymbols.TokenNameERROR; break;
+ case TerminalTokens.TokenNameElidedSemicolonAndRightBrace : nextToken = getNextToken(); break;
+ case TerminalTokens.TokenNameFloatingPointLiteral : nextToken = ITerminalSymbols.TokenNameFloatingPointLiteral; break;
+ case TerminalTokens.TokenNameGREATER : nextToken = ITerminalSymbols.TokenNameGREATER; break;
+ case TerminalTokens.TokenNameGREATER_EQUAL : nextToken = ITerminalSymbols.TokenNameGREATER_EQUAL; break;
+ case TerminalTokens.TokenNameIdentifier : nextToken = ITerminalSymbols.TokenNameIdentifier; break;
+ case TerminalTokens.TokenNameIntegerLiteral : nextToken = ITerminalSymbols.TokenNameIntegerLiteral; break;
+ case TerminalTokens.TokenNameLBRACE : nextToken = ITerminalSymbols.TokenNameLBRACE; break;
+ case TerminalTokens.TokenNameLBRACKET : nextToken = ITerminalSymbols.TokenNameLBRACKET; break;
+ case TerminalTokens.TokenNameLEFT_SHIFT : nextToken = ITerminalSymbols.TokenNameLEFT_SHIFT; break;
+ case TerminalTokens.TokenNameLEFT_SHIFT_EQUAL : nextToken = ITerminalSymbols.TokenNameLEFT_SHIFT_EQUAL; break;
+ case TerminalTokens.TokenNameLESS : nextToken = ITerminalSymbols.TokenNameLESS; break;
+ case TerminalTokens.TokenNameLESS_EQUAL : nextToken = ITerminalSymbols.TokenNameLESS_EQUAL; break;
+ case TerminalTokens.TokenNameLPAREN : nextToken = ITerminalSymbols.TokenNameLPAREN; break;
+ case TerminalTokens.TokenNameLongLiteral : nextToken = ITerminalSymbols.TokenNameLongLiteral; break;
+ case TerminalTokens.TokenNameMINUS : nextToken = ITerminalSymbols.TokenNameMINUS; break;
+ case TerminalTokens.TokenNameMINUS_EQUAL : nextToken = ITerminalSymbols.TokenNameMINUS_EQUAL; break;
+ case TerminalTokens.TokenNameMINUS_MINUS : nextToken = ITerminalSymbols.TokenNameMINUS_MINUS; break;
+ case TerminalTokens.TokenNameMULTIPLY : nextToken = ITerminalSymbols.TokenNameMULTIPLY; break;
+ case TerminalTokens.TokenNameMULTIPLY_EQUAL : nextToken = ITerminalSymbols.TokenNameMULTIPLY_EQUAL; break;
+ case TerminalTokens.TokenNameNOT : nextToken = ITerminalSymbols.TokenNameNOT; break;
+ case TerminalTokens.TokenNameNOT_EQUAL : nextToken = ITerminalSymbols.TokenNameNOT_EQUAL; break;
+ case TerminalTokens.TokenNameNotAToken : nextToken = ITerminalSymbols.TokenNameNotAToken; break;
+ case TerminalTokens.TokenNameOR : nextToken = ITerminalSymbols.TokenNameOR; break;
+ case TerminalTokens.TokenNameOR_EQUAL : nextToken = ITerminalSymbols.TokenNameOR_EQUAL; break;
+ case TerminalTokens.TokenNameOR_OR : nextToken = ITerminalSymbols.TokenNameOR_OR; break;
+ case TerminalTokens.TokenNamePLUS : nextToken = ITerminalSymbols.TokenNamePLUS; break;
+ case TerminalTokens.TokenNamePLUS_EQUAL : nextToken = ITerminalSymbols.TokenNamePLUS_EQUAL; break;
+ case TerminalTokens.TokenNamePLUS_PLUS : nextToken = ITerminalSymbols.TokenNamePLUS_PLUS; break;
+ case TerminalTokens.TokenNameQUESTION : nextToken = ITerminalSymbols.TokenNameQUESTION; break;
+ case TerminalTokens.TokenNameRBRACE : nextToken = ITerminalSymbols.TokenNameRBRACE; break;
+ case TerminalTokens.TokenNameRBRACKET : nextToken = ITerminalSymbols.TokenNameRBRACKET; break;
+ case TerminalTokens.TokenNameREMAINDER : nextToken = ITerminalSymbols.TokenNameREMAINDER; break;
+ case TerminalTokens.TokenNameREMAINDER_EQUAL : nextToken = ITerminalSymbols.TokenNameREMAINDER_EQUAL; break;
+ case TerminalTokens.TokenNameRIGHT_SHIFT : nextToken = ITerminalSymbols.TokenNameRIGHT_SHIFT; break;
+ case TerminalTokens.TokenNameRIGHT_SHIFT_EQUAL : nextToken = ITerminalSymbols.TokenNameRIGHT_SHIFT_EQUAL; break;
+ case TerminalTokens.TokenNameRPAREN : nextToken = ITerminalSymbols.TokenNameRPAREN; break;
+ case TerminalTokens.TokenNameRestrictedIdentifierYield : nextToken = ITerminalSymbols.TokenNameRestrictedIdentifierYield; break;
+ case TerminalTokens.TokenNameRestrictedIdentifierpermits : nextToken = ITerminalSymbols.TokenNameRestrictedIdentifierpermits; break;
+ case TerminalTokens.TokenNameRestrictedIdentifierrecord : nextToken = ITerminalSymbols.TokenNameRestrictedIdentifierrecord; break;
+ case TerminalTokens.TokenNameRestrictedIdentifiersealed : nextToken = ITerminalSymbols.TokenNameRestrictedIdentifiersealed; break;
+ case TerminalTokens.TokenNameSEMICOLON : nextToken = ITerminalSymbols.TokenNameSEMICOLON; break;
+ case TerminalTokens.TokenNameSingleQuoteStringLiteral : nextToken = ITerminalSymbols.TokenNameSingleQuoteStringLiteral; break;
+ case TerminalTokens.TokenNameStringLiteral : nextToken = ITerminalSymbols.TokenNameStringLiteral; break;
+ case TerminalTokens.TokenNameTWIDDLE : nextToken = ITerminalSymbols.TokenNameTWIDDLE; break;
+ case TerminalTokens.TokenNameTextBlock : nextToken = ITerminalSymbols.TokenNameTextBlock; break;
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT : nextToken = ITerminalSymbols.TokenNameUNSIGNED_RIGHT_SHIFT; break;
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : nextToken = ITerminalSymbols.TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL; break;
+ case TerminalTokens.TokenNameWHITESPACE : nextToken = ITerminalSymbols.TokenNameWHITESPACE; break;
+ case TerminalTokens.TokenNameXOR : nextToken = ITerminalSymbols.TokenNameXOR; break;
+ case TerminalTokens.TokenNameXOR_EQUAL : nextToken = ITerminalSymbols.TokenNameXOR_EQUAL; break;
+ case TerminalTokens.TokenNameabstract : nextToken = ITerminalSymbols.TokenNameabstract; break;
+ case TerminalTokens.TokenNameafter : nextToken = ITerminalSymbols.TokenNameafter; break;
+ case TerminalTokens.TokenNameas : nextToken = ITerminalSymbols.TokenNameas; break;
+ case TerminalTokens.TokenNameassert : nextToken = ITerminalSymbols.TokenNameassert; break;
+ case TerminalTokens.TokenNamebase : nextToken = ITerminalSymbols.TokenNamebase; break;
+ case TerminalTokens.TokenNamebefore : nextToken = ITerminalSymbols.TokenNamebefore; break;
+ case TerminalTokens.TokenNameboolean : nextToken = ITerminalSymbols.TokenNameboolean; break;
+ case TerminalTokens.TokenNamebreak : nextToken = ITerminalSymbols.TokenNamebreak; break;
+ case TerminalTokens.TokenNamebyte : nextToken = ITerminalSymbols.TokenNamebyte; break;
+ case TerminalTokens.TokenNamecallin : nextToken = ITerminalSymbols.TokenNamecallin; break;
+ case TerminalTokens.TokenNamecase : nextToken = ITerminalSymbols.TokenNamecase; break;
+ case TerminalTokens.TokenNamecatch : nextToken = ITerminalSymbols.TokenNamecatch; break;
+ case TerminalTokens.TokenNamechar : nextToken = ITerminalSymbols.TokenNamechar; break;
+ case TerminalTokens.TokenNameclass : nextToken = ITerminalSymbols.TokenNameclass; break;
+ case TerminalTokens.TokenNameconst : nextToken = ITerminalSymbols.TokenNameconst; break;
+ case TerminalTokens.TokenNamecontinue : nextToken = ITerminalSymbols.TokenNamecontinue; break;
+ case TerminalTokens.TokenNamedefault : nextToken = ITerminalSymbols.TokenNamedefault; break;
+ case TerminalTokens.TokenNamedo : nextToken = ITerminalSymbols.TokenNamedo; break;
+ case TerminalTokens.TokenNamedouble : nextToken = ITerminalSymbols.TokenNamedouble; break;
+ case TerminalTokens.TokenNameelse : nextToken = ITerminalSymbols.TokenNameelse; break;
+ case TerminalTokens.TokenNameenum : nextToken = ITerminalSymbols.TokenNameenum; break;
+ case TerminalTokens.TokenNameextends : nextToken = ITerminalSymbols.TokenNameextends; break;
+ case TerminalTokens.TokenNamefalse : nextToken = ITerminalSymbols.TokenNamefalse; break;
+ case TerminalTokens.TokenNamefinal : nextToken = ITerminalSymbols.TokenNamefinal; break;
+ case TerminalTokens.TokenNamefinally : nextToken = ITerminalSymbols.TokenNamefinally; break;
+ case TerminalTokens.TokenNamefloat : nextToken = ITerminalSymbols.TokenNamefloat; break;
+ case TerminalTokens.TokenNamefor : nextToken = ITerminalSymbols.TokenNamefor; break;
+ case TerminalTokens.TokenNameget : nextToken = ITerminalSymbols.TokenNameget; break;
+ case TerminalTokens.TokenNamegoto : nextToken = ITerminalSymbols.TokenNamegoto; break;
+ case TerminalTokens.TokenNameif : nextToken = ITerminalSymbols.TokenNameif; break;
+ case TerminalTokens.TokenNameimplements : nextToken = ITerminalSymbols.TokenNameimplements; break;
+ case TerminalTokens.TokenNameimport : nextToken = ITerminalSymbols.TokenNameimport; break;
+ case TerminalTokens.TokenNameinstanceof : nextToken = ITerminalSymbols.TokenNameinstanceof; break;
+ case TerminalTokens.TokenNameint : nextToken = ITerminalSymbols.TokenNameint; break;
+ case TerminalTokens.TokenNameinterface : nextToken = ITerminalSymbols.TokenNameinterface; break;
+ case TerminalTokens.TokenNamelong : nextToken = ITerminalSymbols.TokenNamelong; break;
+ case TerminalTokens.TokenNamenative : nextToken = ITerminalSymbols.TokenNamenative; break;
+ case TerminalTokens.TokenNamenew : nextToken = ITerminalSymbols.TokenNamenew; break;
+ case TerminalTokens.TokenNamenon_sealed : nextToken = ITerminalSymbols.TokenNamenon_sealed; break;
+ case TerminalTokens.TokenNamenull : nextToken = ITerminalSymbols.TokenNamenull; break;
+ case TerminalTokens.TokenNamepackage : nextToken = ITerminalSymbols.TokenNamepackage; break;
+ case TerminalTokens.TokenNameplayedBy : nextToken = ITerminalSymbols.TokenNameplayedBy; break;
+ case TerminalTokens.TokenNameprecedence : nextToken = ITerminalSymbols.TokenNameprecedence; break;
+ case TerminalTokens.TokenNameprivate : nextToken = ITerminalSymbols.TokenNameprivate; break;
+ case TerminalTokens.TokenNameprotected : nextToken = ITerminalSymbols.TokenNameprotected; break;
+ case TerminalTokens.TokenNamepublic : nextToken = ITerminalSymbols.TokenNamepublic; break;
+ case TerminalTokens.TokenNamereplace : nextToken = ITerminalSymbols.TokenNamereplace; break;
+ case TerminalTokens.TokenNamereturn : nextToken = ITerminalSymbols.TokenNamereturn; break;
+ case TerminalTokens.TokenNameset : nextToken = ITerminalSymbols.TokenNameset; break;
+ case TerminalTokens.TokenNameshort : nextToken = ITerminalSymbols.TokenNameshort; break;
+ case TerminalTokens.TokenNamestatic : nextToken = ITerminalSymbols.TokenNamestatic; break;
+ case TerminalTokens.TokenNamestrictfp : nextToken = ITerminalSymbols.TokenNamestrictfp; break;
+ case TerminalTokens.TokenNamesuper : nextToken = ITerminalSymbols.TokenNamesuper; break;
+ case TerminalTokens.TokenNameswitch : nextToken = ITerminalSymbols.TokenNameswitch; break;
+ case TerminalTokens.TokenNamesynchronized : nextToken = ITerminalSymbols.TokenNamesynchronized; break;
+ case TerminalTokens.TokenNameteam : nextToken = ITerminalSymbols.TokenNameteam; break;
+ case TerminalTokens.TokenNamethis : nextToken = ITerminalSymbols.TokenNamethis; break;
+ case TerminalTokens.TokenNamethrow : nextToken = ITerminalSymbols.TokenNamethrow; break;
+ case TerminalTokens.TokenNamethrows : nextToken = ITerminalSymbols.TokenNamethrows; break;
+ case TerminalTokens.TokenNametransient : nextToken = ITerminalSymbols.TokenNametransient; break;
+ case TerminalTokens.TokenNametrue : nextToken = ITerminalSymbols.TokenNametrue; break;
+ case TerminalTokens.TokenNametry : nextToken = ITerminalSymbols.TokenNametry; break;
+ case TerminalTokens.TokenNametsuper : nextToken = ITerminalSymbols.TokenNametsuper; break;
+ case TerminalTokens.TokenNamevoid : nextToken = ITerminalSymbols.TokenNamevoid; break;
+ case TerminalTokens.TokenNamevolatile : nextToken = ITerminalSymbols.TokenNamevolatile; break;
+ case TerminalTokens.TokenNamewhen : nextToken = ITerminalSymbols.TokenNamewhen; break;
+ case TerminalTokens.TokenNamewhile : nextToken = ITerminalSymbols.TokenNamewhile; break;
+ case TerminalTokens.TokenNamewith : nextToken = ITerminalSymbols.TokenNamewith; break;
+ case TerminalTokens.TokenNamewithin : nextToken = ITerminalSymbols.TokenNamewithin; break;
+ default:
+ throw new InvalidInputException("Unknown token (check Scanner/TerminalTokens): " + nextToken); //$NON-NLS-1$
}
- this.taskTags = taskTags;
- this.isTaskCaseSensitive = isTaskCaseSensitive;
+ return nextToken;
}
-}
-public PublicScanner(
- boolean tokenizeComments,
- boolean tokenizeWhiteSpace,
- boolean checkNonExternalizedStringLiterals,
- long sourceLevel,
- char[][] taskTags,
- char[][] taskPriorities,
- boolean isTaskCaseSensitive) {
-
- this(
- tokenizeComments,
- tokenizeWhiteSpace,
- checkNonExternalizedStringLiterals,
- sourceLevel,
- sourceLevel,
- taskTags,
- taskPriorities,
- isTaskCaseSensitive);
-}
-
-public final boolean atEnd() {
- // This code is not relevant if source is
- // Only a part of the real stream input
-
- return this.eofPosition <= this.currentPosition;
-}
-
-// chech presence of task: tags
-// TODO (frederic) see if we need to take unicode characters into account...
-public void checkTaskTag(int commentStart, int commentEnd) throws InvalidInputException {
- char[] src = this.source;
-
- // only look for newer task: tags
- if (this.foundTaskCount > 0
- && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
- return;
+ @Override
+ public char[] getSource(){
+ return this.delegate.getSource();
}
- int foundTaskIndex = this.foundTaskCount;
- char previous = src[commentStart+1]; // should be '*' or '/'
- for (
- int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) {
- char[] tag = null;
- char[] priority = null;
- // check for tag occurrence only if not ambiguous with javadoc tag
- if (previous != '@') {
- nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) {
- tag = this.taskTags[itag];
- int tagLength = tag.length;
- if (tagLength == 0) continue nextTag;
- // ensure tag is not leaded with letter if tag starts with a letter
- if (ScannerHelper.isJavaIdentifierStart(this.complianceLevel, tag[0])) {
- if (ScannerHelper.isJavaIdentifierPart(this.complianceLevel, previous)) {
- continue nextTag;
- }
- }
-
- for (int t = 0; t < tagLength; t++) {
- char sc, tc;
- int x = i+t;
- if (x >= this.eofPosition || x >= commentEnd) continue nextTag;
- // case sensitive check
- if ((sc = src[i + t]) != (tc = tag[t])) {
- // case insensitive check
- if (this.isTaskCaseSensitive || (ScannerHelper.toLowerCase(sc) != ScannerHelper.toLowerCase(tc))) {
- continue nextTag;
- }
- }
- }
- // ensure tag is not followed with letter if tag finishes with a letter
- if (i+tagLength < commentEnd && ScannerHelper.isJavaIdentifierPart(this.complianceLevel, src[i+tagLength-1])) {
- if (ScannerHelper.isJavaIdentifierPart(this.complianceLevel, src[i + tagLength]))
- continue nextTag;
- }
- if (this.foundTaskTags == null) {
- this.foundTaskTags = new char[5][];
- this.foundTaskMessages = new char[5][];
- this.foundTaskPriorities = new char[5][];
- this.foundTaskPositions = new int[5][];
- } else if (this.foundTaskCount == this.foundTaskTags.length) {
- System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
- System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
- System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
- System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount);
- }
-
- priority = this.taskPriorities != null && itag < this.taskPriorities.length
- ? this.taskPriorities[itag]
- : null;
-
- this.foundTaskTags[this.foundTaskCount] = tag;
- this.foundTaskPriorities[this.foundTaskCount] = priority;
- this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 };
- this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
- this.foundTaskCount++;
- i += tagLength - 1; // will be incremented when looping
- break nextTag;
- }
- }
- previous = src[i];
- }
- boolean containsEmptyTask = false;
- for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
- // retrieve message start and end positions
- int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
- int max_value = i + 1 < this.foundTaskCount
- ? this.foundTaskPositions[i + 1][0] - 1
- : commentEnd - 1;
- // at most beginning of next task
- if (max_value < msgStart) {
- max_value = msgStart; // would only occur if tag is before EOF.
- }
- int end = -1;
- char c;
- for (int j = msgStart; j < max_value; j++) {
- if ((c = src[j]) == '\n' || c == '\r') {
- end = j - 1;
- break;
- }
- }
- if (end == -1) {
- for (int j = max_value; j > msgStart; j--) {
- if ((c = src[j]) == '*') {
- end = j - 1;
- break;
- }
- }
- if (end == -1)
- end = max_value;
- }
- if (msgStart == end) {
- // if the description is empty, we might want to see if two tags are not sharing the same message
- // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=110797
- containsEmptyTask = true;
- continue;
- }
- // trim the message
- // we don't trim the beginning of the message to be able to show it after the task tag
- while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
- end--;
- // update the end position of the task
- this.foundTaskPositions[i][1] = end;
- // get the message source
- final int messageLength = end - msgStart + 1;
- char[] message = new char[messageLength];
- System.arraycopy(src, msgStart, message, 0, messageLength);
- this.foundTaskMessages[i] = message;
- }
- if (containsEmptyTask) {
- for (int i = foundTaskIndex, max = this.foundTaskCount; i < max; i++) {
- if (this.foundTaskMessages[i].length == 0) {
- loop: for (int j = i + 1; j < max; j++) {
- if (this.foundTaskMessages[j].length != 0) {
- this.foundTaskMessages[i] = this.foundTaskMessages[j];
- this.foundTaskPositions[i][1] = this.foundTaskPositions[j][1];
- break loop;
- }
- }
- }
- }
+ /**
+ * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
+ * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
+ *
+ * @param begin the given start position
+ * @param end the given end position
+ */
+ @Override
+ public void resetTo(int begin, int end) {
+ this.delegate.resetTo(begin, end);
}
-}
-public char[] getCurrentIdentifierSource() {
- //return the token REAL source (aka unicodes are precomputed)
- if (this.withoutUnicodePtr != 0) {
- //0 is used as a fast test flag so the real first char is in position 1
- char[] result = new char[this.withoutUnicodePtr];
- System.arraycopy(
- this.withoutUnicodeBuffer,
- 1,
- result,
- 0,
- this.withoutUnicodePtr);
- return result;
+ /**
+ * Search the line number corresponding to a specific position
+ * @param position int
+ * @return int
+ */
+ @Override
+ public final int getLineNumber(int position) {
+ return this.delegate.getLineNumber(position);
}
- int length = this.currentPosition - this.startPosition;
- if (length == this.eofPosition) return this.source;
- return this.deduplication.sharedCopyOfRange(this.source, this.startPosition, this.currentPosition);
-}
-@Override
-public int getCurrentTokenEndPosition(){
- return this.currentPosition - 1;
-}
-@Override
-public char[] getCurrentTokenSource() {
- // Return the token REAL source (aka unicodes are precomputed)
-
- char[] result;
- if (this.withoutUnicodePtr != 0)
- // 0 is used as a fast test flag so the real first char is in position 1
- System.arraycopy(
- this.withoutUnicodeBuffer,
- 1,
- result = new char[this.withoutUnicodePtr],
- 0,
- this.withoutUnicodePtr);
- else {
- int length;
- System.arraycopy(
- this.source,
- this.startPosition,
- result = new char[length = this.currentPosition - this.startPosition],
- 0,
- length);
+ @Override
+ public final void setSource(char[] sourceString){
+ this.delegate.setSource(sourceString);
}
- return result;
-}
-public final String getCurrentTokenString() {
- // Return current token as a string
- if (this.withoutUnicodePtr != 0) {
- // 0 is used as a fast test flag so the real first char is in position 1
- return new String(
- this.withoutUnicodeBuffer,
- 1,
- this.withoutUnicodePtr);
- }
- return new String(
- this.source,
- this.startPosition,
- this.currentPosition - this.startPosition);
-}
-public char[] getCurrentTokenSourceString() {
- //return the token REAL source (aka unicodes are precomputed).
- //REMOVE the two " that are at the beginning and the end.
-
- char[] result;
- if (this.withoutUnicodePtr != 0)
- //0 is used as a fast test flag so the real first char is in position 1
- System.arraycopy(this.withoutUnicodeBuffer, 2,
- //2 is 1 (real start) + 1 (to jump over the ")
- result = new char[this.withoutUnicodePtr - 2], 0, this.withoutUnicodePtr - 2);
- else {
- int length;
- System.arraycopy(
- this.source,
- this.startPosition + 1,
- result = new char[length = this.currentPosition - this.startPosition - 2],
- 0,
- length);
- }
- return result;
-}
-protected final boolean scanForTextBlockBeginning() {
- if (this.complianceLevel < ClassFileConstants.JDK13 || !this.previewEnabled) {
- return false;
- }
- try {
- // Don't change the position and current character unless we are certain
- // to be dealing with a text block. For producing all errors like before
- // in case of a valid """ but missing \r or \n, just return false and not
- // throw any error.
- int temp = this.currentPosition;
- if ((this.source[temp++] == '\"' && this.source[temp++] == '\"')) {
- char c = this.source[temp++];
- while (ScannerHelper.isWhitespace(c)) {
- switch (c) {
- case 10 : /* \ u000a: LINE FEED */
- case 13 : /* \ u000d: CARRIAGE RETURN */
- this.currentCharacter = c;
- this.currentPosition = temp;
- return true;
- default:
- break;
- }
- c = this.source[temp++];
- }
- }
- } catch(IndexOutOfBoundsException e) {
- //let it return false;
- }
- return false;
-}
-protected final boolean scanForTextBlockClose() throws InvalidInputException {
- try {
- if (this.source[this.currentPosition] == '\"' && this.source[this.currentPosition + 1] == '\"') {
- return true;
- }
- } catch(IndexOutOfBoundsException e) {
- //let it return false;
- }
- return false;
-}
-public final String getCurrentStringLiteral() {
- //return the token REAL source (aka unicodes are precomputed).
- //REMOVE the two " that are at the beginning and the end.
-
- if (this.withoutUnicodePtr != 0)
- //0 is used as a fast test flag so the real first char is in position 1
- //2 is 1 (real start) + 1 (to jump over the ")
- return new String(this.withoutUnicodeBuffer, 2, this.withoutUnicodePtr - 2);
- else {
- return new String(this.source, this.startPosition + 1, this.currentPosition - this.startPosition - 2);
- }
-}
-@Override
-public final char[] getRawTokenSource() {
- int length = this.currentPosition - this.startPosition;
- char[] tokenSource = new char[length];
- System.arraycopy(this.source, this.startPosition, tokenSource, 0, length);
- return tokenSource;
-}
-
-public final char[] getRawTokenSourceEnd() {
- int length = this.eofPosition - this.currentPosition - 1;
- char[] sourceEnd = new char[length];
- System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length);
- return sourceEnd;
-}
-
-@Override
-public int getCurrentTokenStartPosition(){
- return this.startPosition;
-}
-/*
- * Search the source position corresponding to the end of a given line number
- *
- * Line numbers are 1-based, and relative to the scanner initialPosition.
- * Character positions are 0-based.
- *
- * In case the given line number is inconsistent, answers -1.
- */
-@Override
-public final int getLineEnd(int lineNumber) {
-
- if (this.lineEnds == null || this.linePtr == -1)
- return -1;
- if (lineNumber > this.lineEnds.length+1)
- return -1;
- if (lineNumber <= 0)
- return -1;
- if (lineNumber == this.lineEnds.length + 1)
- return this.eofPosition;
- return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
-}
-
-@Override
-public final int[] getLineEnds() {
- //return a bounded copy of this.lineEnds
- if (this.linePtr == -1) {
- return EMPTY_LINE_ENDS;
- }
- int[] copy;
- System.arraycopy(this.lineEnds, 0, copy = new int[this.linePtr + 1], 0, this.linePtr + 1);
- return copy;
-}
-
-/**
- * Search the source position corresponding to the beginning of a given line number
- *
- * Line numbers are 1-based, and relative to the scanner initialPosition.
- * Character positions are 0-based.
- *
- * e.g. getLineStart(1) --> 0 indicates that the first line starts at character 0.
- *
- * In case the given line number is inconsistent, answers -1.
- *
- * @param lineNumber int
- * @return int
- */
-@Override
-public final int getLineStart(int lineNumber) {
-
- if (this.lineEnds == null || this.linePtr == -1)
- return -1;
- if (lineNumber > this.lineEnds.length + 1)
- return -1;
- if (lineNumber <= 0)
- return -1;
-
- if (lineNumber == 1)
- return this.initialPosition;
- return this.lineEnds[lineNumber-2]+1; // next line start one character behind the lineEnd of the previous line
-}
-public final int getNextChar() {
- try {
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- this.unicodeAsBackSlash = false;
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- return this.currentCharacter;
- } catch(IndexOutOfBoundsException | InvalidInputException e) {
- return -1;
- }
-}
-public final int getNextCharWithBoundChecks() {
- if (this.currentPosition >= this.eofPosition) {
- return -1;
- }
- this.currentCharacter = this.source[this.currentPosition++];
- if (this.currentPosition >= this.eofPosition) {
- this.unicodeAsBackSlash = false;
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- return this.currentCharacter;
- }
- if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') {
- try {
- getNextUnicodeChar();
- } catch (InvalidInputException e) {
- return -1;
- }
- } else {
- this.unicodeAsBackSlash = false;
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- return this.currentCharacter;
-}
-public final boolean getNextChar(char testedChar) {
- //BOOLEAN
- //handle the case of unicode.
- //when a unicode appears then we must use a buffer that holds char internal values
- //At the end of this method currentCharacter holds the new visited char
- //and currentPosition points right next after it
- //Both previous lines are true if the currentCharacter is == to the testedChar
- //On false, no side effect has occured.
-
- //ALL getNextChar.... ARE OPTIMIZED COPIES
-
- if (this.currentPosition >= this.eofPosition) { // handle the obvious case upfront
- this.unicodeAsBackSlash = false;
- return false;
- }
-
- int temp = this.currentPosition;
- try {
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- if (this.currentCharacter != testedChar) {
- this.currentPosition = temp;
- this.withoutUnicodePtr--;
- return false;
- }
- return true;
- } //-------------end unicode traitement--------------
- else {
- if (this.currentCharacter != testedChar) {
- this.currentPosition = temp;
- return false;
- }
- this.unicodeAsBackSlash = false;
- if (this.withoutUnicodePtr != 0)
- unicodeStore();
- return true;
- }
- } catch(IndexOutOfBoundsException | InvalidInputException e) {
- this.unicodeAsBackSlash = false;
- this.currentPosition = temp;
- return false;
- }
-}
-public final int getNextChar(char testedChar1, char testedChar2) {
- //INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others
- //test can be done with (x==0) for the first and (x>0) for the second
- //handle the case of unicode.
- //when a unicode appears then we must use a buffer that holds char internal values
- //At the end of this method currentCharacter holds the new visited char
- //and currentPosition points right next after it
- //Both previous lines are true if the currentCharacter is == to the testedChar1/2
- //On false, no side effect has occured.
-
- //ALL getNextChar.... ARE OPTIMIZED COPIES
- if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
- return -1;
-
- int temp = this.currentPosition;
- try {
- int result;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- if (this.currentCharacter == testedChar1) {
- result = 0;
- } else if (this.currentCharacter == testedChar2) {
- result = 1;
- } else {
- this.currentPosition = temp;
- this.withoutUnicodePtr--;
- result = -1;
- }
- return result;
- } else {
- if (this.currentCharacter == testedChar1) {
- result = 0;
- } else if (this.currentCharacter == testedChar2) {
- result = 1;
- } else {
- this.currentPosition = temp;
- return -1;
- }
-
- if (this.withoutUnicodePtr != 0)
- unicodeStore();
- return result;
- }
- } catch(IndexOutOfBoundsException | InvalidInputException e) {
- this.currentPosition = temp;
- return -1;
- }
-}
-/*
- * This method consumes digits as well as underscores if underscores are located between digits
- * @throws InvalidInputException if underscores are not located between digits or if underscores are used in source < 1.7
- */
-private final void consumeDigits(int radix) throws InvalidInputException {
- consumeDigits(radix, false);
-}
-/*
- * This method consumes digits as well as underscores if underscores are located between digits
- * @throws InvalidInputException if underscores are not located between digits or if underscores are used in source < 1.7
- */
-private final void consumeDigits(int radix, boolean expectingDigitFirst) throws InvalidInputException {
- final int USING_UNDERSCORE = 1;
- final int INVALID_POSITION = 2;
- switch(consumeDigits0(radix, USING_UNDERSCORE, INVALID_POSITION, expectingDigitFirst)) {
- case USING_UNDERSCORE :
- if (this.sourceLevel < ClassFileConstants.JDK1_7) {
- throw new InvalidInputException(UNDERSCORES_IN_LITERALS_NOT_BELOW_17);
- }
- break;
- case INVALID_POSITION :
- if (this.sourceLevel < ClassFileConstants.JDK1_7) {
- throw new InvalidInputException(UNDERSCORES_IN_LITERALS_NOT_BELOW_17);
- }
- throw new InvalidInputException(INVALID_UNDERSCORE);
- }
-}
-private final int consumeDigits0(int radix, int usingUnderscore, int invalidPosition, boolean expectingDigitFirst) throws InvalidInputException {
- int kind = 0;
- if (getNextChar('_')) {
- if (expectingDigitFirst) {
- return invalidPosition;
- }
- kind = usingUnderscore;
- while (getNextChar('_')) {/*empty */}
- }
- if (getNextCharAsDigit(radix)) {
- // continue to read digits or underscore
- while (getNextCharAsDigit(radix)) {/*empty */}
- int kind2 = consumeDigits0(radix, usingUnderscore, invalidPosition, false);
- if (kind2 == 0) {
- return kind;
- }
- return kind2;
- }
- if (kind == usingUnderscore) return invalidPosition;
- return kind;
-}
-public final boolean getNextCharAsDigit() throws InvalidInputException {
- //BOOLEAN
- //handle the case of unicode.
- //when a unicode appears then we must use a buffer that holds char internal values
- //At the end of this method currentCharacter holds the new visited char
- //and currentPosition points right next after it
- //Both previous lines are true if the currentCharacter is a digit
- //On false, no side effect has occured.
-
- //ALL getNextChar.... ARE OPTIMIZED COPIES
- if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
- return false;
-
- int temp = this.currentPosition;
- try {
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- if (!ScannerHelper.isDigit(this.currentCharacter)) {
- this.currentPosition = temp;
- this.withoutUnicodePtr--;
- return false;
- }
- return true;
- } else {
- if (!ScannerHelper.isDigit(this.currentCharacter)) {
- this.currentPosition = temp;
- return false;
- }
- if (this.withoutUnicodePtr != 0)
- unicodeStore();
- return true;
- }
- } catch(IndexOutOfBoundsException | InvalidInputException e) {
- this.currentPosition = temp;
- return false;
- }
-}
-public final boolean getNextCharAsDigit(int radix) {
- //BOOLEAN
- //handle the case of unicode.
- //when a unicode appears then we must use a buffer that holds char internal values
- //At the end of this method currentCharacter holds the new visited char
- //and currentPosition points right next after it
- //Both previous lines are true if the currentCharacter is a digit base on radix
- //On false, no side effect has occured.
-
- //ALL getNextChar.... ARE OPTIMIZED COPIES
- if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
- return false;
-
- int temp = this.currentPosition;
- try {
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- if (ScannerHelper.digit(this.currentCharacter, radix) == -1) {
- this.currentPosition = temp;
- this.withoutUnicodePtr--;
- return false;
- }
- return true;
- } else {
- if (ScannerHelper.digit(this.currentCharacter, radix) == -1) {
- this.currentPosition = temp;
- return false;
- }
- if (this.withoutUnicodePtr != 0)
- unicodeStore();
- return true;
- }
- } catch(IndexOutOfBoundsException | InvalidInputException e) {
- this.currentPosition = temp;
- return false;
- }
-}
-public boolean getNextCharAsJavaIdentifierPartWithBoundCheck() {
- //BOOLEAN
- //handle the case of unicode.
- //when a unicode appears then we must use a buffer that holds char internal values
- //At the end of this method currentCharacter holds the new visited char
- //and currentPosition points right next after it
- //Both previous lines are true if the currentCharacter is a JavaIdentifierPart
- //On false, no side effect has occured.
-
- //ALL getNextChar.... ARE OPTIMIZED COPIES
- int pos = this.currentPosition;
- if (pos >= this.eofPosition) // handle the obvious case upfront
- return false;
-
- int temp2 = this.withoutUnicodePtr;
- try {
- boolean unicode = false;
- this.currentCharacter = this.source[this.currentPosition++];
- if (this.currentPosition < this.eofPosition) {
- if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') {
- getNextUnicodeChar();
- unicode = true;
- }
- }
- char c = this.currentCharacter;
- boolean isJavaIdentifierPart = false;
- if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
- // Unicode 4 detection
- char low = (char) getNextCharWithBoundChecks();
- if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
- // illegal low surrogate
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
- isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c, low);
- }
- else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- } else {
- isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c);
- }
- if (unicode) {
- if (!isJavaIdentifierPart) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
- return true;
- } else {
- if (!isJavaIdentifierPart) {
- this.currentPosition = pos;
- return false;
- }
-
- if (this.withoutUnicodePtr != 0)
- unicodeStore();
- return true;
- }
- } catch(InvalidInputException e) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
-}
-public boolean getNextCharAsJavaIdentifierPart() {
- //BOOLEAN
- //handle the case of unicode.
- //when a unicode appears then we must use a buffer that holds char internal values
- //At the end of this method currentCharacter holds the new visited char
- //and currentPosition points right next after it
- //Both previous lines are true if the currentCharacter is a JavaIdentifierPart
- //On false, no side effect has occured.
-
- //ALL getNextChar.... ARE OPTIMIZED COPIES
- int pos;
- if ((pos = this.currentPosition) >= this.eofPosition) // handle the obvious case upfront
- return false;
-
- int temp2 = this.withoutUnicodePtr;
- try {
- boolean unicode = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- unicode = true;
- }
- char c = this.currentCharacter;
- boolean isJavaIdentifierPart = false;
- if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
- // Unicode 4 detection
- char low = (char) getNextChar();
- if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
- // illegal low surrogate
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
- isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c, low);
- }
- else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- } else {
- isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(this.complianceLevel, c);
- }
- if (unicode) {
- if (!isJavaIdentifierPart) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
- return true;
- } else {
- if (!isJavaIdentifierPart) {
- this.currentPosition = pos;
- return false;
- }
-
- if (this.withoutUnicodePtr != 0)
- unicodeStore();
- return true;
- }
- } catch(IndexOutOfBoundsException | InvalidInputException e) {
- this.currentPosition = pos;
- this.withoutUnicodePtr = temp2;
- return false;
- }
-}
-/*
- * External API in JavaConventions.
- * This is used to optimize the case where the scanner is used to scan a single identifier.
- * In this case, the AIOOBE is slower to handle than a bound check
- */
-public int scanIdentifier() throws InvalidInputException {
- int whiteStart = 0;
- while (true) { //loop for jumping over comments
- this.withoutUnicodePtr = 0;
- //start with a new token (even comment written with unicode )
- // ---------Consume white space and handles startPosition---------
- whiteStart = this.currentPosition;
- boolean isWhiteSpace, hasWhiteSpaces = false;
- int offset;
- int unicodePtr;
- boolean checkIfUnicode = false;
- do {
- unicodePtr = this.withoutUnicodePtr;
- offset = this.currentPosition;
- this.startPosition = this.currentPosition;
- if (this.currentPosition < this.eofPosition) {
- this.currentCharacter = this.source[this.currentPosition++];
- checkIfUnicode = this.currentPosition < this.eofPosition
- && this.currentCharacter == '\\'
- && this.source[this.currentPosition] == 'u';
- } else if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
- // reposition scanner in case we are interested by spaces as tokens
- this.currentPosition--;
- this.startPosition = whiteStart;
- return TokenNameWHITESPACE;
- } else {
- return TokenNameEOF;
- }
- if (checkIfUnicode) {
- isWhiteSpace = jumpOverUnicodeWhiteSpace();
- offset = this.currentPosition - offset;
- } else {
- offset = this.currentPosition - offset;
- // inline version of:
- //isWhiteSpace =
- // (this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter);
- switch (this.currentCharacter) {
- case 10 : /* \ u000a: LINE FEED */
- case 12 : /* \ u000c: FORM FEED */
- case 13 : /* \ u000d: CARRIAGE RETURN */
- case 32 : /* \ u0020: SPACE */
- case 9 : /* \ u0009: HORIZONTAL TABULATION */
- isWhiteSpace = true;
- break;
- default :
- isWhiteSpace = false;
- }
- }
- if (isWhiteSpace) {
- hasWhiteSpaces = true;
- }
- } while (isWhiteSpace);
- if (hasWhiteSpaces) {
- if (this.tokenizeWhiteSpace) {
- // reposition scanner in case we are interested by spaces as tokens
- this.currentPosition-=offset;
- this.startPosition = whiteStart;
- if (checkIfUnicode) {
- this.withoutUnicodePtr = unicodePtr;
- }
- return TokenNameWHITESPACE;
- } else if (checkIfUnicode) {
- this.withoutUnicodePtr = 0;
- unicodeStore();
- } else {
- this.withoutUnicodePtr = 0;
- }
- }
- char c = this.currentCharacter;
- if (c < ScannerHelper.MAX_OBVIOUS) {
- if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
- return scanIdentifierOrKeywordWithBoundCheck();
- }
- return TokenNameERROR;
- }
- boolean isJavaIdStart;
- if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- // Unicode 4 detection
- char low = (char) getNextCharWithBoundChecks();
- if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
- // illegal low surrogate
- throw new InvalidInputException(INVALID_LOW_SURROGATE);
- }
- isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low);
- } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- throw new InvalidInputException(INVALID_HIGH_SURROGATE);
- } else {
- // optimized case already checked
- isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c);
- }
- if (isJavaIdStart)
- return scanIdentifierOrKeywordWithBoundCheck();
- return TokenNameERROR;
- }
-}
-@Override
-public int getNextToken() throws InvalidInputException {
-//{ObjectTeams: support '.' 'team':
- if (this._dotSeen > 0)
- this._dotSeen--; // "aging"
-// SH}
- this.wasAcr = false;
- if (this.diet) {
- jumpOverMethodBody();
- this.diet = false;
- return this.currentPosition > this.eofPosition ? TokenNameEOF : TokenNameRBRACE;
- }
- int whiteStart = 0;
- try {
- while (true) { //loop for jumping over comments
- this.withoutUnicodePtr = 0;
- //start with a new token (even comment written with unicode )
-
- // ---------Consume white space and handles startPosition---------
- whiteStart = this.currentPosition;
- boolean isWhiteSpace, hasWhiteSpaces = false;
- int offset;
- int unicodePtr;
- boolean checkIfUnicode = false;
- do {
- unicodePtr = this.withoutUnicodePtr;
- offset = this.currentPosition;
- this.startPosition = this.currentPosition;
- boolean repositionNeeded = false;
- if(this.currentPosition < this.source.length){
- this.currentCharacter = this.source[this.currentPosition];
- this.currentPosition++;
- if(this.currentCharacter == '\\') {
- if (this.currentPosition < this.source.length) {
- checkIfUnicode = this.source[this.currentPosition] == 'u';
- } else {
- repositionNeeded = true;
- }
- } else {
- checkIfUnicode = false;
- }
- } else {
- this.currentPosition++;
- repositionNeeded = true;
- }
- if(repositionNeeded){
- if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
- // reposition scanner in case we are interested by spaces as tokens
- this.currentPosition--;
- this.startPosition = whiteStart;
- return TokenNameWHITESPACE;
- }
- if (this.currentPosition > this.eofPosition)
- return TokenNameEOF;
- }
- if (this.currentPosition > this.eofPosition) {
- if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
- this.currentPosition--;
- // reposition scanner in case we are interested by spaces as tokens
- this.startPosition = whiteStart;
- return TokenNameWHITESPACE;
- }
- return TokenNameEOF;
- }
- if (checkIfUnicode) {
- isWhiteSpace = jumpOverUnicodeWhiteSpace();
- offset = this.currentPosition - offset;
- } else {
- offset = this.currentPosition - offset;
- if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- if (this.recordLineSeparator) {
- pushLineSeparator();
- }
- }
- // inline version of:
- //isWhiteSpace =
- // (this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter);
- switch (this.currentCharacter) {
- case 10 : /* \ u000a: LINE FEED */
- case 12 : /* \ u000c: FORM FEED */
- case 13 : /* \ u000d: CARRIAGE RETURN */
- case 32 : /* \ u0020: SPACE */
- case 9 : /* \ u0009: HORIZONTAL TABULATION */
- isWhiteSpace = true;
- break;
- default :
- isWhiteSpace = false;
- }
- }
- if (isWhiteSpace) {
- hasWhiteSpaces = true;
- }
- } while (isWhiteSpace);
- if (hasWhiteSpaces) {
- if (this.tokenizeWhiteSpace) {
- // reposition scanner in case we are interested by spaces as tokens
- this.currentPosition-=offset;
- this.startPosition = whiteStart;
- if (checkIfUnicode) {
- this.withoutUnicodePtr = unicodePtr;
- }
- return TokenNameWHITESPACE;
- } else if (checkIfUnicode) {
- this.withoutUnicodePtr = 0;
- unicodeStore();
- } else {
- this.withoutUnicodePtr = 0;
- }
- }
- // ---------Identify the next token-------------
- switch (this.currentCharacter) {
- case '@' :
-/* if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
- return TokenNameAT;
- } else {
- return TokenNameERROR;
- }*/
- return TokenNameAT;
- case '(' :
- return TokenNameLPAREN;
- case ')' :
- return TokenNameRPAREN;
- case '{' :
- return TokenNameLBRACE;
- case '}' :
- return TokenNameRBRACE;
- case '[' :
- return TokenNameLBRACKET;
- case ']' :
- return TokenNameRBRACKET;
- case ';' :
- return TokenNameSEMICOLON;
- case ',' :
- return TokenNameCOMMA;
- case '.' :
- if (getNextCharAsDigit()) {
- return scanNumber(true);
- }
- int temp = this.currentPosition;
- if (getNextChar('.')) {
- if (getNextChar('.')) {
- return TokenNameELLIPSIS;
- } else {
- this.currentPosition = temp;
- return TokenNameDOT;
- }
- } else {
-//{ObjectTeams: record the one '.':
- this._dotSeen = 2; // now
-// SH}
- this.currentPosition = temp;
- return TokenNameDOT;
- }
- case '+' :
- {
- int test;
- if ((test = getNextChar('+', '=')) == 0)
- return TokenNamePLUS_PLUS;
- if (test > 0)
- return TokenNamePLUS_EQUAL;
- return TokenNamePLUS;
- }
- case '-' :
- {
- int test;
- if ((test = getNextChar('-', '=')) == 0)
- return TokenNameMINUS_MINUS;
- if (test > 0)
- return TokenNameMINUS_EQUAL;
-// FIXME:
- if (getNextChar('>'))
- return TokenNameARROW;
-//{ObjectTeams: check for callout binding after '-' tokens
- else {
- if (test < 0 && this._isOTSource)
- if (getNextChar('>')) {
- this._calloutSeen = true;
- return TokenNameBINDOUT;
- }
- }
-// Markus Witte}
- return TokenNameMINUS;
- }
- case '~' :
- return TokenNameTWIDDLE;
- case '!' :
- if (getNextChar('='))
- return TokenNameNOT_EQUAL;
- return TokenNameNOT;
- case '*' :
- if (getNextChar('='))
- return TokenNameMULTIPLY_EQUAL;
- return TokenNameMULTIPLY;
- case '%' :
- if (getNextChar('='))
- return TokenNameREMAINDER_EQUAL;
- return TokenNameREMAINDER;
- case '<' :
- {
- int test;
- if ((test = getNextChar('=', '<')) == 0)
- return TokenNameLESS_EQUAL;
- if (test > 0) {
- if (getNextChar('='))
- return TokenNameLEFT_SHIFT_EQUAL;
- return TokenNameLEFT_SHIFT;
- }
-//{ObjectTeams: check for callin binding after '<' tokens
- else {
- if (test < 0 && this._isOTSource)
- if (getNextChar('-')) {
- this._callinSeen = true;
- return TokenNameBINDIN;
- }
- }
-// Markus Witte}
- return TokenNameLESS;
- }
- case '>' :
- {
- int test;
- if (this.returnOnlyGreater) {
- return TokenNameGREATER;
- }
- if ((test = getNextChar('=', '>')) == 0)
- return TokenNameGREATER_EQUAL;
- if (test > 0) {
- if ((test = getNextChar('=', '>')) == 0)
- return TokenNameRIGHT_SHIFT_EQUAL;
- if (test > 0) {
- if (getNextChar('='))
- return TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
- return TokenNameUNSIGNED_RIGHT_SHIFT;
- }
- return TokenNameRIGHT_SHIFT;
- }
- return TokenNameGREATER;
- }
- case '=' :
-//{ObjectTeams: check for callout override after '=' tokens
- /* @original
- if (getNextChar('='))
- return TokenNameEQUAL_EQUAL;
- return TokenNameEQUAL;
- */
- {
- int test;
- if ((test = getNextChar('=', '>')) == 0)
- return TokenNameEQUAL_EQUAL;
- if (test > 0) {
- this._calloutSeen = true;
- return TokenNameCALLOUT_OVERRIDE;
- } else {
- return TokenNameEQUAL;
- }
- }
-// Markus Witte}
- case '&' :
- {
- int test;
- if ((test = getNextChar('&', '=')) == 0)
- return TokenNameAND_AND;
- if (test > 0)
- return TokenNameAND_EQUAL;
- return TokenNameAND;
- }
- case '|' :
- {
- int test;
- if ((test = getNextChar('|', '=')) == 0)
- return TokenNameOR_OR;
- if (test > 0)
- return TokenNameOR_EQUAL;
- return TokenNameOR;
- }
- case '^' :
- if (getNextChar('='))
- return TokenNameXOR_EQUAL;
- return TokenNameXOR;
- case '?' :
- return TokenNameQUESTION;
- case ':' :
- if (getNextChar(':'))
- return TokenNameCOLON_COLON;
- return TokenNameCOLON;
- case '\'' :
- {
- int test;
- if ((test = getNextChar('\n', '\r')) == 0) {
- throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
- }
- if (test > 0) {
- // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
- for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
- if (this.currentPosition + lookAhead == this.eofPosition)
- break;
- if (this.source[this.currentPosition + lookAhead] == '\n')
- break;
- if (this.source[this.currentPosition + lookAhead] == '\'') {
- this.currentPosition += lookAhead + 1;
- break;
- }
- }
- throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
- }
- }
- if (getNextChar('\'')) {
- // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
- for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
- if (this.currentPosition + lookAhead == this.eofPosition)
- break;
- if (this.source[this.currentPosition + lookAhead] == '\n')
- break;
- if (this.source[this.currentPosition + lookAhead] == '\'') {
- this.currentPosition += lookAhead + 1;
- break;
- }
- }
- throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
- }
- if (getNextChar('\\')) {
- if (this.unicodeAsBackSlash) {
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- } else {
- this.currentCharacter = this.source[this.currentPosition++];
- }
- scanEscapeCharacter();
- } else { // consume next character
- this.unicodeAsBackSlash = false;
- checkIfUnicode = false;
- try {
- checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u');
- } catch(IndexOutOfBoundsException e) {
- this.currentPosition--;
- throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
- }
- if (checkIfUnicode) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- if (getNextChar('\''))
- return TokenNameCharacterLiteral;
- // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
- for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
- if (this.currentPosition + lookAhead == this.eofPosition)
- break;
- if (this.source[this.currentPosition + lookAhead] == '\n')
- break;
- if (this.source[this.currentPosition + lookAhead] == '\'') {
- this.currentPosition += lookAhead + 1;
- break;
- }
- }
- throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
- case '"' :
- boolean isTextBlock = false;
- int lastQuotePos = 0;
- try {
- // consume next character
- this.unicodeAsBackSlash = false;
- boolean isUnicode = false;
- isTextBlock = scanForTextBlockBeginning();
- if (!isTextBlock) {
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- this.rawStart = this.currentPosition - this.startPosition;
- int terminators = 0;
- while (this.currentPosition <= this.eofPosition) {
- if (this.currentCharacter == '"') {
- if (!isTextBlock) {
- return ITerminalSymbols.TokenNameStringLiteral;
- }
- lastQuotePos = this.currentPosition;
- // look for text block delimiter
- if (scanForTextBlockClose()) {
- // Account for just the snippet being passed around
- // If already at the EOF, bail out.
- if (this.currentPosition + 2 < this.source.length && this.source[this.currentPosition + 2] == '"') {
- terminators++;
- if (terminators > 2)
- throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
- } else {
- this.currentPosition += 2;
- return ITerminalSymbols.TokenNameTextBlock;
- }
- }
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- } else {
- terminators = 0;
- }
- /**** \r and \n are not valid in string literals ****/
- if (!isTextBlock && (this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
- // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
- if (isUnicode) {
- int start = this.currentPosition;
- for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
- if (this.currentPosition >= this.eofPosition) {
- this.currentPosition = start;
- break;
- }
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
- isUnicode = true;
- getNextUnicodeChar();
- } else {
- isUnicode = false;
- }
- if (!isUnicode && this.currentCharacter == '\n') {
- this.currentPosition--; // set current position on new line character
- break;
- }
- if (this.currentCharacter == '\"') {
- throw new InvalidInputException(INVALID_CHAR_IN_STRING);
- }
- }
- } else {
- this.currentPosition--; // set current position on new line character
- }
- throw new InvalidInputException(INVALID_CHAR_IN_STRING);
- }
- if (this.currentCharacter == '\\') {
- if (this.unicodeAsBackSlash) {
- this.withoutUnicodePtr--;
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- this.withoutUnicodePtr--;
- } else {
- isUnicode = false;
- }
- } else {
- if (this.withoutUnicodePtr == 0) {
- unicodeInitializeBuffer(this.currentPosition - this.startPosition);
- }
- this.withoutUnicodePtr --;
- this.currentCharacter = this.source[this.currentPosition++];
- }
- // we need to compute the escape character in a separate buffer
- scanEscapeCharacter();
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- // consume next character
- if (this.currentPosition >= this.eofPosition) {
- break;
- }
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- isUnicode = false;
- if (isTextBlock && this.currentCharacter == '"')
- continue;
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- if (isTextBlock) {
- if (lastQuotePos > 0)
- this.currentPosition = lastQuotePos;
- this.currentPosition = (lastQuotePos > 0) ? lastQuotePos : this.startPosition + this.rawStart;
- throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
- } else {
- throw new InvalidInputException(UNTERMINATED_STRING);
- }
- } catch (IndexOutOfBoundsException e) {
- if (isTextBlock) {
- this.currentPosition = (lastQuotePos > 0) ? lastQuotePos : this.startPosition + this.rawStart;
- throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
- } else {
- this.currentPosition--;
- throw new InvalidInputException(UNTERMINATED_STRING);
- }
- } catch (InvalidInputException e) {
- if (e.getMessage().equals(INVALID_ESCAPE)) {
- // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
- for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
- if (this.currentPosition + lookAhead == this.eofPosition)
- break;
- if (this.source[this.currentPosition + lookAhead] == '\n')
- break;
- if (this.source[this.currentPosition + lookAhead] == '\"') {
- this.currentPosition += lookAhead + 1;
- break;
- }
- }
-
- }
- throw e; // rethrow
- }
- case '/' :
- if (!this.skipComments) {
- int test = getNextChar('/', '*');
- if (test == 0) { //line comment
- this.lastCommentLinePosition = this.currentPosition;
- try { //get the next char
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- }
-
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++;
- } //jump over the \\
- boolean isUnicode = false;
- while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
- if (this.currentPosition >= this.eofPosition) {
- this.lastCommentLinePosition = this.currentPosition;
- this.currentPosition ++;
- // this avoids duplicating the code in the catch(IndexOutOfBoundsException e)
- throw new IndexOutOfBoundsException();
- }
- this.lastCommentLinePosition = this.currentPosition;
- //get the next char
- isUnicode = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- }
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++;
- } //jump over the \\
- }
- /*
- * We need to completely consume the line break
- */
- if (this.currentCharacter == '\r'
- && this.eofPosition > this.currentPosition) {
- if (this.source[this.currentPosition] == '\n') {
- this.currentPosition++;
- this.currentCharacter = '\n';
- } else if ((this.source[this.currentPosition] == '\\')
- && (this.source[this.currentPosition + 1] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- }
- }
- recordComment(TokenNameCOMMENT_LINE);
- if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
- if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- if (this.checkNonExternalizedStringLiterals &&
- this.lastPosition < this.currentPosition) {
- parseTags();
- }
- if (this.recordLineSeparator) {
- if (isUnicode) {
- pushUnicodeLineSeparator();
- } else {
- pushLineSeparator();
- }
- }
- }
- if (this.tokenizeComments) {
- return TokenNameCOMMENT_LINE;
- }
- } catch (IndexOutOfBoundsException e) {
- this.currentPosition--;
- recordComment(TokenNameCOMMENT_LINE);
- if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
- if (this.checkNonExternalizedStringLiterals &&
- this.lastPosition < this.currentPosition) {
- parseTags();
- }
- if (this.tokenizeComments) {
- return TokenNameCOMMENT_LINE;
- } else {
- this.currentPosition++;
- }
- }
- break;
- }
- if (test > 0) { //traditional and javadoc comment
- try { //get the next char
- boolean isJavadoc = false, star = false;
- boolean isUnicode = false;
- int previous;
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- isUnicode = false;
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
-
- if (this.currentCharacter == '*') {
- isJavadoc = true;
- star = true;
- }
- if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- if (this.recordLineSeparator) {
- if (isUnicode) {
- pushUnicodeLineSeparator();
- } else {
- pushLineSeparator();
- }
- }
- }
- isUnicode = false;
- previous = this.currentPosition;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- //-------------unicode traitement ------------
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- isUnicode = false;
- }
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++; //jump over the \\
- }
- // empty comment is not a javadoc /**/
- if (this.currentCharacter == '/') {
- isJavadoc = false;
- }
- //loop until end of comment */
- int firstTag = 0;
- while ((this.currentCharacter != '/') || (!star)) {
- if (this.currentPosition >= this.eofPosition) {
- throw new InvalidInputException(UNTERMINATED_COMMENT);
- }
- if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- if (this.recordLineSeparator) {
- if (isUnicode) {
- pushUnicodeLineSeparator();
- } else {
- pushLineSeparator();
- }
- }
- }
- switch (this.currentCharacter) {
- case '*':
- star = true;
- break;
- case '@':
- if (firstTag == 0 && this.isFirstTag()) {
- firstTag = previous;
- }
- //$FALL-THROUGH$ default case to set star to false
- default:
- star = false;
- }
- //get next char
- previous = this.currentPosition;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- //-------------unicode traitement ------------
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- isUnicode = false;
- }
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++;
- } //jump over the \\
- }
- int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK;
- recordComment(token);
- this.commentTagStarts[this.commentPtr] = firstTag;
- if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
- if (this.tokenizeComments) {
- /*
- if (isJavadoc)
- return TokenNameCOMMENT_JAVADOC;
- return TokenNameCOMMENT_BLOCK;
- */
- return token;
- }
- } catch (IndexOutOfBoundsException e) {
- this.currentPosition--;
- throw new InvalidInputException(UNTERMINATED_COMMENT);
- }
- break;
- }
- }
- if (getNextChar('='))
- return TokenNameDIVIDE_EQUAL;
- return TokenNameDIVIDE;
- case '\u001a' :
- if (atEnd())
- return TokenNameEOF;
- //the atEnd may not be <currentPosition == source.length> if source is only some part of a real (external) stream
- throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
- default :
- char c = this.currentCharacter;
- if (c < ScannerHelper.MAX_OBVIOUS) {
- if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
- return scanIdentifierOrKeyword();
- } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
- return scanNumber(false);
- } else {
- return TokenNameERROR;
- }
- }
- boolean isJavaIdStart;
- if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- // Unicode 4 detection
- char low = (char) getNextChar();
- if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
- // illegal low surrogate
- throw new InvalidInputException(INVALID_LOW_SURROGATE);
- }
- isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low);
- }
- else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- throw new InvalidInputException(INVALID_HIGH_SURROGATE);
- } else {
- // optimized case already checked
- isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c);
- }
- if (isJavaIdStart)
- return scanIdentifierOrKeyword();
- if (ScannerHelper.isDigit(this.currentCharacter)) {
- return scanNumber(false);
- }
- return TokenNameERROR;
- }
- }
- } //-----------------end switch while try--------------------
- catch (IndexOutOfBoundsException e) {
- if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
- // reposition scanner in case we are interested by spaces as tokens
- this.currentPosition--;
- this.startPosition = whiteStart;
- return TokenNameWHITESPACE;
- }
- }
- return TokenNameEOF;
-}
-public void getNextUnicodeChar()
- throws InvalidInputException {
- //VOID
- //handle the case of unicode.
- //when a unicode appears then we must use a buffer that holds char internal values
- //At the end of this method currentCharacter holds the new visited char
- //and currentPosition points right next after it
-
- //ALL getNextChar.... ARE OPTIMIZED COPIES
- int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
- this.currentPosition++;
- if (this.currentPosition < this.eofPosition) {
- while (this.source[this.currentPosition] == 'u') {
- this.currentPosition++;
- if (this.currentPosition >= this.eofPosition) {
- this.currentPosition--;
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- unicodeSize++;
- }
- } else {
- this.currentPosition--;
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
-
- if ((this.currentPosition + 4) > this.eofPosition) {
- this.currentPosition += (this.eofPosition - this.currentPosition);
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- if ((c1 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
- || c1 < 0
- || (c2 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
- || c2 < 0
- || (c3 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
- || c3 < 0
- || (c4 = ScannerHelper.getHexadecimalValue(this.source[this.currentPosition++])) > 15
- || c4 < 0){
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
- //need the unicode buffer
- if (this.withoutUnicodePtr == 0) {
- //buffer all the entries that have been left aside....
- unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
- }
- //fill the buffer with the char
- unicodeStore();
- this.unicodeAsBackSlash = this.currentCharacter == '\\';
-}
-public NLSTag[] getNLSTags() {
- final int length = this.nlsTagsPtr;
- if (length != 0) {
- NLSTag[] result = new NLSTag[length];
- System.arraycopy(this.nlsTags, 0, result, 0, length);
- this.nlsTagsPtr = 0;
- return result;
- }
- return null;
-}
-@Override
-public char[] getSource(){
- return this.source;
-}
-protected boolean isFirstTag() {
- return true;
-}
-public final void jumpOverMethodBody() {
-
- this.wasAcr = false;
- int found = 1;
- try {
- while (true) { //loop for jumping over comments
- this.withoutUnicodePtr = 0;
- // ---------Consume white space and handles startPosition---------
- boolean isWhiteSpace;
- do {
- this.startPosition = this.currentPosition;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- isWhiteSpace = jumpOverUnicodeWhiteSpace();
- } else {
- if (this.recordLineSeparator
- && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
- pushLineSeparator();
- }
- isWhiteSpace = CharOperation.isWhitespace(this.currentCharacter);
- }
- } while (isWhiteSpace);
-
- // -------consume token until } is found---------
- NextToken: switch (this.currentCharacter) {
- case '{' :
- found++;
- break NextToken;
- case '}' :
- found--;
- if (found == 0)
- return;
- break NextToken;
- case '\'' :
- {
- boolean test;
- test = getNextChar('\\');
- if (test) {
- try {
- if (this.unicodeAsBackSlash) {
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- } else {
- this.currentCharacter = this.source[this.currentPosition++];
- }
- scanEscapeCharacter();
- } catch (InvalidInputException ex) {
- // ignore
- }
- } else {
- try { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- } catch (InvalidInputException ex) {
- // ignore
- }
- }
- getNextChar('\'');
- break NextToken;
- }
- case '"' :
- boolean isTextBlock = false;
- int firstClosingBrace = 0;
- try {
- try { // consume next character
- isTextBlock = scanForTextBlockBeginning();
- if (!isTextBlock) {
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- } catch (InvalidInputException ex) {
- // ignore
- }
- Inner: while (this.currentPosition <= this.eofPosition) {
- if (isTextBlock) {
- switch (this.currentCharacter) {
- case '"':
- // look for text block delimiter
- if (scanForTextBlockClose()) {
- this.currentPosition += 2;
- this.currentCharacter = this.source[this.currentPosition];
- isTextBlock = false;
- break Inner;
- }
- break;
- case '}':
- if (firstClosingBrace == 0)
- firstClosingBrace = this.currentPosition;
- break;
- case '\r' :
- if (this.source[this.currentPosition] == '\n')
- this.currentPosition++;
- //$FALL-THROUGH$
- case '\n' :
- pushLineSeparator();
- //$FALL-THROUGH$
- default:
- if (this.currentCharacter == '\\' && this.source[this.currentPosition] == '"') {
- this.currentPosition++;
- }
- this.currentCharacter = this.source[this.currentPosition++];
- continue Inner;
- }
- } else if (this.currentCharacter == '"') {
- break Inner;
- }
- if (this.currentCharacter == '\r'){
- if (this.source[this.currentPosition] == '\n') this.currentPosition++;
- break NextToken; // the string cannot go further that the line
- }
- if (this.currentCharacter == '\n'){
- break; // the string cannot go further that the line
- }
- if (this.currentCharacter == '\\') {
- try {
- if (this.unicodeAsBackSlash) {
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- } else {
- this.currentCharacter = this.source[this.currentPosition++];
- }
- scanEscapeCharacter();
- } catch (InvalidInputException ex) {
- // ignore
- }
- }
- try { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- } catch (InvalidInputException ex) {
- // ignore
- }
- }
- } catch (IndexOutOfBoundsException e) {
- if(isTextBlock) {
- // Pull it back to the first closing brace after the beginning
- // of the unclosed text block and let recovery take over.
- if (firstClosingBrace > 0) {
- this.currentPosition = firstClosingBrace - 1;
- }
- }
- }
- break NextToken;
- case '/' :
- {
- int test;
- if ((test = getNextChar('/', '*')) == 0) { //line comment
- try {
- this.lastCommentLinePosition = this.currentPosition;
- //get the next char
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- }
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++;
- } //jump over the \\
- boolean isUnicode = false;
- while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
- if (this.currentPosition >= this.eofPosition) {
- this.lastCommentLinePosition = this.currentPosition;
- this.currentPosition ++;
- // this avoids duplicating the code inside the catch(IndexOutOfBoundsException e) below
- throw new IndexOutOfBoundsException();
- }
- this.lastCommentLinePosition = this.currentPosition;
- //get the next char
- isUnicode = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- isUnicode = true;
- getNextUnicodeChar();
- }
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++;
- } //jump over the \\
- }
- /*
- * We need to completely consume the line break
- */
- if (this.currentCharacter == '\r'
- && this.eofPosition > this.currentPosition) {
- if (this.source[this.currentPosition] == '\n') {
- this.currentPosition++;
- this.currentCharacter = '\n';
- } else if ((this.source[this.currentPosition] == '\\')
- && (this.source[this.currentPosition + 1] == 'u')) {
- isUnicode = true;
- getNextUnicodeChar();
- }
- }
- recordComment(TokenNameCOMMENT_LINE);
- if (this.recordLineSeparator
- && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
- if (this.checkNonExternalizedStringLiterals &&
- this.lastPosition < this.currentPosition) {
- parseTags();
- }
- if (this.recordLineSeparator) {
- if (isUnicode) {
- pushUnicodeLineSeparator();
- } else {
- pushLineSeparator();
- }
- }
- }
- } catch (IndexOutOfBoundsException e) {
- //an eof will then be generated
- this.currentPosition--;
- recordComment(TokenNameCOMMENT_LINE);
- if (this.checkNonExternalizedStringLiterals &&
- this.lastPosition < this.currentPosition) {
- parseTags();
- }
- if (!this.tokenizeComments) {
- this.currentPosition++;
- }
- }
- break NextToken;
- }
- if (test > 0) { //traditional and javadoc comment
- boolean isJavadoc = false;
- try { //get the next char
- boolean star = false;
- int previous;
- boolean isUnicode = false;
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- isUnicode = false;
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
-
- if (this.currentCharacter == '*') {
- isJavadoc = true;
- star = true;
- }
- if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- if (this.recordLineSeparator) {
- if (isUnicode) {
- pushUnicodeLineSeparator();
- } else {
- pushLineSeparator();
- }
- }
- }
- isUnicode = false;
- previous = this.currentPosition;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- isUnicode = false;
- }
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++; //jump over the \\
- }
- // empty comment is not a javadoc /**/
- if (this.currentCharacter == '/') {
- isJavadoc = false;
- }
- //loop until end of comment */
- int firstTag = 0;
- while ((this.currentCharacter != '/') || (!star)) {
- if (this.currentPosition >= this.eofPosition) {
- return;
- }
- if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- if (this.recordLineSeparator) {
- if (isUnicode) {
- pushUnicodeLineSeparator();
- } else {
- pushLineSeparator();
- }
- }
- }
- switch (this.currentCharacter) {
- case '*':
- star = true;
- break;
- case '@':
- if (firstTag == 0 && this.isFirstTag()) {
- firstTag = previous;
- }
- //$FALL-THROUGH$ default case to set star to false
- default:
- star = false;
- }
- //get next char
- previous = this.currentPosition;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- isUnicode = true;
- } else {
- isUnicode = false;
- }
- //handle the \\u case manually into comment
- if (this.currentCharacter == '\\') {
- if (this.source[this.currentPosition] == '\\')
- this.currentPosition++;
- } //jump over the \\
- }
- recordComment(isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK);
- this.commentTagStarts[this.commentPtr] = firstTag;
- } catch (IndexOutOfBoundsException e) {
- return;
- }
- break NextToken;
- }
- break NextToken;
- }
-
- default :
- try {
- char c = this.currentCharacter;
- if (c < ScannerHelper.MAX_OBVIOUS) {
- if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
- scanIdentifierOrKeyword();
- break NextToken;
- } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
- scanNumber(false);
- break NextToken;
- } else {
- break NextToken;
- }
- }
- boolean isJavaIdStart;
- if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- // Unicode 4 detection
- char low = (char) getNextChar();
- if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
- // illegal low surrogate
- break NextToken;
- }
- isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c, low);
- } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
- break NextToken;
- } else {
- // optimized case already checked
- isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.complianceLevel, c);
- }
- if (isJavaIdStart) {
- scanIdentifierOrKeyword();
- break NextToken;
- }
-// if (ScannerHelper.isDigit(this.currentCharacter)) {
-// scanNumber(false);
-// break NextToken;
-// }
- } catch (InvalidInputException ex) {
- // ignore
- }
- }
- }
- //-----------------end switch while try--------------------
- } catch (IndexOutOfBoundsException | InvalidInputException e) {
- // ignore
- }
- return;
-}
-public final boolean jumpOverUnicodeWhiteSpace() throws InvalidInputException {
- //BOOLEAN
- //handle the case of unicode. Jump over the next whiteSpace
- //making startPosition pointing on the next available char
- //On false, the currentCharacter is filled up with a potential
- //correct char
-
- this.wasAcr = false;
- getNextUnicodeChar();
- return CharOperation.isWhitespace(this.currentCharacter);
-}
-
-private void parseTags() {
- int position = 0;
- final int currentStartPosition = this.startPosition;
- final int currentLinePtr = this.linePtr;
- if (currentLinePtr >= 0) {
- position = this.lineEnds[currentLinePtr] + 1;
- }
- while (ScannerHelper.isWhitespace(this.source[position])) {
- position++;
- }
- if (currentStartPosition == position) {
- // the whole line is commented out
- return;
- }
- char[] s = null;
- int sourceEnd = this.currentPosition;
- int sourceStart = currentStartPosition;
- int sourceDelta = 0;
- if (this.withoutUnicodePtr != 0) {
- // 0 is used as a fast test flag so the real first char is in position 1
- System.arraycopy(
- this.withoutUnicodeBuffer,
- 1,
- s = new char[this.withoutUnicodePtr],
- 0,
- this.withoutUnicodePtr);
- sourceEnd = this.withoutUnicodePtr;
- sourceStart = 1;
- sourceDelta = currentStartPosition;
- } else {
- s = this.source;
- }
- int pos = CharOperation.indexOf(TAG_PREFIX, s, true, sourceStart, sourceEnd);
- if (pos != -1) {
- if (this.nlsTags == null) {
- this.nlsTags = new NLSTag[10];
- this.nlsTagsPtr = 0;
- }
- while (pos != -1) {
- int start = pos + TAG_PREFIX_LENGTH;
- int end = CharOperation.indexOf(TAG_POSTFIX, s, start, sourceEnd);
- if (end != -1) {
- NLSTag currentTag = null;
- final int currentLine = currentLinePtr + 1;
- try {
- currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, extractInt(s, start, end));
- } catch (NumberFormatException e) {
- currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, -1);
- }
- if (this.nlsTagsPtr == this.nlsTags.length) {
- // resize
- System.arraycopy(this.nlsTags, 0, (this.nlsTags = new NLSTag[this.nlsTagsPtr + 10]), 0, this.nlsTagsPtr);
- }
- this.nlsTags[this.nlsTagsPtr++] = currentTag;
- } else {
- end = start;
- }
- pos = CharOperation.indexOf(TAG_PREFIX, s, true, end, sourceEnd);
- }
- }
-}
-private int extractInt(char[] array, int start, int end) {
- int value = 0;
- for (int i = start; i < end; i++) {
- final char currentChar = array[i];
- int digit = 0;
- switch(currentChar) {
- case '0' :
- digit = 0;
- break;
- case '1' :
- digit = 1;
- break;
- case '2' :
- digit = 2;
- break;
- case '3' :
- digit = 3;
- break;
- case '4' :
- digit = 4;
- break;
- case '5' :
- digit = 5;
- break;
- case '6' :
- digit = 6;
- break;
- case '7' :
- digit = 7;
- break;
- case '8' :
- digit = 8;
- break;
- case '9' :
- digit = 9;
- break;
- default :
- throw new NumberFormatException();
- }
- value *= 10;
- if (digit < 0) throw new NumberFormatException();
- value += digit;
- }
- return value;
-}
-public final void pushLineSeparator() {
- //see comment on isLineDelimiter(char) for the use of '\n' and '\r'
- final int INCREMENT = 250;
- //currentCharacter is at position currentPosition-1
- // cr 000D
- if (this.currentCharacter == '\r') {
- int separatorPos = this.currentPosition - 1;
- if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
- int length = this.lineEnds.length;
- if (++this.linePtr >= length)
- System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length);
- this.lineEnds[this.linePtr] = separatorPos;
- // look-ahead for merged cr+lf
- try {
- if (this.source[this.currentPosition] == '\n') {
- //System.out.println("look-ahead LF-" + this.currentPosition);
- this.lineEnds[this.linePtr] = this.currentPosition;
- this.currentPosition++;
- this.wasAcr = false;
- } else {
- this.wasAcr = true;
- }
- } catch(IndexOutOfBoundsException e) {
- this.wasAcr = true;
- }
- } else {
- // lf 000A
- if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf
- if (this.wasAcr && (this.lineEnds[this.linePtr] == (this.currentPosition - 2))) {
- //System.out.println("merge LF-" + (this.currentPosition - 1));
- this.lineEnds[this.linePtr] = this.currentPosition - 1;
- } else {
- int separatorPos = this.currentPosition - 1;
- if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
- int length = this.lineEnds.length;
- if (++this.linePtr >= length)
- System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length);
- this.lineEnds[this.linePtr] = separatorPos;
- }
- this.wasAcr = false;
- }
- }
-}
-public final void pushUnicodeLineSeparator() {
- // cr 000D
- if (this.currentCharacter == '\r') {
- if (this.source[this.currentPosition] == '\n') {
- this.wasAcr = false;
- } else {
- this.wasAcr = true;
- }
- } else {
- // lf 000A
- if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf
- this.wasAcr = false;
- }
- }
-}
-
-public void recordComment(int token) {
- // compute position
- int commentStart = this.startPosition;
- int stopPosition = this.currentPosition;
- switch (token) {
- case TokenNameCOMMENT_LINE:
- // both positions are negative
- commentStart = -this.startPosition;
- stopPosition = -this.lastCommentLinePosition;
- break;
- case TokenNameCOMMENT_BLOCK:
- // only end position is negative
- stopPosition = -this.currentPosition;
- break;
- }
-
- // a new comment is recorded
- int length = this.commentStops.length;
- if (++this.commentPtr >= length) {
- int newLength = length + COMMENT_ARRAYS_SIZE*10;
- System.arraycopy(this.commentStops, 0, this.commentStops = new int[newLength], 0, length);
- System.arraycopy(this.commentStarts, 0, this.commentStarts = new int[newLength], 0, length);
- System.arraycopy(this.commentTagStarts, 0, this.commentTagStarts = new int[newLength], 0, length);
- }
- this.commentStops[this.commentPtr] = stopPosition;
- this.commentStarts[this.commentPtr] = commentStart;
-}
-
-/**
- * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
- * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
- *
- * @param begin the given start position
- * @param end the given end position
- */
-@Override
-public void resetTo(int begin, int end) {
- //reset the scanner to a given position where it may rescan again
-
- this.diet = false;
- this.initialPosition = this.startPosition = this.currentPosition = begin;
- if (this.source != null && this.source.length < end) {
- this.eofPosition = this.source.length;
- } else {
- this.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
- }
- this.commentPtr = -1; // reset comment stack
- this.foundTaskCount = 0;
-}
-
-protected final void scanEscapeCharacter() throws InvalidInputException {
- // the string with "\\u" is a legal string of two chars \ and u
- //thus we use a direct access to the source (for regular cases).
- switch (this.currentCharacter) {
- case 'b' :
- this.currentCharacter = '\b';
- break;
- case 't' :
- this.currentCharacter = '\t';
- break;
- case 'n' :
- this.currentCharacter = '\n';
- break;
- case 'f' :
- this.currentCharacter = '\f';
- break;
- case 'r' :
- this.currentCharacter = '\r';
- break;
- case '\"' :
- this.currentCharacter = '\"';
- break;
- case '\'' :
- this.currentCharacter = '\'';
- break;
- case 's' :
- if (this.sourceLevel < ClassFileConstants.JDK15) {
- throw new InvalidInputException(INVALID_ESCAPE);
- }
- this.currentCharacter = ' ';
- break;
- case '\\' :
- this.currentCharacter = '\\';
- break;
- default :
- // -----------octal escape--------------
- // OctalDigit
- // OctalDigit OctalDigit
- // ZeroToThree OctalDigit OctalDigit
-
- int number = ScannerHelper.getHexadecimalValue(this.currentCharacter);
- if (number >= 0 && number <= 7) {
- boolean zeroToThreeNot = number > 3;
- if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
- int digit = ScannerHelper.getHexadecimalValue(this.currentCharacter);
- if (digit >= 0 && digit <= 7) {
- number = (number * 8) + digit;
- if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
- if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character
- this.currentPosition--;
- } else {
- digit = ScannerHelper.getHexadecimalValue(this.currentCharacter);
- if (digit >= 0 && digit <= 7){ // has read \ZeroToThree OctalDigit OctalDigit
- number = (number * 8) + digit;
- } else {// has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character
- this.currentPosition--;
- }
- }
- } else { // has read \OctalDigit NonDigit--> ignore last character
- this.currentPosition--;
- }
- } else { // has read \OctalDigit NonOctalDigit--> ignore last character
- this.currentPosition--;
- }
- } else { // has read \OctalDigit --> ignore last character
- this.currentPosition--;
- }
- if (number > 255)
- throw new InvalidInputException(INVALID_ESCAPE);
- this.currentCharacter = (char) number;
- } else
- throw new InvalidInputException(INVALID_ESCAPE);
- }
-}
-
-//{ObjectTeams: added to retrieve OT-specific special identifiers (after, before, replace)
-/*
- * If the Identifier is an SpecialIdentifier it will return the appropriate symbol from TerminalTokens.
- * @param data[] Identifier String
- * @return The int-type of an Special Identifier or TokenNameERROR
- */
-public int getCallinModifierToken(char[] data) {
-// replace after before
-
- int length=data.length;
- int index=0;
- char firstLetter = data[index];
- switch (firstLetter) {
- case 'a' :
- switch(length) {
- case 5: //after
- if ((data[++index] == 'f')
- && (data[++index] == 't')
- && (data[++index] == 'e')
- && (data[++index] == 'r'))
- return TokenNameafter;
- }
- break;
- case 'b' :
- switch (length) {
- case 6:// before
- if ((data[++index] == 'e')
- && (data[++index] == 'f')
- && (data[++index] == 'o')
- && (data[++index] == 'r')
- && (data[++index] == 'e'))
- return TokenNamebefore;
- }
- break;
- case 'r' :
- switch (length) {
- case 7: //replace
- if ((data[++index] == 'e')
- && (data[++index] == 'p')
- && (data[++index] == 'l')
- && (data[++index] == 'a')
- && (data[++index] == 'c')
- && (data[++index] == 'e'))
- return TokenNamereplace;
- }
- }
- return TokenNameERROR;
-}
-// Markus Witte}
-
-public int scanIdentifierOrKeywordWithBoundCheck() {
- //test keywords
-
- //first dispatch on the first char.
- //then the length. If there are several
- //keywors with the same length AND the same first char, then do another
- //dispatch on the second char
- this.useAssertAsAnIndentifier = false;
- this.useEnumAsAnIndentifier = false;
-
- char[] src = this.source;
- identLoop: {
- int pos;
- int srcLength = this.eofPosition;
- while (true) {
- if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront
- break identLoop;
- char c = src[pos];
- if (c < ScannerHelper.MAX_OBVIOUS) {
- if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] &
- (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) {
- if (this.withoutUnicodePtr != 0) {
- this.currentCharacter = c;
- unicodeStore();
- }
- this.currentPosition++;
- } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) {
- this.currentCharacter = c;
- break identLoop;
- } else {
- //System.out.println("slow<=128: "+ c);
- while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/}
- break identLoop;
- }
- } else {
- //System.out.println("slow>>128: "+ c);
- while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/}
- break identLoop;
- }
- }
- }
-
- int index, length;
- char[] data;
- if (this.withoutUnicodePtr == 0) {
- //quick test on length == 1 but not on length > 12 while most identifier
- //have a length which is <= 12...but there are lots of identifier with
- //only one char....
- if ((length = this.currentPosition - this.startPosition) == 1) {
- return InternalTokenNameIdentifier;
- }
- data = this.source;
- index = this.startPosition;
- } else {
- if ((length = this.withoutUnicodePtr) == 1)
- return InternalTokenNameIdentifier;
- data = this.withoutUnicodeBuffer;
- index = 1;
- }
-
- return internalScanIdentifierOrKeyword(index, length, data);
-}
-public int scanIdentifierOrKeyword() {
- //test keywords
-
- //first dispatch on the first char.
- //then the length. If there are several
- //keywords with the same length AND the same first char, then do another
- //dispatch on the second char
- this.useAssertAsAnIndentifier = false;
- this.useEnumAsAnIndentifier = false;
-
- char[] src = this.source;
- identLoop: {
- int pos;
- int srcLength = this.eofPosition;
- while (true) {
- if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront
- break identLoop;
- char c = src[pos];
- if (c < ScannerHelper.MAX_OBVIOUS) {
- if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] &
- (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) {
- if (this.withoutUnicodePtr != 0) {
- this.currentCharacter = c;
- unicodeStore();
- }
- this.currentPosition++;
- } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) {
- this.currentCharacter = c;
- break identLoop;
- } else {
- //System.out.println("slow<=128: "+ c);
- while (getNextCharAsJavaIdentifierPart()){/*empty*/}
- break identLoop;
- }
- } else {
- //System.out.println("slow>>128: "+ c);
- while (getNextCharAsJavaIdentifierPart()){/*empty*/}
- break identLoop;
- }
- }
- }
-
- int index, length;
- char[] data;
- if (this.withoutUnicodePtr == 0) {
- //quick test on length == 1 but not on length > 12 while most identifier
- //have a length which is <= 12...but there are lots of identifier with
- //only one char....
- if ((length = this.currentPosition - this.startPosition) == 1) {
- return InternalTokenNameIdentifier;
- }
- data = this.source;
- index = this.startPosition;
- } else {
- if ((length = this.withoutUnicodePtr) == 1)
- return InternalTokenNameIdentifier;
- data = this.withoutUnicodeBuffer;
- index = 1;
- }
-
- return internalScanIdentifierOrKeyword(index, length, data);
-}
-private int internalScanIdentifierOrKeyword(int index, int length, char[] data) {
-//{ObjectTeams: callin/calloutSeen/atStartOfImport/precedenceSeen has effect only once:
- boolean calloutSeen = this._calloutSeen;
- this._calloutSeen = false;
- boolean callinSeen = this._callinSeen;
- this._callinSeen = false;
- boolean precedenceSeen = this._precedenceSeen;
- this._precedenceSeen = false;
- boolean atStartOfImport = this._atStartOfImport;
- this._atStartOfImport = false;
-// SH}
- switch (data[index]) {
- case 'a' :
- switch(length) {
-//{ObjectTeams: keyword 'as':
- case 2: //as
- if ( this._isOTSource
- && (data[++index] == 's')) {
- return TokenNameas;
- } else {
- return InternalTokenNameIdentifier;
- }
-// MW}
- case 8: //abstract
- if ((data[++index] == 'b')
- && (data[++index] == 's')
- && (data[++index] == 't')
- && (data[++index] == 'r')
- && (data[++index] == 'a')
- && (data[++index] == 'c')
- && (data[++index] == 't')) {
- return TokenNameabstract;
- } else {
- return InternalTokenNameIdentifier;
- }
-//{ObjectTeams: 'after' (only if after "<-" or "precedence"):
- case 5:
- if (callinSeen || precedenceSeen) {
- if ( (data[++index] == 'f')
- && (data[++index] == 't')
- && (data[++index] == 'e')
- && (data[++index] == 'r'))
- return TokenNameafter;
- }
- return InternalTokenNameIdentifier;
-// SH}
- case 6: // assert
- if ((data[++index] == 's')
- && (data[++index] == 's')
- && (data[++index] == 'e')
- && (data[++index] == 'r')
- && (data[++index] == 't')) {
- if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
- this.containsAssertKeyword = true;
- return TokenNameassert;
- } else {
- this.useAssertAsAnIndentifier = true;
- return InternalTokenNameIdentifier;
- }
- } else {
- return InternalTokenNameIdentifier;
- }
- default:
- return InternalTokenNameIdentifier;
- }
- case 'b' : //boolean break byte (before)
- switch (length) {
- case 4 :
- if ((data[++index] == 'y') && (data[++index] == 't') && (data[++index] == 'e'))
- return TokenNamebyte;
- else
-//{ObjectTeams: check for base keyword
- /*@original
- return InternalTokenNameIdentifier;
- */
- {
- if ( baseIsKeyword(atStartOfImport)
- && (data[index] == 'a')
- && (data[++index] == 's')
- && (data[++index] == 'e'))
- return TokenNamebase;
- else
- return InternalTokenNameIdentifier;
- }
-//Markus Witte}
- case 5 :
- if ((data[++index] == 'r')
- && (data[++index] == 'e')
- && (data[++index] == 'a')
- && (data[++index] == 'k'))
- return TokenNamebreak;
- else
- return InternalTokenNameIdentifier;
-
-//{ObjectTeams: 'before' (only if after "<-"):
- case 6:
- if (callinSeen) {
- if ( (data[++index] == 'e')
- && (data[++index] == 'f')
- && (data[++index] == 'o')
- && (data[++index] == 'r')
- && (data[++index] == 'e'))
- return TokenNamebefore;
- }
- return InternalTokenNameIdentifier;
-// SH}
- case 7 :
- if ((data[++index] == 'o')
- && (data[++index] == 'o')
- && (data[++index] == 'l')
- && (data[++index] == 'e')
- && (data[++index] == 'a')
- && (data[++index] == 'n'))
- return TokenNameboolean;
- else
- return InternalTokenNameIdentifier;
- default :
- return InternalTokenNameIdentifier;
- }
-
- case 'c' : //case char catch const class continue
- switch (length) {
- case 4 :
- if (data[++index] == 'a')
- if ((data[++index] == 's') && (data[++index] == 'e'))
- return TokenNamecase;
- else
- return InternalTokenNameIdentifier;
- else
- if ((data[index] == 'h') && (data[++index] == 'a') && (data[++index] == 'r'))
- return TokenNamechar;
- else
- return InternalTokenNameIdentifier;
- case 5 :
- if (data[++index] == 'a')
- if ((data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h'))
- return TokenNamecatch;
- else
- return InternalTokenNameIdentifier;
- else
- if (data[index] == 'l')
- if ((data[++index] == 'a')
- && (data[++index] == 's')
- && (data[++index] == 's'))
-//{ObjectTeams: advance scanner state:
- {
- if (this._teamKeywordSeen)
- enterOTSource(); // either in team class or in ROFI class
-// orig:
- return TokenNameclass;
-// :giro
- }
-// SH}
- else
- return InternalTokenNameIdentifier;
- else if ((data[index] == 'o')
- && (data[++index] == 'n')
- && (data[++index] == 's')
- && (data[++index] == 't'))
- return TokenNameconst; //const is not used in java ???????
- else
- return InternalTokenNameIdentifier;
-//{ObjectTeams: check for callin keyword
- case 6: //callin
- if ( this._isOTSource
- && (data[++index] == 'a')
- && (data[++index] == 'l')
- && (data[++index] == 'l')
- && (data[++index] == 'i')
- && (data[++index] == 'n'))
- return TokenNamecallin;
- else
- return InternalTokenNameIdentifier;
-
-//Markus Witte}
- case 8 :
- if ((data[++index] == 'o')
- && (data[++index] == 'n')
- && (data[++index] == 't')
- && (data[++index] == 'i')
- && (data[++index] == 'n')
- && (data[++index] == 'u')
- && (data[++index] == 'e'))
- return TokenNamecontinue;
- else
- return InternalTokenNameIdentifier;
- default :
- return InternalTokenNameIdentifier;
- }
-
- case 'd' : //default do double
- switch (length) {
- case 2 :
- if ((data[++index] == 'o'))
- return TokenNamedo;
- else
- return InternalTokenNameIdentifier;
- case 6 :
- if ((data[++index] == 'o')
- && (data[++index] == 'u')
- && (data[++index] == 'b')
- && (data[++index] == 'l')
- && (data[++index] == 'e'))
- return TokenNamedouble;
- else
- return InternalTokenNameIdentifier;
- case 7 :
- if ((data[++index] == 'e')
- && (data[++index] == 'f')
- && (data[++index] == 'a')
- && (data[++index] == 'u')
- && (data[++index] == 'l')
- && (data[++index] == 't'))
- return TokenNamedefault;
- else
- return InternalTokenNameIdentifier;
- default :
- return InternalTokenNameIdentifier;
- }
- case 'e' : //else extends
- switch (length) {
- case 4 :
- if (data[++index] == 'l') {
- if ((data[++index] == 's') && (data[++index] == 'e')) {
- return TokenNameelse;
- } else {
- return InternalTokenNameIdentifier;
- }
- } else if ((data[index] == 'n')
- && (data[++index] == 'u')
- && (data[++index] == 'm')) {
- if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
- return TokenNameenum;
- } else {
- this.useEnumAsAnIndentifier = true;
- return InternalTokenNameIdentifier;
- }
- }
- return InternalTokenNameIdentifier;
- case 7 :
- if ((data[++index] == 'x')
- && (data[++index] == 't')
- && (data[++index] == 'e')
- && (data[++index] == 'n')
- && (data[++index] == 'd')
- && (data[++index] == 's'))
- return TokenNameextends;
- else
- return InternalTokenNameIdentifier;
- default :
- return InternalTokenNameIdentifier;
- }
-
- case 'f' : //final finally float for false
- switch (length) {
- case 3 :
- if ((data[++index] == 'o') && (data[++index] == 'r'))
- return TokenNamefor;
- else
- return InternalTokenNameIdentifier;
- case 5 :
- if (data[++index] == 'i')
- if ((data[++index] == 'n')
- && (data[++index] == 'a')
- && (data[++index] == 'l')) {
- return TokenNamefinal;
- } else
- return InternalTokenNameIdentifier;
- else
- if (data[index] == 'l')
- if ((data[++index] == 'o')
- && (data[++index] == 'a')
- && (data[++index] == 't'))
- return TokenNamefloat;
- else
- return InternalTokenNameIdentifier;
- else
- if ((data[index] == 'a')
- && (data[++index] == 'l')
- && (data[++index] == 's')
- && (data[++index] == 'e'))
- return TokenNamefalse;
- else
- return InternalTokenNameIdentifier;
- case 7 :
- if ((data[++index] == 'i')
- && (data[++index] == 'n')
- && (data[++index] == 'a')
- && (data[++index] == 'l')
- && (data[++index] == 'l')
- && (data[++index] == 'y'))
- return TokenNamefinally;
- else
- return InternalTokenNameIdentifier;
-
- default :
- return InternalTokenNameIdentifier;
- }
- case 'g' :
-//{ObjectTeams: 'get':
- if (length == 3 && calloutSeen) {
- if ( (data[++index] == 'e')
- && (data[++index] == 't'))
- return TokenNameget;
- }
-// SH}
- //goto
- if (length == 4) {
- if ((data[++index] == 'o')
- && (data[++index] == 't')
- && (data[++index] == 'o')) {
- return TokenNamegoto;
- }
- } //no goto in java are allowed, so why java removes this keyword ???
- return InternalTokenNameIdentifier;
-
- case 'i' : //if implements import instanceof int interface
- switch (length) {
- case 2 :
- if (data[++index] == 'f')
- return TokenNameif;
- else
- return InternalTokenNameIdentifier;
- case 3 :
- if ((data[++index] == 'n') && (data[++index] == 't'))
- return TokenNameint;
- else
- return InternalTokenNameIdentifier;
- case 6 :
- if ((data[++index] == 'm')
- && (data[++index] == 'p')
- && (data[++index] == 'o')
- && (data[++index] == 'r')
- && (data[++index] == 't'))
-//{ObjectTeams: support 'base' as the very next word:
- {
- this._atStartOfImport = true;
-// orig:
- return TokenNameimport;
-// :giro
- }
-// SH}
- else
- return InternalTokenNameIdentifier;
- case 9 :
- if ((data[++index] == 'n')
- && (data[++index] == 't')
- && (data[++index] == 'e')
- && (data[++index] == 'r')
- && (data[++index] == 'f')
- && (data[++index] == 'a')
- && (data[++index] == 'c')
- && (data[++index] == 'e'))
-//{ObjectTeams: advance scanner state:
- {
- if (this._teamKeywordSeen)
- enterOTSource(); // in ROFI interface
-// orig:
- return TokenNameinterface;
-// :giro
- }
-// SH}
- else
- return InternalTokenNameIdentifier;
- case 10 :
- if (data[++index] == 'm')
- if ((data[++index] == 'p')
- && (data[++index] == 'l')
- && (data[++index] == 'e')
- && (data[++index] == 'm')
- && (data[++index] == 'e')
- && (data[++index] == 'n')
- && (data[++index] == 't')
- && (data[++index] == 's'))
- return TokenNameimplements;
- else
- return InternalTokenNameIdentifier;
- else
- if ((data[index] == 'n')
- && (data[++index] == 's')
- && (data[++index] == 't')
- && (data[++index] == 'a')
- && (data[++index] == 'n')
- && (data[++index] == 'c')
- && (data[++index] == 'e')
- && (data[++index] == 'o')
- && (data[++index] == 'f'))
- return TokenNameinstanceof;
- else
- return InternalTokenNameIdentifier;
-
- default :
- return InternalTokenNameIdentifier;
- }
- case 'l' : //long
- if (length == 4) {
- if ((data[++index] == 'o')
- && (data[++index] == 'n')
- && (data[++index] == 'g')) {
- return TokenNamelong;
- }
- }
- return InternalTokenNameIdentifier;
-
- case 'n' : //native new null
- switch (length) {
- case 3 :
- if ((data[++index] == 'e') && (data[++index] == 'w'))
- return TokenNamenew;
- else
- return InternalTokenNameIdentifier;
- case 4 :
- if ((data[++index] == 'u') && (data[++index] == 'l') && (data[++index] == 'l'))
- return TokenNamenull;
- else
- return InternalTokenNameIdentifier;
- case 6 :
- if ((data[++index] == 'a')
- && (data[++index] == 't')
- && (data[++index] == 'i')
- && (data[++index] == 'v')
- && (data[++index] == 'e')) {
- return TokenNamenative;
- } else
- return InternalTokenNameIdentifier;
- default :
- return InternalTokenNameIdentifier;
- }
-
- case 'p' : //package private protected public
- switch (length) {
- case 6 :
- if ((data[++index] == 'u')
- && (data[++index] == 'b')
- && (data[++index] == 'l')
- && (data[++index] == 'i')
- && (data[++index] == 'c')) {
- return TokenNamepublic;
- } else
- return InternalTokenNameIdentifier;
- case 7 :
- if (data[++index] == 'a')
- if ((data[++index] == 'c')
- && (data[++index] == 'k')
- && (data[++index] == 'a')
- && (data[++index] == 'g')
- && (data[++index] == 'e'))
- return TokenNamepackage;
- else
- return InternalTokenNameIdentifier;
- else
- if ((data[index] == 'r')
- && (data[++index] == 'i')
- && (data[++index] == 'v')
- && (data[++index] == 'a')
- && (data[++index] == 't')
- && (data[++index] == 'e')) {
- return TokenNameprivate;
- } else
- return InternalTokenNameIdentifier;
-//{ObjectTeams: check for playedBy/precedence keywords
- case 8 :
- if ( this._isOTSource
- && (data[++index] == 'l')
- && (data[++index] == 'a')
- && (data[++index] == 'y')
- && (data[++index] == 'e')
- && (data[++index] == 'd')
- && (data[++index] == 'B')
- && (data[++index] == 'y')) {
- return TokenNameplayedBy;
- } else
- return InternalTokenNameIdentifier;
- case 10 :
- if ( this._isOTSource
- && (data[++index] == 'r')
- && (data[++index] == 'e')
- && (data[++index] == 'c')
- && (data[++index] == 'e')
- && (data[++index] == 'd')
- && (data[++index] == 'e')
- && (data[++index] == 'n')
- && (data[++index] == 'c')
- && (data[++index] == 'e')) {
- this._precedenceSeen = true;
- return TokenNameprecedence;
- } else
- return InternalTokenNameIdentifier;
-//Markus Witte/SH}
- case 9 :
- if ((data[++index] == 'r')
- && (data[++index] == 'o')
- && (data[++index] == 't')
- && (data[++index] == 'e')
- && (data[++index] == 'c')
- && (data[++index] == 't')
- && (data[++index] == 'e')
- && (data[++index] == 'd')) {
- return TokenNameprotected;
- } else
- return InternalTokenNameIdentifier;
-
- default :
- return InternalTokenNameIdentifier;
- }
- case 'r' : //return
- if (length == 6) {
- if ((data[++index] == 'e')
- && (data[++index] == 't')
- && (data[++index] == 'u')
- && (data[++index] == 'r')
- && (data[++index] == 'n')) {
- return TokenNamereturn;
- }
- }
-//{ObjectTeams: 'replace' (only if after "<-"):
- else if (length == 7 && callinSeen) {
- if ( (data[++index] == 'e')
- && (data[++index] == 'p')
- && (data[++index] == 'l')
- && (data[++index] == 'a')
- && (data[++index] == 'c')
- && (data[++index] == 'e'))
- return TokenNamereplace;
- }
-// SH}
- return InternalTokenNameIdentifier;
-
- case 's' : //short static super switch synchronized strictfp
- switch (length) {
-//{ObjectTeams: 'set' (after '->')
- case 3:
- if (calloutSeen) {
- if ( (data[++index] == 'e')
- && (data[++index] == 't'))
- return TokenNameset;
- }
- return InternalTokenNameIdentifier;
-// SH}
- case 5 :
- if (data[++index] == 'h')
- if ((data[++index] == 'o') && (data[++index] == 'r') && (data[++index] == 't'))
- return TokenNameshort;
- else
- return InternalTokenNameIdentifier;
- else
- if ((data[index] == 'u')
- && (data[++index] == 'p')
- && (data[++index] == 'e')
- && (data[++index] == 'r'))
- return TokenNamesuper;
- else
- return InternalTokenNameIdentifier;
-
- case 6 :
- if (data[++index] == 't')
- if ((data[++index] == 'a')
- && (data[++index] == 't')
- && (data[++index] == 'i')
- && (data[++index] == 'c')) {
- return TokenNamestatic;
- } else
- return InternalTokenNameIdentifier;
- else
- if ((data[index] == 'w')
- && (data[++index] == 'i')
- && (data[++index] == 't')
- && (data[++index] == 'c')
- && (data[++index] == 'h'))
- return TokenNameswitch;
- else
- return InternalTokenNameIdentifier;
- case 8 :
- if ((data[++index] == 't')
- && (data[++index] == 'r')
- && (data[++index] == 'i')
- && (data[++index] == 'c')
- && (data[++index] == 't')
- && (data[++index] == 'f')
- && (data[++index] == 'p'))
- return TokenNamestrictfp;
- else
- return InternalTokenNameIdentifier;
- case 12 :
- if ((data[++index] == 'y')
- && (data[++index] == 'n')
- && (data[++index] == 'c')
- && (data[++index] == 'h')
- && (data[++index] == 'r')
- && (data[++index] == 'o')
- && (data[++index] == 'n')
- && (data[++index] == 'i')
- && (data[++index] == 'z')
- && (data[++index] == 'e')
- && (data[++index] == 'd')) {
- return TokenNamesynchronized;
- } else
- return InternalTokenNameIdentifier;
- default :
- return InternalTokenNameIdentifier;
- }
-
- case 't' : //try throw throws transient this true
- switch (length) {
- case 3 :
- if ((data[++index] == 'r') && (data[++index] == 'y'))
- return TokenNametry;
- else
- return InternalTokenNameIdentifier;
- case 4 :
- if (data[++index] == 'h')
- if ((data[++index] == 'i') && (data[++index] == 's'))
- return TokenNamethis;
- else
- return InternalTokenNameIdentifier;
- else
- if ((data[index] == 'r') && (data[++index] == 'u') && (data[++index] == 'e'))
- return TokenNametrue;
- else
-//{ObjectTeams: check for team keyword (always checked except after '.' -- if seen set isOTsource)
- if ((data[index] == 'e')
- && (data[++index] == 'a')
- && (data[++index] == 'm')
- && (this._isOTSource || this._dotSeen == 0)
- && !this.parsePureJavaOnly)
- {
- this._teamKeywordSeen = true;
- return TokenNameteam;
- } else
-//Markus Witte}
- return InternalTokenNameIdentifier;
- case 5 :
- if ((data[++index] == 'h')
- && (data[++index] == 'r')
- && (data[++index] == 'o')
- && (data[++index] == 'w'))
- return TokenNamethrow;
- else
- return InternalTokenNameIdentifier;
- case 6 :
-//{ObjectTeams: check for tsuper keyword
-/* orig:
- if ((data[++index] == 'h')
- && (data[++index] == 'r')
- :giro */
- if ((data[++index] == 'h')) {
- if ((data[++index] == 'r')
-// orig:
- && (data[++index] == 'o')
- && (data[++index] == 'w')
- && (data[++index] == 's'))
- return TokenNamethrows;
- else
- return InternalTokenNameIdentifier;
-// :giro
- } else {
- if ( this._isOTSource
- && (data[index] == 's')
- && (data[++index] == 'u')
- && (data[++index] == 'p')
- && (data[++index] == 'e')
- && (data[++index] == 'r'))
- return TokenNametsuper;
- else
- return InternalTokenNameIdentifier;
- }
-//Markus Witte}
- case 9 :
- if ((data[++index] == 'r')
- && (data[++index] == 'a')
- && (data[++index] == 'n')
- && (data[++index] == 's')
- && (data[++index] == 'i')
- && (data[++index] == 'e')
- && (data[++index] == 'n')
- && (data[++index] == 't')) {
- return TokenNametransient;
- } else
- return InternalTokenNameIdentifier;
-
- default :
- return InternalTokenNameIdentifier;
- }
-
- case 'v' : //void volatile
- switch (length) {
- case 4 :
- if ((data[++index] == 'o') && (data[++index] == 'i') && (data[++index] == 'd'))
- return TokenNamevoid;
- else
- return InternalTokenNameIdentifier;
- case 8 :
- if ((data[++index] == 'o')
- && (data[++index] == 'l')
- && (data[++index] == 'a')
- && (data[++index] == 't')
- && (data[++index] == 'i')
- && (data[++index] == 'l')
- && (data[++index] == 'e')) {
- return TokenNamevolatile;
- } else
- return InternalTokenNameIdentifier;
-
- default :
- return InternalTokenNameIdentifier;
- }
-
- case 'w' : //while widefp
- switch (length) {
-//{ObjectTeams: check for with, when keywords
-
- case 4 : // with when
- switch (data[++index]) {
- case 'i':
- if ( this._isOTSource
- && (data[++index] == 't')
- && (data[++index] == 'h'))
- return TokenNamewith;
- break;
- case 'h':
- if ( this._isOTSource
- && (data[++index] == 'e')
- && (data[++index] == 'n'))
- return TokenNamewhen;
- }
- return InternalTokenNameIdentifier;
-
-//Markus Witte}
- case 5 :
- if ((data[++index] == 'h')
- && (data[++index] == 'i')
- && (data[++index] == 'l')
- && (data[++index] == 'e'))
- return TokenNamewhile;
- else
- return InternalTokenNameIdentifier;
- //case 6:if ( (data[++index] =='i') && (data[++index]=='d') && (data[++index]=='e') && (data[++index]=='f')&& (data[++index]=='p'))
- //return TokenNamewidefp ;
- //else
- //return TokenNameIdentifier;
-//{ObjectTeams: check for within keyword (also in std-Java files).
- case 6 :
- if ((data[++index] == 'i')
- && (data[++index] == 't')
- && (data[++index] == 'h')
- && (data[++index] == 'i')
- && (data[++index] == 'n')
- && !this.parsePureJavaOnly)
- return TokenNamewithin;
- else
- return InternalTokenNameIdentifier;
-
-//Markus Witte}
- default :
- return InternalTokenNameIdentifier;
- }
-
- default :
- return InternalTokenNameIdentifier;
- }
-}
-
-
-public int scanNumber(boolean dotPrefix) throws InvalidInputException {
-
- //when entering this method the currentCharacter is the first
- //digit of the number. It may be preceeded by a '.' when
- //dotPrefix is true
-
- boolean floating = dotPrefix;
- if (!dotPrefix && (this.currentCharacter == '0')) {
- if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
- int start = this.currentPosition;
- consumeDigits(16, true);
- int end = this.currentPosition;
- if (getNextChar('l', 'L') >= 0) {
- if (end == start) {
- throw new InvalidInputException(INVALID_HEXA);
- }
- return TokenNameLongLiteral;
- } else if (getNextChar('.')) {
- // hexadecimal floating point literal
- // read decimal part
- boolean hasNoDigitsBeforeDot = end == start;
- start = this.currentPosition;
- consumeDigits(16, true);
- end = this.currentPosition;
- if (hasNoDigitsBeforeDot && end == start) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- throw new InvalidInputException(INVALID_HEXA);
- }
-
- if (getNextChar('p', 'P') >= 0) { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
-
- if ((this.currentCharacter == '-')
- || (this.currentCharacter == '+')) { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- if (!ScannerHelper.isDigit(this.currentCharacter)) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- if (this.currentCharacter == '_') {
- // wrongly place '_'
- consumeDigits(10);
- throw new InvalidInputException(INVALID_UNDERSCORE);
- }
- throw new InvalidInputException(INVALID_HEXA);
- }
- consumeDigits(10);
- if (getNextChar('f', 'F') >= 0) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- return TokenNameFloatingPointLiteral;
- }
- if (getNextChar('d', 'D') >= 0) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- return TokenNameDoubleLiteral;
- }
- if (getNextChar('l', 'L') >= 0) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- throw new InvalidInputException(INVALID_HEXA);
- }
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- return TokenNameDoubleLiteral;
- } else {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- throw new InvalidInputException(INVALID_HEXA);
- }
- } else if (getNextChar('p', 'P') >= 0) { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
-
- if ((this.currentCharacter == '-')
- || (this.currentCharacter == '+')) { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- if (!ScannerHelper.isDigit(this.currentCharacter)) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- if (this.currentCharacter == '_') {
- // wrongly place '_'
- consumeDigits(10);
- throw new InvalidInputException(INVALID_UNDERSCORE);
- }
- throw new InvalidInputException(INVALID_FLOAT);
- }
- consumeDigits(10);
- if (getNextChar('f', 'F') >= 0) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- return TokenNameFloatingPointLiteral;
- }
- if (getNextChar('d', 'D') >= 0) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- return TokenNameDoubleLiteral;
- }
- if (getNextChar('l', 'L') >= 0) {
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- throw new InvalidInputException(INVALID_HEXA);
- }
- if (this.sourceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(ILLEGAL_HEXA_LITERAL);
- }
- return TokenNameDoubleLiteral;
- } else {
- if (end == start)
- throw new InvalidInputException(INVALID_HEXA);
- return TokenNameIntegerLiteral;
- }
- } else if (getNextChar('b', 'B') >= 0) { //----------binary-----------------
- int start = this.currentPosition;
- consumeDigits(2, true);
- int end = this.currentPosition;
- if (end == start) {
- if (this.sourceLevel < ClassFileConstants.JDK1_7) {
- throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17);
- }
- throw new InvalidInputException(INVALID_BINARY);
- }
- if (getNextChar('l', 'L') >= 0) {
- if (this.sourceLevel < ClassFileConstants.JDK1_7) {
- throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17);
- }
- return TokenNameLongLiteral;
- }
- if (this.sourceLevel < ClassFileConstants.JDK1_7) {
- throw new InvalidInputException(BINARY_LITERAL_NOT_BELOW_17);
- }
- return TokenNameIntegerLiteral;
- }
-
- //there is no x or X nor b or B in the number
- //potential octal
- if (getNextCharAsDigit()) { //-------------potential octal-----------------
- consumeDigits(10);
-
- if (getNextChar('l', 'L') >= 0) {
- return TokenNameLongLiteral;
- }
-
- if (getNextChar('f', 'F') >= 0) {
- return TokenNameFloatingPointLiteral;
- }
-
- if (getNextChar('d', 'D') >= 0) {
- return TokenNameDoubleLiteral;
- } else { //make the distinction between octal and float ....
- boolean isInteger = true;
- if (getNextChar('.')) {
- isInteger = false;
- consumeDigits(10);
- }
- if (getNextChar('e', 'E') >= 0) { // consume next character
- isInteger = false;
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
-
- if ((this.currentCharacter == '-')
- || (this.currentCharacter == '+')) { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- if (!ScannerHelper.isDigit(this.currentCharacter)) {
- if (this.currentCharacter == '_') {
- // wrongly place '_'
- consumeDigits(10);
- throw new InvalidInputException(INVALID_UNDERSCORE);
- }
- throw new InvalidInputException(INVALID_FLOAT);
- }
- consumeDigits(10);
- }
- if (getNextChar('f', 'F') >= 0)
- return TokenNameFloatingPointLiteral;
- if (getNextChar('d', 'D') >= 0 || !isInteger)
- return TokenNameDoubleLiteral;
- return TokenNameIntegerLiteral;
- }
- } else {
- /* carry on */
- }
- }
-
- consumeDigits(10);
-
- if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
- return TokenNameLongLiteral;
-
- if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
- consumeDigits(10, true);
- floating = true;
- }
-
- //if floating is true both exponant and suffix may be optional
-
- if (getNextChar('e', 'E') >= 0) {
- floating = true;
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
-
- if ((this.currentCharacter == '-')
- || (this.currentCharacter == '+')) { // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStore();
- }
- }
- }
- if (!ScannerHelper.isDigit(this.currentCharacter)) {
- if (this.currentCharacter == '_') {
- // wrongly place '_'
- consumeDigits(10);
- throw new InvalidInputException(INVALID_UNDERSCORE);
- }
- throw new InvalidInputException(INVALID_FLOAT);
- }
- // current character is a digit so we expect no digit first (the next character could be an underscore)
- consumeDigits(10);
- }
-
- if (getNextChar('d', 'D') >= 0)
- return TokenNameDoubleLiteral;
- if (getNextChar('f', 'F') >= 0)
- return TokenNameFloatingPointLiteral;
-
- //the long flag has been tested before
-
- return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral;
-}
-
-/**
- * Search the line number corresponding to a specific position
- * @param position int
- * @return int
- */
-@Override
-public final int getLineNumber(int position) {
- return Util.getLineNumber(position, this.lineEnds, 0, this.linePtr);
-}
-@Override
-public final void setSource(char[] sourceString){
- //the source-buffer is set to sourceString
-
- int sourceLength;
- if (sourceString == null) {
- this.source = CharOperation.NO_CHAR;
- sourceLength = 0;
- } else {
- this.source = sourceString;
- sourceLength = sourceString.length;
- }
- this.startPosition = -1;
- this.eofPosition = sourceLength;
- this.initialPosition = this.currentPosition = 0;
- this.containsAssertKeyword = false;
- this.linePtr = -1;
-//{ObjectTeams: reset to default mode (std-Java).
- resetOTFlags();
-// SH}
-}
-/*
- * Should be used if a parse (usually a diet parse) has already been performed on the unit,
- * so as to get the already computed line end positions.
- */
-public final void setSource(char[] contents, CompilationResult compilationResult) {
- if (contents == null) {
- char[] cuContents = compilationResult.compilationUnit.getContents();
- setSource(cuContents);
- } else {
- setSource(contents);
- }
- int[] lineSeparatorPositions = compilationResult.lineSeparatorPositions;
- if (lineSeparatorPositions != null) {
- this.lineEnds = lineSeparatorPositions;
- this.linePtr = lineSeparatorPositions.length - 1;
- }
-}
-/*
- * Should be used if a parse (usually a diet parse) has already been performed on the unit,
- * so as to get the already computed line end positions.
- */
-public final void setSource(CompilationResult compilationResult) {
- setSource(null, compilationResult);
-}
-@Override
-public String toString() {
- if (this.startPosition == this.eofPosition)
- return "EOF\n\n" + new String(this.source); //$NON-NLS-1$
- if (this.currentPosition > this.eofPosition)
- return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$
- if (this.currentPosition <= 0)
- return "NOT started!\n\n"+ new String(this.source); //$NON-NLS-1$
-
- StringBuilder buffer = new StringBuilder();
- if (this.startPosition < 1000) {
- buffer.append(this.source, 0, this.startPosition);
- } else {
- buffer.append("<source beginning>\n...\n"); //$NON-NLS-1$
- int line = Util.getLineNumber(this.startPosition-1000, this.lineEnds, 0, this.linePtr);
- int lineStart = getLineStart(line);
- buffer.append(this.source, lineStart, this.startPosition-lineStart);
- }
-
- buffer.append("\n===============================\nStarts here -->"); //$NON-NLS-1$
- int middleLength = (this.currentPosition - 1) - this.startPosition + 1;
- if (middleLength > -1) {
- buffer.append(this.source, this.startPosition, middleLength);
- }
- buffer.append("<-- Ends here\n===============================\n"); //$NON-NLS-1$
-
- buffer.append(this.source, (this.currentPosition - 1) + 1, this.eofPosition - (this.currentPosition - 1) - 1);
-
- return buffer.toString();
-}
-public String toStringAction(int act) {
- switch (act) {
- case InternalTokenNameIdentifier :
- return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- case TokenNameabstract :
- return "abstract"; //$NON-NLS-1$
-//{ObjectTeams: deal with OT-specific identifiers
- case TokenNameas :
- return "as"; //$NON-NLS-1$
- case TokenNamecallin :
- return "callin"; //$NON-NLS-1$
- case TokenNameplayedBy :
- return "playedBy"; //$NON-NLS-1$
- case TokenNameprecedence :
- return "precedence"; //$NON-NLS-1$
- case TokenNameteam :
- return "team"; //$NON-NLS-1$
- case TokenNamewith :
- return "with"; //$NON-NLS-1$
- case TokenNamewithin :
- return "within"; //$NON-NLS-1$
- case TokenNamereplace:
- return "replace"; //$NON-NLS-1$
- case TokenNamebefore:
- return "before"; //$NON-NLS-1$
- case TokenNameafter:
- return "after"; //$NON-NLS-1$
- case TokenNameget:
- return "get"; //$NON-NLS-1$
- case TokenNameset:
- return "set"; //$NON-NLS-1$
-// Markus Witte}
- case TokenNameboolean :
- return "boolean"; //$NON-NLS-1$
- case TokenNamebreak :
- return "break"; //$NON-NLS-1$
- case TokenNamebyte :
- return "byte"; //$NON-NLS-1$
- case TokenNamecase :
- return "case"; //$NON-NLS-1$
- case TokenNamecatch :
- return "catch"; //$NON-NLS-1$
- case TokenNamechar :
- return "char"; //$NON-NLS-1$
- case TokenNameclass :
- return "class"; //$NON-NLS-1$
- case TokenNamecontinue :
- return "continue"; //$NON-NLS-1$
- case TokenNamedefault :
- return "default"; //$NON-NLS-1$
- case TokenNamedo :
- return "do"; //$NON-NLS-1$
- case TokenNamedouble :
- return "double"; //$NON-NLS-1$
- case TokenNameelse :
- return "else"; //$NON-NLS-1$
- case TokenNameextends :
- return "extends"; //$NON-NLS-1$
- case TokenNamefalse :
- return "false"; //$NON-NLS-1$
- case TokenNamefinal :
- return "final"; //$NON-NLS-1$
- case TokenNamefinally :
- return "finally"; //$NON-NLS-1$
- case TokenNamefloat :
- return "float"; //$NON-NLS-1$
- case TokenNamefor :
- return "for"; //$NON-NLS-1$
- case TokenNameif :
- return "if"; //$NON-NLS-1$
- case TokenNameimplements :
- return "implements"; //$NON-NLS-1$
- case TokenNameimport :
- return "import"; //$NON-NLS-1$
- case TokenNameinstanceof :
- return "instanceof"; //$NON-NLS-1$
- case TokenNameint :
- return "int"; //$NON-NLS-1$
- case TokenNameinterface :
- return "interface"; //$NON-NLS-1$
- case TokenNamelong :
- return "long"; //$NON-NLS-1$
- case TokenNamenative :
- return "native"; //$NON-NLS-1$
- case TokenNamenew :
- return "new"; //$NON-NLS-1$
- case TokenNamenull :
- return "null"; //$NON-NLS-1$
- case TokenNamepackage :
- return "package"; //$NON-NLS-1$
- case TokenNameprivate :
- return "private"; //$NON-NLS-1$
- case TokenNameprotected :
- return "protected"; //$NON-NLS-1$
- case TokenNamepublic :
- return "public"; //$NON-NLS-1$
- case TokenNamereturn :
- return "return"; //$NON-NLS-1$
- case TokenNameshort :
- return "short"; //$NON-NLS-1$
- case TokenNamestatic :
- return "static"; //$NON-NLS-1$
- case TokenNamesuper :
- return "super"; //$NON-NLS-1$
- case TokenNameswitch :
- return "switch"; //$NON-NLS-1$
- case TokenNamesynchronized :
- return "synchronized"; //$NON-NLS-1$
- case TokenNamethis :
- return "this"; //$NON-NLS-1$
- case TokenNamethrow :
- return "throw"; //$NON-NLS-1$
- case TokenNamethrows :
- return "throws"; //$NON-NLS-1$
- case TokenNametransient :
- return "transient"; //$NON-NLS-1$
- case TokenNametrue :
- return "true"; //$NON-NLS-1$
- case TokenNametry :
- return "try"; //$NON-NLS-1$
- case TokenNamevoid :
- return "void"; //$NON-NLS-1$
- case TokenNamevolatile :
- return "volatile"; //$NON-NLS-1$
- case TokenNamewhile :
- return "while"; //$NON-NLS-1$
-
- case TokenNameIntegerLiteral :
- return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- case TokenNameLongLiteral :
- return "Long(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- case TokenNameFloatingPointLiteral :
- return "Float(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- case TokenNameDoubleLiteral :
- return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- case TokenNameCharacterLiteral :
- return "Char(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- case TokenNameStringLiteral :
- return "String(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
-
- case TokenNamePLUS_PLUS :
- return "++"; //$NON-NLS-1$
- case TokenNameMINUS_MINUS :
- return "--"; //$NON-NLS-1$
- case TokenNameEQUAL_EQUAL :
- return "=="; //$NON-NLS-1$
-//{ObjectTeams: deal with callins/callouts
- case TokenNameBINDIN :
- return "<-"; //$NON-NLS-1$
- case TokenNameBINDOUT :
- return "->"; //$NON-NLS-1$
- case TokenNameCALLOUT_OVERRIDE :
- return "=>"; //$NON-NLS-1$
-// Markus Witte}
- case TokenNameLESS_EQUAL :
- return "<="; //$NON-NLS-1$
- case TokenNameGREATER_EQUAL :
- return ">="; //$NON-NLS-1$
- case TokenNameNOT_EQUAL :
- return "!="; //$NON-NLS-1$
- case TokenNameLEFT_SHIFT :
- return "<<"; //$NON-NLS-1$
- case TokenNameRIGHT_SHIFT :
- return ">>"; //$NON-NLS-1$
- case TokenNameUNSIGNED_RIGHT_SHIFT :
- return ">>>"; //$NON-NLS-1$
- case TokenNamePLUS_EQUAL :
- return "+="; //$NON-NLS-1$
- case TokenNameMINUS_EQUAL :
- return "-="; //$NON-NLS-1$
- case TokenNameARROW :
- return "->"; //$NON-NLS-1$
- case TokenNameMULTIPLY_EQUAL :
- return "*="; //$NON-NLS-1$
- case TokenNameDIVIDE_EQUAL :
- return "/="; //$NON-NLS-1$
- case TokenNameAND_EQUAL :
- return "&="; //$NON-NLS-1$
- case TokenNameOR_EQUAL :
- return "|="; //$NON-NLS-1$
- case TokenNameXOR_EQUAL :
- return "^="; //$NON-NLS-1$
- case TokenNameREMAINDER_EQUAL :
- return "%="; //$NON-NLS-1$
- case TokenNameLEFT_SHIFT_EQUAL :
- return "<<="; //$NON-NLS-1$
- case TokenNameRIGHT_SHIFT_EQUAL :
- return ">>="; //$NON-NLS-1$
- case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL :
- return ">>>="; //$NON-NLS-1$
- case TokenNameOR_OR :
- return "||"; //$NON-NLS-1$
- case TokenNameAND_AND :
- return "&&"; //$NON-NLS-1$
- case TokenNamePLUS :
- return "+"; //$NON-NLS-1$
- case TokenNameMINUS :
- return "-"; //$NON-NLS-1$
- case TokenNameNOT :
- return "!"; //$NON-NLS-1$
- case TokenNameREMAINDER :
- return "%"; //$NON-NLS-1$
- case TokenNameXOR :
- return "^"; //$NON-NLS-1$
- case TokenNameAND :
- return "&"; //$NON-NLS-1$
- case TokenNameMULTIPLY :
- return "*"; //$NON-NLS-1$
- case TokenNameOR :
- return "|"; //$NON-NLS-1$
- case TokenNameTWIDDLE :
- return "~"; //$NON-NLS-1$
- case TokenNameDIVIDE :
- return "/"; //$NON-NLS-1$
- case TokenNameGREATER :
- return ">"; //$NON-NLS-1$
- case TokenNameLESS :
- return "<"; //$NON-NLS-1$
- case TokenNameLPAREN :
- return "("; //$NON-NLS-1$
- case TokenNameRPAREN :
- return ")"; //$NON-NLS-1$
- case TokenNameLBRACE :
- return "{"; //$NON-NLS-1$
- case TokenNameRBRACE :
- return "}"; //$NON-NLS-1$
- case TokenNameLBRACKET :
- return "["; //$NON-NLS-1$
- case TokenNameRBRACKET :
- return "]"; //$NON-NLS-1$
- case TokenNameSEMICOLON :
- return ";"; //$NON-NLS-1$
- case TokenNameQUESTION :
- return "?"; //$NON-NLS-1$
- case TokenNameCOLON :
- return ":"; //$NON-NLS-1$
- case TokenNameCOLON_COLON :
- return "::"; //$NON-NLS-1$
- case TokenNameCOMMA :
- return ","; //$NON-NLS-1$
- case TokenNameDOT :
- return "."; //$NON-NLS-1$
- case TokenNameEQUAL :
- return "="; //$NON-NLS-1$
- case TokenNameEOF :
- return "EOF"; //$NON-NLS-1$
- case TokenNameWHITESPACE :
- return "white_space(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- default :
- return "not-a-token"; //$NON-NLS-1$
- }
-}
-public void unicodeInitializeBuffer(int length) {
- this.withoutUnicodePtr = length;
- if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[length+(1+10)];
- int bLength = this.withoutUnicodeBuffer.length;
- if (1+length >= bLength) {
- System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length + (1+10)], 0, bLength);
- }
- System.arraycopy(this.source, this.startPosition, this.withoutUnicodeBuffer, 1, length);
-}
-public void unicodeStore() {
- int pos = ++this.withoutUnicodePtr;
- if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10];
- int length = this.withoutUnicodeBuffer.length;
- if (pos == length) {
- System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length);
- }
- this.withoutUnicodeBuffer[pos] = this.currentCharacter;
-}
-public void unicodeStore(char character) {
- int pos = ++this.withoutUnicodePtr;
- if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10];
- int length = this.withoutUnicodeBuffer.length;
- if (pos == length) {
- System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length);
- }
- this.withoutUnicodeBuffer[pos] = character;
-}
-
-public static boolean isIdentifier(int token) {
- return token == TerminalTokens.TokenNameIdentifier;
-}
-
-public static boolean isLiteral(int token) {
- switch(token) {
- case TerminalTokens.TokenNameIntegerLiteral:
- case TerminalTokens.TokenNameLongLiteral:
- case TerminalTokens.TokenNameFloatingPointLiteral:
- case TerminalTokens.TokenNameDoubleLiteral:
- case TerminalTokens.TokenNameStringLiteral:
- case TerminalTokens.TokenNameTextBlock:
- case TerminalTokens.TokenNameCharacterLiteral:
- return true;
- default:
- return false;
+ @Override
+ public String toString() {
+ return this.delegate.toString();
}
-}
-public static boolean isKeyword(int token) {
- switch(token) {
- case TerminalTokens.TokenNameabstract:
- case TerminalTokens.TokenNameassert:
- case TerminalTokens.TokenNamebyte:
- case TerminalTokens.TokenNamebreak:
- case TerminalTokens.TokenNameboolean:
- case TerminalTokens.TokenNamecase:
- case TerminalTokens.TokenNamechar:
- case TerminalTokens.TokenNamecatch:
- case TerminalTokens.TokenNameclass:
- case TerminalTokens.TokenNamecontinue:
- case TerminalTokens.TokenNamedo:
- case TerminalTokens.TokenNamedouble:
- case TerminalTokens.TokenNamedefault:
- case TerminalTokens.TokenNameelse:
- case TerminalTokens.TokenNameextends:
- case TerminalTokens.TokenNamefor:
- case TerminalTokens.TokenNamefinal:
- case TerminalTokens.TokenNamefloat:
- case TerminalTokens.TokenNamefalse:
- case TerminalTokens.TokenNamefinally:
- case TerminalTokens.TokenNameif:
- case TerminalTokens.TokenNameint:
- case TerminalTokens.TokenNameimport:
- case TerminalTokens.TokenNameinterface:
- case TerminalTokens.TokenNameimplements:
- case TerminalTokens.TokenNameinstanceof:
- case TerminalTokens.TokenNamelong:
- case TerminalTokens.TokenNamenew:
- case TerminalTokens.TokenNamenon_sealed:
- case TerminalTokens.TokenNamenull:
- case TerminalTokens.TokenNamenative:
- case TerminalTokens.TokenNamepublic:
- case TerminalTokens.TokenNamepackage:
- case TerminalTokens.TokenNameprivate:
- case TerminalTokens.TokenNameprotected:
- case TerminalTokens.TokenNamereturn:
- case TerminalTokens.TokenNameshort:
- case TerminalTokens.TokenNamesuper:
- case TerminalTokens.TokenNamestatic:
- case TerminalTokens.TokenNameswitch:
- case TerminalTokens.TokenNamestrictfp:
- case TerminalTokens.TokenNamesynchronized:
- case TerminalTokens.TokenNametry:
- case TerminalTokens.TokenNamethis:
- case TerminalTokens.TokenNametrue:
- case TerminalTokens.TokenNamethrow:
- case TerminalTokens.TokenNamethrows:
- case TerminalTokens.TokenNametransient:
- case TerminalTokens.TokenNamevoid:
- case TerminalTokens.TokenNamevolatile:
- case TerminalTokens.TokenNamewhile:
- return true;
- default:
- return false;
- }
-}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java
index bcac151..ca92268 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2013 IBM Corporation and others.
+ * Copyright (c) 2011, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -16,13 +16,14 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-
import java.net.MalformedURLException;
import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.internal.core.util.Util;
/**
* The location of the index files are represented as {@link IndexLocation}
@@ -55,6 +56,7 @@
}
private final URL url; // url of the given index location
+ private final URI uri; // uri of the given index location
/**
* Set to true if this index location is of an index file specified
@@ -65,16 +67,28 @@
protected IndexLocation(File file) {
URL tempUrl = null;
+ URI tempUri = null;
try {
- tempUrl = file.toURI().toURL();
+ tempUri = file.toURI();
+ tempUrl = tempUri.toURL();
} catch (MalformedURLException e) {
// should not happen
+ Util.log(e, "Unexpected uri to url failure"); //$NON-NLS-1$
}
this.url = tempUrl;
+ this.uri = tempUri;
}
public IndexLocation(URL url) {
this.url = url;
+ URI tempUri = null;
+ try {
+ tempUri = url.toURI();
+ } catch (URISyntaxException e) {
+ // should not happen
+ Util.log(e, "Unexpected url to uri failure"); //$NON-NLS-1$
+ }
+ this.uri = tempUri;
}
/**
@@ -110,9 +124,13 @@
return this.url;
}
+ public URI getUri() {
+ return this.uri;
+ }
+
@Override
public int hashCode() {
- return this.url.hashCode();
+ return this.uri != null ? this.uri.hashCode() : this.url.hashCode();
}
public boolean isParticipantIndex() {
@@ -133,6 +151,6 @@
@Override
public String toString() {
- return this.url.toString();
+ return this.uri.toString();
}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java
index c2aa864..3a11cf4 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011 IBM Corporation and others.
+ * Copyright (c) 2011, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -17,7 +17,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
+import java.net.URISyntaxException;
import java.net.URL;
+import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -59,7 +61,11 @@
@Override
public boolean equals(Object other) {
if (!(other instanceof JarIndexLocation)) return false;
- return this.localUrl.equals(((JarIndexLocation) other).localUrl);
+ try {
+ return Objects.equals(this.localUrl.toURI(),((JarIndexLocation) other).localUrl.toURI());
+ } catch (URISyntaxException e) {
+ return false;
+ }
}
@Override
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
index 9e7a8f2..c725686 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -18,6 +18,7 @@
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
+import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,6 +29,7 @@
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -296,8 +298,13 @@
// an existing index location exists - make sure it has not changed (i.e. the URL has not changed)
URL existingURL = indexLocation.getUrl();
if (newIndexURL != null) {
- // if either URL is different then the index location has been updated so rebuild.
- if(!newIndexURL.equals(existingURL)) {
+ boolean urisarequal = false;
+ try {
+ urisarequal = Objects.equals(newIndexURL.toURI(), existingURL.toURI());
+ } catch (URISyntaxException e) {
+ // ignore missing RFC 2396 compliance
+ }
+ if(!urisarequal) {
// URL has changed so remove the old index and create a new one
this.removeIndex(containerPath);
// create a new one
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
index 490ce51..fd34337 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
@@ -36,7 +36,7 @@
/* background processing */
protected volatile Thread processingThread;
- protected Job progressJob;
+ protected volatile Job progressJob;
/* counter indicating whether job execution is enabled or not, disabled if <= 0
it cannot go beyond 1 */
@@ -392,6 +392,8 @@
}
job = currentJob();
}
+ //make sure next index job will schedule new ProgressJob:
+ JobManager.this.progressJob = null;
return Status.OK_STATUS;
}
}
@@ -405,8 +407,9 @@
// must check for new job inside this sync block to avoid timing hole
if ((job = currentJob()) == null) {
- if (this.progressJob != null) {
- this.progressJob.cancel();
+ Job pJob = this.progressJob;
+ if (pJob != null) {
+ pJob.cancel();
this.progressJob = null;
}
if (idlingStart < 0)
@@ -433,10 +436,11 @@
try {
this.executing = true;
if (this.progressJob == null) {
- this.progressJob = new ProgressJob(Messages.bind(Messages.jobmanager_indexing, "", "")); //$NON-NLS-1$ //$NON-NLS-2$
- this.progressJob.setPriority(Job.LONG);
- this.progressJob.setSystem(true);
- this.progressJob.schedule();
+ ProgressJob pJob = new ProgressJob(Messages.bind(Messages.jobmanager_indexing, "", "")); //$NON-NLS-1$ //$NON-NLS-2$
+ pJob.setPriority(Job.LONG);
+ pJob.setSystem(true);
+ pJob.schedule();
+ this.progressJob = pJob;
}
/*boolean status = */job.execute(null);
//if (status == FAILED) request(job);