diff options
author | Olivier Thomann | 2007-07-05 13:54:21 +0000 |
---|---|---|
committer | Olivier Thomann | 2007-07-05 13:54:21 +0000 |
commit | ccd12469d7fc21a8e1a0a597451a059df56002ad (patch) | |
tree | 523e581ca9d698174267a2280a1922d10a03788c | |
parent | 4b460199498c48cda44ce10125aa5901a10bff62 (diff) | |
download | eclipse.jdt.core-ccd12469d7fc21a8e1a0a597451a059df56002ad.tar.gz eclipse.jdt.core-ccd12469d7fc21a8e1a0a597451a059df56002ad.tar.xz eclipse.jdt.core-ccd12469d7fc21a8e1a0a597451a059df56002ad.zip |
HEAD - Fixes for 192774, 189799 and 191082
20 files changed, 1490 insertions, 610 deletions
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationCodeExample.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationCodeExample.java index 92086784d7..a1048b0e63 100644 --- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationCodeExample.java +++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationCodeExample.java @@ -24,18 +24,27 @@ public class MirrorDeclarationCodeExample "import org.eclipse.jdt.apt.tests.annotations.mirrortest.MirrorDeclarationTestAnnotation;" + "\n" + "@MirrorDeclarationTestAnnotation(s=\"fred\", value=5)" + "\n" + "public class DeclarationTestClass {" + "\n" + - " public class ClassDec {" + "\n" + - " public ClassDec() {}" + "\n" + - " public ClassDec(int j) {}" + "\n" + - " public static final int i = 1;" + "\n" + - " public float f;" + "\n" + - " public static final String s = \"hello\";" + "\n" + - " public java.util.GregorianCalendar gc;" + "\n" + - " public void methodDec(int k, String... t) throws Exception {}" + "\n" + - " public void methodDecNoArg(){}" + "\n" + - " }" + "\n" + - " public enum EnumDec {" + "\n" + - " aardvark, anteater" + "\n" + - " }" + "\n" + + " public class ClassDec {" + "\n" + + " public ClassDec() {}" + "\n" + + " public ClassDec(int j) {}" + "\n" + + " public static final int i = 1;" + "\n" + + " public float f;" + "\n" + + " public static final String s = \"hello\";" + "\n" + + " public java.util.GregorianCalendar gc;" + "\n" + + " public void methodDec(int k, String... t) throws Exception {}" + "\n" + + " public void methodDecNoArg(){}" + "\n" + + " @MirrorDeclarationTestAnnotation() public Object foo(Object o) throws Exception {\n" + + " return null;\n" + + " }\n" + + " @MirrorDeclarationTestAnnotation() public Object foo2(Object o) throws Exception {\n" + + " return null;\n" + + " }\n" + + " @MirrorDeclarationTestAnnotation() public Object foo3(Object o) throws Exception {\n" + + " return null;\n" + + " }\n" + + " }" + "\n" + + " public enum EnumDec {" + "\n" + + " aardvark, anteater" + "\n" + + " }" + "\n" + "}"; } diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationTestAnnotationProcessor.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationTestAnnotationProcessor.java index e5887a90ff..ab76849d76 100644 --- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationTestAnnotationProcessor.java +++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/annotations/mirrortest/MirrorDeclarationTestAnnotationProcessor.java @@ -25,6 +25,7 @@ package org.eclipse.jdt.apt.tests.annotations.mirrortest; import java.util.Collection; +import java.util.HashSet; import org.eclipse.jdt.apt.tests.annotations.BaseProcessor; import org.eclipse.jdt.apt.tests.annotations.ProcessorTestStatus; @@ -159,14 +160,21 @@ public class MirrorDeclarationTestAnnotationProcessor extends BaseProcessor { ProcessorTestStatus.assertTrue("constructor with one (int) arg", constructIntArg != null); Collection<MethodDeclaration> methodDecls = testClassDec.getMethods(); - ProcessorTestStatus.assertEquals("Number of methods", 2, methodDecls.size()); + ProcessorTestStatus.assertEquals("Number of methods", 5, methodDecls.size()); + HashSet<AnnotationMirror> annotationMirrors = new HashSet<AnnotationMirror>(); + for (MethodDeclaration methodDeclaration : methodDecls) { + Collection<AnnotationMirror> mirrors = methodDeclaration.getAnnotationMirrors(); + annotationMirrors.addAll(mirrors); + } + ProcessorTestStatus.assertEquals("Wrong size for annotation mirrors", 3, annotationMirrors.size()); + MethodDeclaration methodDecl = null; methodDecl = methodDecls.iterator().next(); ProcessorTestStatus.assertTrue("method declaration exists", methodDecl != null); ClassType superClass = testClassDec.getSuperclass(); - ProcessorTestStatus.assertEquals("Object is only super", "java.lang.Object", superClass.toString()); + ProcessorTestStatus.assertEquals("Object is only super", "java.lang.Object", superClass.toString()); } /** diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar Binary files differindex 6681fff6b2..cec6739166 100644 --- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar +++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar diff --git a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elementutils/ElementUtilsProc.java b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elementutils/ElementUtilsProc.java index ace386f43b..cebde2e875 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elementutils/ElementUtilsProc.java +++ b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elementutils/ElementUtilsProc.java @@ -452,13 +452,40 @@ public class ElementUtilsProc extends BaseProcessor nameToDoc.put("F", " Javadoc on element F\n @param <T1> a type parameter\n"); nameToDoc.put("FChild", " Javadoc on nested element FChild\n"); nameToDoc.put("FEnum", " Javadoc on nested enum FEnum\n Two lines long\n"); - nameToDoc.put("FChildI", " Javadoc on nested interface FChildI\n"); + nameToDoc.put("FChildI", + " Javadoc on nested interface FChildI\n" + + "\tthis line has tab after asterisk and ends with another tab\t\n" + + "\tthis one too\t\n" + + " this line has three spaces after asterisk and ends with three spaces \n" + + " this line has only one space before the asterisk\n"); nameToDoc.put("_fieldT1_protected", "Javadoc on field _fieldT1_protected, inline format "); + nameToDoc.put("_fieldT1_private", + "\n" + + " Javadoc on _fieldT1_private\n" + + " this line starts with two spaces, no asterisk\n" + + " This line starts, contains\tand ends with a tab\t\n" + + " This line starts with a space, tab, space, tab, space\n"); nameToDoc.put("fieldInt", null); nameToDoc.put("method_T1", " Javadoc on F.method_T1\n"); nameToDoc.put("method_String", null); + nameToDoc.put("getAnonymousObjectAbstract", ""); + nameToDoc.put("add", "\n @add(int)\n"); + nameToDoc.put("foo", "\n Creates a new instance of AllChecks \n"); + nameToDoc.put("bar", " @bar\t(int)\n"); + nameToDoc.put("bar2", "\t@bar2(int)\n"); + nameToDoc.put("m", " Method\tm\n"); + nameToDoc.put("m1", "This is a comment for the method m1,\n" + + " it is on two lines\n"); + nameToDoc.put("m2", "Another comment - starts on first line and\n" + + " continue on the second line "); + nameToDoc.put("m3", " One more test case that.\n" + + " needs\n" + + " to be verified.\n" + + "\n" + + " An empty line with no spaces need to be seen as an empty line.\n" + + "\n" + + " End of the comment.\n"); - String actual = _elementUtils.getDocComment(_elementF); String expected = nameToDoc.get("F"); if (!expected.equals(actual)) { @@ -471,12 +498,12 @@ public class ElementUtilsProc extends BaseProcessor actual = _elementUtils.getDocComment(e); expected = nameToDoc.get(name); if (expected == null && actual != null) { - reportError("examineGetDocComment: Expected getDocComment(" + name + ") to return null, but got " + actual); + reportError("examineGetDocComment: Expected getDocComment(" + name + ") to return null, but got " + _elementUtils.getDocComment(e)); return false; } else if (expected != null) { if (!expected.equals(actual)) { - reportError("examineGetDocComment: Unexpected result from getDocComment(" + name + "): " + actual); + reportError("examineGetDocComment: Unexpected result from getDocComment(" + name + "): " + _elementUtils.getDocComment(e)); return false; } } diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/targets/model/pc/F.java b/org.eclipse.jdt.compiler.apt.tests/resources/targets/model/pc/F.java index b4f7299fa1..bd736cdd34 100644 --- a/org.eclipse.jdt.compiler.apt.tests/resources/targets/model/pc/F.java +++ b/org.eclipse.jdt.compiler.apt.tests/resources/targets/model/pc/F.java @@ -5,6 +5,13 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// CAUTION! THIS FILE CONTAINS SPECIFIC COMBINATIONS OF TABS AND SPACES, +// FOR TESTING WHITESPACE HANDLING IN JAVADOC. DO NOT REFORMAT OR MODIFY +// WHITESPACE IN ANY JAVADOC IN THIS FILE. +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + package targets.model.pc; /** @@ -27,12 +34,23 @@ public class F<T1> { /** * Javadoc on nested interface FChildI + * this line has tab after asterisk and ends with another tab + * this one too + * this line has three spaces after asterisk and ends with three spaces + * this line has only one space before the asterisk */ public interface FChildI {} /** Javadoc on field _fieldT1_protected, inline format */ protected T1 _fieldT1_protected; + // Next line has a space at the end, after the double asterisks + /** + * Javadoc on _fieldT1_private + this line starts with two spaces, no asterisk + This line starts, contains and ends with a tab + This line starts with a space, tab, space, tab, space + */ private T1 _fieldT1_private; int fieldInt; @@ -70,4 +88,60 @@ public class F<T1> { // unrelated to the same-signature methods in Overriding.java void f() {} + + /************************/ + /*** Abstract methods ***/ + /************************/ + + public Object getAnonymousObjectAbstract() { + return null; + } + + /** + * @add(int) + */ + int add (int j) { + return j + j; + } + + /** + * Creates a new instance of AllChecks + */ + public void foo() { + } + + /** + * @bar (int) + */ + int bar(int i) { return i; } + + /** + * @bar2(int) + */ + int bar2(int i) { return i; } + +/** + Method m + */ + void m() {} + + /** This is a comment for the method m1, + * it is on two lines + */ + void m1() {} + + /** Another comment - starts on first line and + continue on the second line */ + void m2() {} + + /** + * One more test case that. + * needs + * to be verified. + * + * An empty line with no spaces need to be seen as an empty line. + * + * End of the comment. + */ + void m3() {} }
\ No newline at end of file diff --git a/org.eclipse.jdt.compiler.apt/META-INF/MANIFEST.MF b/org.eclipse.jdt.compiler.apt/META-INF/MANIFEST.MF index 777b6d6983..2d0602ba67 100644 --- a/org.eclipse.jdt.compiler.apt/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.compiler.apt/META-INF/MANIFEST.MF @@ -5,7 +5,7 @@ Bundle-SymbolicName: org.eclipse.jdt.compiler.apt Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-Vendor: %providerName -Fragment-Host: org.eclipse.jdt.core;bundle-version="3.3.0" +Fragment-Host: org.eclipse.jdt.core;bundle-version="[3.3.0,4.0.0)" Bundle-Localization: compiler_apt_fragment Eclipse-LazyStart: true Export-Package: org.eclipse.jdt.internal.compiler.apt.dispatch;x-friends:="org.eclipse.jdt.apt.pluggable.core", diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java index 8366a6117a..a466bcdab6 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java @@ -48,7 +48,7 @@ public class BatchProcessingEnvImpl extends BaseProcessingEnvImpl { _dispatchManager = dispatchManager; Class<?> c = null; try { - c = Class.forName("org.eclipse.jdt.internal.compiler.tool.EclipseCompiler"); //$NON-NLS-1$ + c = Class.forName("org.eclipse.jdt.internal.compiler.tool.EclipseCompilerImpl"); //$NON-NLS-1$ } catch (ClassNotFoundException e) { // ignore } @@ -79,7 +79,7 @@ public class BatchProcessingEnvImpl extends BaseProcessingEnvImpl { } else { String encoding = (String) batchCompiler.options.get(CompilerOptions.OPTION_Encoding); Charset charset = encoding != null ? Charset.forName(encoding) : null; - JavaFileManager manager = new EclipseFileManager(batchCompiler, batchCompiler.compilerLocale, charset); + JavaFileManager manager = new EclipseFileManager(batchCompiler.compilerLocale, charset); ArrayList<String> options = new ArrayList<String>(); for (String argument : commandLineArguments) { options.add(argument); diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/AnnotationMirrorImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/AnnotationMirrorImpl.java index f03c090fef..71568bb63e 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/AnnotationMirrorImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/AnnotationMirrorImpl.java @@ -56,11 +56,42 @@ public class AnnotationMirrorImpl implements AnnotationMirror, InvocationHandler if (this._binding == null) { return ((AnnotationMirrorImpl) obj)._binding == null; } - return this._binding.equals(((AnnotationMirrorImpl) obj)._binding); + return equals(this._binding, ((AnnotationMirrorImpl) obj)._binding); } return false; } + private static boolean equals(AnnotationBinding annotationBinding, AnnotationBinding annotationBinding2) { + if (annotationBinding.getAnnotationType() != annotationBinding2.getAnnotationType()) return false; + final ElementValuePair[] elementValuePairs = annotationBinding.getElementValuePairs(); + final ElementValuePair[] elementValuePairs2 = annotationBinding2.getElementValuePairs(); + final int length = elementValuePairs.length; + if (length != elementValuePairs2.length) return false; + loop: for (int i = 0; i < length; i++) { + ElementValuePair pair = elementValuePairs[i]; + // loop on the given pair to make sure one will match + for (int j = 0; j < length; j++) { + ElementValuePair pair2 = elementValuePairs2[j]; + if (pair.binding == pair2.binding) { + if (pair.value == null) { + if (pair2.value == null) { + continue loop; + } + return false; + } else { + if (pair2.value == null + || !pair2.value.equals(pair.value)) { + return false; + } + } + continue loop; + } + } + return false; + } + return true; + } + public DeclaredType getAnnotationType() { if (this._binding == null) { return _env.getFactory().getErrorType(); diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java index 22a03bf464..559872c4ae 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2007 BEA Systems, Inc. + * Copyright (c) 2006, 2007 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,7 +7,7 @@ * * Contributors: * wharley@bea.com - initial API and implementation - * + * *******************************************************************************/ package org.eclipse.jdt.internal.compiler.apt.model; @@ -61,13 +61,10 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; public class ElementsImpl implements Elements { // Used for parsing Javadoc comments: matches initial delimiter, followed by whitespace - private static final Pattern INITIAL_DELIMITER = Pattern.compile("^\\s*/\\*\\*\\s*"); //$NON-NLS-1$ - // Used for parsing Javadoc comments: matches initial whitespace followed by one or more stars - private static final Pattern INITIAL_WHITESPACE_STARS = Pattern.compile("^\\s*\\*+"); //$NON-NLS-1$ + private static final Pattern INITIAL_DELIMITER = Pattern.compile("^\\s*/\\*+"); //$NON-NLS-1$ - private final BaseProcessingEnvImpl _env; - + /* * The processing env creates and caches an ElementsImpl. Other clients should * not create their own; they should ask the env for it. @@ -93,7 +90,7 @@ public class ElementsImpl implements Elements { while (null != binding) { for (AnnotationBinding annotation : binding.getAnnotations()) { if (annotation == null) continue; - ReferenceBinding annotationType = annotation.getAnnotationType(); + ReferenceBinding annotationType = annotation.getAnnotationType(); if (!annotationTypes.contains(annotationType)) { annotationTypes.add(annotationType); annotations.add(annotation); @@ -116,14 +113,14 @@ public class ElementsImpl implements Elements { * Compute a list of all the visible entities in this type. Specifically: * <ul> * <li>All nested types declared in this type, including interfaces and enums</li> - * <li>All protected or public nested types declared in this type's superclasses + * <li>All protected or public nested types declared in this type's superclasses * and superinterfaces, that are not hidden by a name collision</li> * <li>All methods declared in this type, including constructors but not * including static or instance initializers, and including abstract * methods and unimplemented methods declared in interfaces</li> * <li>All protected or public methods declared in this type's superclasses, * that are not overridden by another method, but not including constructors - * or initializers. Includes abstract methods and methods declared in + * or initializers. Includes abstract methods and methods declared in * superinterfaces but not implemented</li> * <li>All fields declared in this type, including constants</li> * <li>All non-private fields declared in this type's superclasses and @@ -169,7 +166,7 @@ public class ElementsImpl implements Elements { } return allMembers; } - + /** * Recursively depth-first walk the tree of superinterfaces of a type, collecting * all the unique superinterface bindings. (Note that because of generics, a type may @@ -178,7 +175,7 @@ public class ElementsImpl implements Elements { * @param existing bindings already in this set will not be re-added or recursed into * @param newfound newly found bindings will be added to this set */ - private void collectSuperInterfaces(ReferenceBinding type, + private void collectSuperInterfaces(ReferenceBinding type, Set<ReferenceBinding> existing, Set<ReferenceBinding> newfound) { for (ReferenceBinding superinterface : type.superInterfaces()) { if (!existing.contains(superinterface) && !newfound.contains(superinterface)) { @@ -190,7 +187,7 @@ public class ElementsImpl implements Elements { /** * Add the members of a type to the maps of subtypes, fields, and methods. Add only those - * which are non-private and which are not overridden by an already-discovered member. + * which are non-private and which are not overridden by an already-discovered member. * For fields, add them all; javac implementation does not take field hiding into account. * @param binding the type whose members will be added to the lists * @param ignoreVisibility if true, all members will be added regardless of whether they @@ -222,7 +219,7 @@ public class ElementsImpl implements Elements { if (null == sameNamedMethods) { // New method name. Create a set for it and add it to the list. // We don't expect many methods with same name, so only 4 slots: - sameNamedMethods = new HashSet<MethodBinding>(4); + sameNamedMethods = new HashSet<MethodBinding>(4); methods.put(methodName, sameNamedMethods); sameNamedMethods.add(method); } @@ -359,7 +356,7 @@ public class ElementsImpl implements Elements { /** * Strip the comment characters from a javadoc comment. Assume the comment is already * missing its closing delimiter. - * + * * We mainly do not attempt to emulate the baroque behavior of javac with respect to * treatment of whitespace. The rules here are simpler: eliminate the opening and * closing delimiter, and eliminate [whitespace plus stars] at the beginning of each @@ -369,12 +366,12 @@ public class ElementsImpl implements Elements { * after the delimiter, but no non-whitespace chars, then delete the whitespace but * preserve the newline; and so forth. */ - public static String formatJavadoc(char[] unparsed) + private static String formatJavadoc(char[] unparsed) { if (unparsed == null || unparsed.length < 5) { // delimiters take 5 chars return null; } - + String[] lines = new String(unparsed).split("\n"); //$NON-NLS-1$ Matcher delimiterMatcher = INITIAL_DELIMITER.matcher(lines[0]); if (!delimiterMatcher.find()) { @@ -384,44 +381,129 @@ public class ElementsImpl implements Elements { lines[0] = lines[0].substring(iOpener); if (lines.length == 1) { // single-line comment. Should trim(), but javac doesn't. - return lines[0]; - } - - int firstLine = lines[0].trim().length() > 0 ? 0 : 1; - - // for each line after the first, including the last, if it starts with whitespace - // followed by stars, skip all that. - for (int line = 1; line < lines.length; ++line) { - Matcher whitespaceMatcher = INITIAL_WHITESPACE_STARS.matcher(lines[line]); - if (whitespaceMatcher.find()) { - int firstAfterStars = whitespaceMatcher.end(); - lines[line] = lines[line].substring(firstAfterStars); + // we should however remove the starting whitespaces + StringBuilder sb = new StringBuilder(); + char[] chars = lines[0].toCharArray(); + boolean startingWhitespaces = true; + for (char c : chars) { + if (Character.isWhitespace(c)) + if (startingWhitespaces) { + continue; + } else { + sb.append(c); + } else { + startingWhitespaces = false; + sb.append(c); + } } + return sb.toString(); } - + + // if the first line ends with spaces after the /** then we want to insert a line separator + int firstLine = lines[0].trim().length() > 0 ? 0 : 1; + // If the last line is now empty, skip it int lastLine = lines[lines.length - 1].trim().length() > 0 ? lines.length - 1 : lines.length - 2; - + StringBuilder sb = new StringBuilder(); + if (lines[0].length() != 0 && firstLine == 1) { + // insert a line separator only if the remaining chars on the line are whitespaces + sb.append('\n'); + } + boolean preserveLineSeparator = lines[0].length() == 0; for (int line = firstLine; line <= lastLine; ++line) { char[] chars = lines[line].toCharArray(); - for (char c : chars) { - if (c == '\t') { - for (int i = 0; i < 8; i++) { - sb.append(' '); - } - } else { - sb.append(c); + int starsIndex = getStars(chars); + int leadingWhitespaces = 0; + boolean recordLeadingWhitespaces = true; + for (int i = 0, max = chars.length; i < max; i++) { + char c = chars[i]; + switch(c) { + case '\t' : + if (starsIndex == -1) { + if (recordLeadingWhitespaces) { + leadingWhitespaces += 8; + } else { + sb.append(c); + } + } else if (i >= starsIndex) { + sb.append(c); + } + break; + case ' ' : + if (starsIndex == -1) { + if (recordLeadingWhitespaces) { + leadingWhitespaces++; + } else { + sb.append(c); + } + } else if (i >= starsIndex) { + sb.append(c); + } + break; + default : + // convert leadingwhitespaces to spaces + recordLeadingWhitespaces = false; + if (leadingWhitespaces != 0) { + int numberOfTabs = leadingWhitespaces / 8; + if (numberOfTabs != 0) { + for (int j = 0, max2 = numberOfTabs; j < max2; j++) { + sb.append(" "); //$NON-NLS-1$ + } + if ((leadingWhitespaces % 8) >= 1) { + sb.append(' '); + } + } else if (line != 0) { + // we don't want to preserve the leading spaces for the first line + for (int j = 0, max2 = leadingWhitespaces; j < max2; j++) { + sb.append(' '); + } + } + leadingWhitespaces = 0; + sb.append(c); + } else if (c != '*' || i > starsIndex) { + sb.append(c); + } } } + // append a newline at the end of each line except the last, even if we skipped the last entirely - if (line < lines.length - 1) { + int end = lines.length - 1; + if (line < end) { + sb.append('\n'); + } else if (preserveLineSeparator && line == end) { sb.append('\n'); } } return sb.toString(); } - + + /** + * Returns the index of the last leading stars on this line, -1 if none. + * + * @param line the given line + * @return the computed index + */ + private static int getStars(char[] line) { + loop: for (int i = 0, max = line.length; i < max; i++) { + char c = line[i]; + if (!Character.isWhitespace(c)) { + if (c == '*') { + // only whitespaces before the first star + // consume all stars and return the last index + for (int j = i + 1; j < max; j++) { + if (line[j] != '*') { + return j; + } + } + return max - 1; + } + // no need to continue + break loop; + } + } + return -1; + } /** * @return all the annotation instance's explicitly set values, plus default values * for all the annotation members that are not explicitly set but that have @@ -507,7 +589,7 @@ public class ElementsImpl implements Elements { // try finding the top-level type and then working downwards. if (null == binding) { ReferenceBinding topLevelBinding = null; - int topLevelSegments = compoundName.length; + int topLevelSegments = compoundName.length; while (--topLevelSegments > 0) { char[][] topLevelName = new char[topLevelSegments][]; for (int i = 0; i < topLevelSegments; ++i) { diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java index 8885910ade..f61911aba9 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java @@ -18,12 +18,15 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.Charset; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; import java.util.Set; import java.util.StringTokenizer; import java.util.zip.ZipException; @@ -34,9 +37,13 @@ import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; import javax.tools.JavaFileObject.Kind; +import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.eclipse.jdt.internal.compiler.batch.Main; +import org.eclipse.jdt.internal.compiler.batch.Main.ResourceBundleFactory; +import org.eclipse.jdt.internal.compiler.env.AccessRule; +import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; /** * Implementation of the Standard Java File Manager @@ -52,18 +59,14 @@ public class EclipseFileManager implements StandardJavaFileManager { Charset charset; Locale locale; Map<String, Iterable<? extends File>> locations; - Main compiler; int flags; + public ResourceBundle bundle; - public EclipseFileManager(Main eclipseCompiler, Locale locale, Charset charset) { - this.compiler = eclipseCompiler; + public EclipseFileManager(Locale locale, Charset charset) { this.locale = locale == null ? Locale.getDefault() : locale; this.charset = charset == null ? Charset.defaultCharset() : charset; this.locations = new HashMap<String, Iterable<? extends File>>(); this.archivesCache = new HashMap<File, Archive>(); - if (locale != null) { - this.compiler.setLocale(locale); - } try { this.setLocation(StandardLocation.PLATFORM_CLASS_PATH, getDefaultBootclasspath()); Iterable<? extends File> defaultClasspath = getDefaultClasspath(); @@ -72,6 +75,11 @@ public class EclipseFileManager implements StandardJavaFileManager { } catch (IOException e) { // ignore } + try { + this.bundle = ResourceBundleFactory.getBundle(this.locale); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$ + } } private void addFiles(File[][] jars, ArrayList<File> files) { @@ -266,7 +274,7 @@ public class EclipseFileManager implements StandardJavaFileManager { ArrayList<FileSystem.Classpath> paths = new ArrayList<FileSystem.Classpath>(); ArrayList<File> files = new ArrayList<File>(); try { - this.compiler.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); + this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); } catch (InvalidInputException e) { return null; } @@ -287,21 +295,28 @@ public class EclipseFileManager implements StandardJavaFileManager { /* * Handle >= JDK 1.6 */ - File javaHome = this.compiler.getJavaHome(); - addFilesFrom(javaHome, "java.endorsed.dirs", "/lib/endorsed", files);//$NON-NLS-1$//$NON-NLS-2$ + String javaHome = System.getProperty("java.home"); //$NON-NLS-1$ + File javaHomeFile = null; if (javaHome != null) { + javaHomeFile = new File(javaHome); + if (!javaHomeFile.exists()) + javaHomeFile = null; + } + + addFilesFrom(javaHomeFile, "java.endorsed.dirs", "/lib/endorsed", files);//$NON-NLS-1$//$NON-NLS-2$ + if (javaHomeFile != null) { File[] directoriesToCheck = null; if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$ - directoriesToCheck = new File[] { new File(javaHome, "../Classes"), //$NON-NLS-1$ + directoriesToCheck = new File[] { new File(javaHomeFile, "../Classes"), //$NON-NLS-1$ }; } else { - directoriesToCheck = new File[] { new File(javaHome, "lib") //$NON-NLS-1$ + directoriesToCheck = new File[] { new File(javaHomeFile, "lib") //$NON-NLS-1$ }; } File[][] jars = Main.getLibrariesFiles(directoriesToCheck); addFiles(jars, files); } - addFilesFrom(javaHome, "java.ext.dirs", "/lib/ext", files);//$NON-NLS-1$//$NON-NLS-2$ + addFilesFrom(javaHomeFile, "java.ext.dirs", "/lib/ext", files);//$NON-NLS-1$//$NON-NLS-2$ return files; } @@ -329,7 +344,7 @@ public class EclipseFileManager implements StandardJavaFileManager { ArrayList<FileSystem.Classpath> paths = new ArrayList<FileSystem.Classpath>(); ArrayList<File> files = new ArrayList<File>(); try { - this.compiler.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); + this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); } catch (InvalidInputException e) { return null; } @@ -343,7 +358,7 @@ public class EclipseFileManager implements StandardJavaFileManager { ArrayList<FileSystem.Classpath> paths = new ArrayList<FileSystem.Classpath>(); ArrayList<File> files = new ArrayList<File>(); try { - this.compiler.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); + this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); } catch (InvalidInputException e) { return null; } @@ -838,6 +853,299 @@ public class EclipseFileManager implements StandardJavaFileManager { } public void setLocale(Locale locale) { - this.locale = locale; + this.locale = locale == null ? Locale.getDefault() : locale; + try { + this.bundle = ResourceBundleFactory.getBundle(this.locale); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + } + + @SuppressWarnings("unchecked") + public void processPathEntries(final int defaultSize, final ArrayList paths, + final String currentPath, String customEncoding, boolean isSourceOnly, + boolean rejectDestinationPathOnJars) + throws InvalidInputException { + String currentClasspathName = null; + String currentDestinationPath = null; + ArrayList currentRuleSpecs = new ArrayList(defaultSize); + StringTokenizer tokenizer = new StringTokenizer(currentPath, + File.pathSeparator + "[]", true); //$NON-NLS-1$ + ArrayList tokens = new ArrayList(); + while (tokenizer.hasMoreTokens()) { + tokens.add(tokenizer.nextToken()); + } + // state machine + final int start = 0; + final int readyToClose = 1; + // 'path' 'path1[rule];path2' + final int readyToCloseEndingWithRules = 2; + // 'path[rule]' 'path1;path2[rule]' + final int readyToCloseOrOtherEntry = 3; + // 'path[rule];' 'path;' 'path1;path2;' + final int rulesNeedAnotherRule = 4; + // 'path[rule1;' + final int rulesStart = 5; + // 'path[' 'path1;path2[' + final int rulesReadyToClose = 6; + // 'path[rule' 'path[rule1;rule2' + final int destinationPathReadyToClose = 7; + // 'path[-d bin' + final int readyToCloseEndingWithDestinationPath = 8; + // 'path[-d bin]' 'path[rule][-d bin]' + final int destinationPathStart = 9; + // 'path[rule][' + final int bracketOpened = 10; + // '.*[.*' + final int bracketClosed = 11; + // '.*([.*])+' + + final int error = 99; + int state = start; + String token = null; + int cursor = 0, tokensNb = tokens.size(), bracket = -1; + while (cursor < tokensNb && state != error) { + token = (String) tokens.get(cursor++); + if (token.equals(File.pathSeparator)) { + switch (state) { + case start: + case readyToCloseOrOtherEntry: + case bracketOpened: + break; + case readyToClose: + case readyToCloseEndingWithRules: + case readyToCloseEndingWithDestinationPath: + state = readyToCloseOrOtherEntry; + addNewEntry(paths, currentClasspathName, currentRuleSpecs, + customEncoding, currentDestinationPath, isSourceOnly, + rejectDestinationPathOnJars); + currentRuleSpecs.clear(); + break; + case rulesReadyToClose: + state = rulesNeedAnotherRule; + break; + case destinationPathReadyToClose: + throw new InvalidInputException( + this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$ + currentPath)); + case bracketClosed: + cursor = bracket + 1; + state = rulesStart; + break; + default: + state = error; + } + } else if (token.equals("[")) { //$NON-NLS-1$ + switch (state) { + case start: + currentClasspathName = ""; //$NON-NLS-1$ + case readyToClose: + bracket = cursor - 1; + case bracketClosed: + state = bracketOpened; + break; + case readyToCloseEndingWithRules: + state = destinationPathStart; + break; + case readyToCloseEndingWithDestinationPath: + state = rulesStart; + break; + case bracketOpened: + default: + state = error; + } + } else if (token.equals("]")) { //$NON-NLS-1$ + switch (state) { + case rulesReadyToClose: + state = readyToCloseEndingWithRules; + break; + case destinationPathReadyToClose: + state = readyToCloseEndingWithDestinationPath; + break; + case bracketOpened: + state = bracketClosed; + break; + case bracketClosed: + default: + state = error; + } + } else { + // regular word + switch (state) { + case start: + case readyToCloseOrOtherEntry: + state = readyToClose; + currentClasspathName = token; + break; + case rulesStart: + if (token.startsWith("-d ")) { //$NON-NLS-1$ + if (currentDestinationPath != null) { + throw new InvalidInputException( + this.bind("configure.duplicateDestinationPathEntry", //$NON-NLS-1$ + currentPath)); + } + currentDestinationPath = token.substring(3).trim(); + state = destinationPathReadyToClose; + break; + } // else we proceed with a rule + case rulesNeedAnotherRule: + if (currentDestinationPath != null) { + throw new InvalidInputException( + this.bind("configure.accessRuleAfterDestinationPath", //$NON-NLS-1$ + currentPath)); + } + state = rulesReadyToClose; + currentRuleSpecs.add(token); + break; + case destinationPathStart: + if (!token.startsWith("-d ")) { //$NON-NLS-1$ + state = error; + } else { + currentDestinationPath = token.substring(3).trim(); + state = destinationPathReadyToClose; + } + break; + case bracketClosed: + for (int i = bracket; i < cursor ; i++) { + currentClasspathName += (String) tokens.get(i); + } + state = readyToClose; + break; + case bracketOpened: + break; + default: + state = error; + } + } + if (state == bracketClosed && cursor == tokensNb) { + cursor = bracket + 1; + state = rulesStart; + } + } + switch(state) { + case readyToCloseOrOtherEntry: + break; + case readyToClose: + case readyToCloseEndingWithRules: + case readyToCloseEndingWithDestinationPath: + addNewEntry(paths, currentClasspathName, currentRuleSpecs, + customEncoding, currentDestinationPath, isSourceOnly, + rejectDestinationPathOnJars); + break; + case bracketOpened: + case bracketClosed: + default : + // we go on anyway + } + } + @SuppressWarnings("unchecked") + protected void addNewEntry(ArrayList paths, String currentClasspathName, + ArrayList currentRuleSpecs, String customEncoding, + String destPath, boolean isSourceOnly, + boolean rejectDestinationPathOnJars) throws InvalidInputException { + + int rulesSpecsSize = currentRuleSpecs.size(); + AccessRuleSet accessRuleSet = null; + if (rulesSpecsSize != 0) { + AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()]; + boolean rulesOK = true; + Iterator i = currentRuleSpecs.iterator(); + int j = 0; + while (i.hasNext()) { + String ruleSpec = (String) i.next(); + char key = ruleSpec.charAt(0); + String pattern = ruleSpec.substring(1); + if (pattern.length() > 0) { + switch (key) { + case '+': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), 0); + break; + case '~': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.DiscouragedReference); + break; + case '-': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.ForbiddenReference); + break; + case '?': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.ForbiddenReference, true/*keep looking for accessible type*/); + break; + default: + rulesOK = false; + } + } else { + rulesOK = false; + } + } + if (rulesOK) { + String templates[] = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH]; + templates[0] = this.bind( + "template.restrictedAccess.type", //$NON-NLS-1$ + new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ + templates[1] = this.bind( + "template.restrictedAccess.constructor", //$NON-NLS-1$ + new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ + templates[2] = this.bind( + "template.restrictedAccess.method", //$NON-NLS-1$ + new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ + templates[3] = this.bind( + "template.restrictedAccess.field", //$NON-NLS-1$ + new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ + accessRuleSet = new AccessRuleSet(accessRules, templates); + } else { + return; + } + } + if (Main.NONE.equals(destPath)) { + destPath = Main.NONE; // keep == comparison valid + } + if (rejectDestinationPathOnJars && destPath != null && + (currentClasspathName.endsWith(".jar") || //$NON-NLS-1$ + currentClasspathName.endsWith(".zip"))) { //$NON-NLS-1$ + throw new InvalidInputException( + this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$ + currentClasspathName)); + } + FileSystem.Classpath currentClasspath = FileSystem.getClasspath( + currentClasspathName, + customEncoding, + isSourceOnly, + accessRuleSet, + destPath); + if (currentClasspath != null) { + paths.add(currentClasspath); + } + } + /* + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string. + */ + private String bind(String id, String binding) { + return bind(id, new String[] { binding }); + } + + /* + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string values. + */ + private String bind(String id, String[] arguments) { + if (id == null) + return "No message available"; //$NON-NLS-1$ + String message = null; + try { + message = this.bundle.getString(id); + } catch (MissingResourceException e) { + // If we got an exception looking for the message, fail gracefully by just returning + // the id we were looking for. In most cases this is semi-informative so is not too bad. + return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$ + } + return MessageFormat.format(message, (Object[]) arguments); } } diff --git a/org.eclipse.jdt.compiler.tool/META-INF/MANIFEST.MF b/org.eclipse.jdt.compiler.tool/META-INF/MANIFEST.MF index 6519d9450b..cd38e6f1cd 100644 --- a/org.eclipse.jdt.compiler.tool/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.compiler.tool/META-INF/MANIFEST.MF @@ -8,4 +8,4 @@ Bundle-Localization: compiler_tool_fragment Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: META-INF.services, org.eclipse.jdt.internal.compiler.tool -Fragment-Host: org.eclipse.jdt.core;bundle-version="3.3.0" +Fragment-Host: org.eclipse.jdt.core;bundle-version="[3.3.0,4.0.0)" diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompiler.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompiler.java index 5d1bfdc6e8..fee67028e1 100644 --- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompiler.java +++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompiler.java @@ -10,9 +10,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.tool; -import java.io.BufferedOutputStream; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -22,48 +20,29 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; -import java.util.HashMap; import java.util.Iterator; import java.util.Locale; -import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import javax.annotation.processing.Processor; import javax.lang.model.SourceVersion; import javax.tools.DiagnosticListener; -import javax.tools.Diagnostic; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; -import org.eclipse.jdt.core.compiler.CategorizedProblem; -import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; -import org.eclipse.jdt.internal.compiler.ClassFile; -import org.eclipse.jdt.internal.compiler.CompilationResult; -import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; -import org.eclipse.jdt.internal.compiler.IProblemFactory; -import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; -import org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.eclipse.jdt.internal.compiler.batch.Main; -import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; -import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; -import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; -import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; -import org.eclipse.jdt.internal.compiler.util.Messages; -import org.eclipse.jdt.internal.compiler.util.SuffixConstants; /** * Implementation of a batch compiler that supports the jsr199 */ -public class EclipseCompiler extends Main implements JavaCompiler { +public class EclipseCompiler implements JavaCompiler { - private static final CompilationUnit[] NO_UNITS = new CompilationUnit[0]; - private HashMap<CompilationUnit, JavaFileObject> javaFileObjectMap; private static Set<SourceVersion> SupportedSourceVersions; static { // Eclipse compiler supports all possible versions from version 0 to @@ -74,180 +53,13 @@ public class EclipseCompiler extends Main implements JavaCompiler { SupportedSourceVersions = Collections.unmodifiableSet(enumSet); } - Iterable<? extends JavaFileObject> compilationUnits; + WeakHashMap<Thread, EclipseCompilerImpl> threadCache; public DiagnosticListener<? super JavaFileObject> diagnosticListener; - public JavaFileManager fileManager; - protected Processor[] processors; - - public EclipseCompiler(PrintWriter out, PrintWriter err, boolean systemExitWhenFinished) { - super(out, err, systemExitWhenFinished); - } public EclipseCompiler() { - super(null, null, false); - } - - public boolean call() { - try { - if (this.proceed) { - this.globalProblemsCount = 0; - this.globalErrorsCount = 0; - this.globalWarningsCount = 0; - this.globalTasksCount = 0; - this.lineCount = 0; - this.exportedClassFilesCounter = 0; - // request compilation - performCompilation(); - } - } catch (InvalidInputException e) { - this.logger.logException(e); - if (this.systemExitWhenFinished) { - cleanup(); - System.exit(-1); - } - return false; - } catch(IllegalArgumentException e) { - throw e; - } catch (RuntimeException e) { // internal compiler failure - this.logger.logException(e); - return false; - } finally { - cleanup(); - } - if (this.globalErrorsCount == 0) - return true; - return false; - } - - private void cleanup() { - this.logger.flush(); - this.logger.close(); - this.processors = null; - try { - if (this.fileManager != null) { - this.fileManager.flush(); - } - } catch (IOException e) { - // ignore - } - } - - public CompilationUnit[] getCompilationUnits() { - if (this.compilationUnits == null) return NO_UNITS; - ArrayList<CompilationUnit> units = new ArrayList<CompilationUnit>(); - for (final JavaFileObject javaFileObject : this.compilationUnits) { - if (javaFileObject.getKind() != JavaFileObject.Kind.SOURCE) { - throw new IllegalArgumentException(); - } - String name = javaFileObject.getName(); - name = name.replace('\\', '/'); - CompilationUnit compilationUnit = new CompilationUnit(null, - name, - null) { - - public char[] getContents() { - try { - return javaFileObject.getCharContent(true).toString().toCharArray(); - } catch(IOException e) { - e.printStackTrace(); - throw new AbortCompilationUnit(null, e, null); - } - } - }; - units.add(compilationUnit); - this.javaFileObjectMap.put(compilationUnit, javaFileObject); - } - CompilationUnit[] result = new CompilationUnit[units.size()]; - units.toArray(result); - return result; + this.threadCache = new WeakHashMap<Thread, EclipseCompilerImpl>(); } /* - * Low-level API performing the actual compilation - */ - public IErrorHandlingPolicy getHandlingPolicy() { - // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match) - return new IErrorHandlingPolicy() { - public boolean proceedOnErrors() { - return false; // stop if there are some errors - } - public boolean stopOnFirstError() { - return false; - } - }; - } - - public IProblemFactory getProblemFactory() { - return new DefaultProblemFactory() { - @Override - public CategorizedProblem createProblem( - final char[] originatingFileName, - final int problemId, - final String[] problemArguments, - final String[] messageArguments, - final int severity, - final int startPosition, - final int endPosition, - final int lineNumber, - final int columnNumber) { - - DiagnosticListener<? super JavaFileObject> diagnosticListener = EclipseCompiler.this.diagnosticListener; - if (diagnosticListener != null) { - diagnosticListener.report(new Diagnostic<JavaFileObject>() { - public String getCode() { - return Integer.toString(problemId); - } - public long getColumnNumber() { - return columnNumber; - } - public long getEndPosition() { - return endPosition; - } - public Kind getKind() { - if ((severity & ProblemSeverities.Error) != 0) { - return Diagnostic.Kind.ERROR; - } - if ((severity & ProblemSeverities.Optional) != 0) { - return Diagnostic.Kind.WARNING; - } - if ((severity & ProblemSeverities.Warning) != 0) { - return Diagnostic.Kind.MANDATORY_WARNING; - } - return Diagnostic.Kind.OTHER; - } - public long getLineNumber() { - return lineNumber; - } - public String getMessage(Locale locale) { - setLocale(locale); - return getLocalizedMessage(problemId, problemArguments); - } - public long getPosition() { - return startPosition; - } - public JavaFileObject getSource() { - try { - if (EclipseCompiler.this.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) { - return EclipseCompiler.this.fileManager.getJavaFileForInput( - StandardLocation.SOURCE_PATH, - new String(originatingFileName), - JavaFileObject.Kind.SOURCE); - } - } catch (IOException e) { - // ignore - } - return null; - } - public long getStartPosition() { - return startPosition; - } - }); - } - return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber, columnNumber); - } - }; - } - - /* * (non-Javadoc) * * @see javax.tools.Tool#getSourceVersions() @@ -265,7 +77,7 @@ public class EclipseCompiler extends Main implements JavaCompiler { Locale locale, Charset charset) { this.diagnosticListener = diagnosticListener; - return new EclipseFileManager(this, locale, charset); + return new EclipseFileManager(locale, charset); } /* * (non-Javadoc) @@ -291,23 +103,31 @@ public class EclipseCompiler extends Main implements JavaCompiler { writerOut = new PrintWriter(out); writerErr = new PrintWriter(out); } - this.compilationUnits = compilationUnits; - this.diagnosticListener = diagnosticListener; + final Thread currentThread = Thread.currentThread(); + EclipseCompilerImpl eclipseCompiler = this.threadCache.get(currentThread); + if (eclipseCompiler == null) { + eclipseCompiler = new EclipseCompilerImpl(writerOut, writerErr, false); + this.threadCache.put(currentThread, eclipseCompiler); + } else { + eclipseCompiler.initialize(writerOut, writerErr, false, null); + } + final EclipseCompilerImpl eclipseCompiler2 = new EclipseCompilerImpl(writerOut, writerErr, false); + eclipseCompiler2.compilationUnits = compilationUnits; + eclipseCompiler2.diagnosticListener = diagnosticListener; if (fileManager != null) { - this.fileManager = fileManager; + eclipseCompiler2.fileManager = fileManager; } else { - this.fileManager = this.getStandardFileManager(diagnosticListener, null, null); + eclipseCompiler2.fileManager = this.getStandardFileManager(diagnosticListener, null, null); } - initialize(writerOut, writerErr, false); - this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6); - this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6); - this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6); + eclipseCompiler2.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6); + eclipseCompiler2.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6); + eclipseCompiler2.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6); ArrayList<String> allOptions = new ArrayList<String>(); if (options != null) { for (Iterator<String> iterator = options.iterator(); iterator.hasNext(); ) { - this.fileManager.handleOption(iterator.next(), iterator); + eclipseCompiler2.fileManager.handleOption(iterator.next(), iterator); } for (String option : options) { allOptions.add(option); @@ -337,17 +157,17 @@ public class EclipseCompiler extends Main implements JavaCompiler { final String[] optionsToProcess = new String[allOptions.size()]; allOptions.toArray(optionsToProcess); try { - this.configure(optionsToProcess); + eclipseCompiler2.configure(optionsToProcess); } catch (InvalidInputException e) { throw new RuntimeException(e); } - if (this.fileManager instanceof StandardJavaFileManager) { - StandardJavaFileManager javaFileManager = (StandardJavaFileManager) this.fileManager; + if (eclipseCompiler2.fileManager instanceof StandardJavaFileManager) { + StandardJavaFileManager javaFileManager = (StandardJavaFileManager) eclipseCompiler2.fileManager; Iterable<? extends File> location = javaFileManager.getLocation(StandardLocation.CLASS_OUTPUT); if (location != null) { - this.setDestinationPath(location.iterator().next().getAbsolutePath()); + eclipseCompiler2.setDestinationPath(location.iterator().next().getAbsolutePath()); } } @@ -358,12 +178,12 @@ public class EclipseCompiler extends Main implements JavaCompiler { if (this.hasRun) { throw new IllegalStateException("This task has already been run"); //$NON-NLS-1$ } - Boolean value = EclipseCompiler.this.call() ? Boolean.TRUE : Boolean.FALSE; + Boolean value = eclipseCompiler2.call() ? Boolean.TRUE : Boolean.FALSE; this.hasRun = true; return value; } public void setLocale(Locale locale) { - EclipseCompiler.this.setLocale(locale); + eclipseCompiler2.setLocale(locale); } public void setProcessors(Iterable<? extends Processor> processors) { ArrayList<Processor> temp = new ArrayList<Processor>(); @@ -372,28 +192,10 @@ public class EclipseCompiler extends Main implements JavaCompiler { } Processor[] processors2 = new Processor[temp.size()]; temp.toArray(processors2); - EclipseCompiler.this.processors = processors2; + eclipseCompiler2.processors = processors2; } }; } - - @Override - @SuppressWarnings("unchecked") - protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map customDefaultOptions) { - super.initialize(outWriter, errWriter, systemExit, customDefaultOptions); - this.javaFileObjectMap = new HashMap<CompilationUnit, JavaFileObject>(); - } - - @Override - protected void initializeAnnotationProcessorManager() { - super.initializeAnnotationProcessorManager(); - if (this.batchCompiler.annotationProcessorManager != null && this.processors != null) { - this.batchCompiler.annotationProcessorManager.setProcessors(this.processors); - } else if (this.processors != null) { - throw new UnsupportedOperationException("Cannot handle annotation processing"); //$NON-NLS-1$ - } - } - /* * (non-Javadoc) * @@ -403,84 +205,6 @@ public class EclipseCompiler extends Main implements JavaCompiler { return Options.processOptions(option); } - // Dump classfiles onto disk for all compilation units that where successful - // and do not carry a -d none spec, either directly or inherited from Main. - public void outputClassFiles(CompilationResult unitResult) { - if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) { - ClassFile[] classFiles = unitResult.getClassFiles(); - boolean generateClasspathStructure = this.fileManager.hasLocation(StandardLocation.CLASS_OUTPUT); - String currentDestinationPath = this.destinationPath; - File outputLocation = null; - if (currentDestinationPath != null) { - outputLocation = new File(currentDestinationPath); - outputLocation.mkdirs(); - } - for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) { - // retrieve the key and the corresponding classfile - ClassFile classFile = classFiles[i]; - char[] filename = classFile.fileName(); - int length = filename.length; - char[] relativeName = new char[length + 6]; - System.arraycopy(filename, 0, relativeName, 0, length); - System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6); - CharOperation.replace(relativeName, '/', File.separatorChar); - String relativeStringName = new String(relativeName); - if (this.compilerOptions.verbose) { - EclipseCompiler.this.out.println( - Messages.bind( - Messages.compilation_write, - new String[] { - String.valueOf(this.exportedClassFilesCounter+1), - relativeStringName - })); - } - try { - JavaFileObject javaFileForOutput = - this.fileManager.getJavaFileForOutput( - StandardLocation.CLASS_OUTPUT, - new String(filename), - JavaFileObject.Kind.CLASS, - this.javaFileObjectMap.get(unitResult.compilationUnit)); - - if (generateClasspathStructure) { - if (currentDestinationPath != null) { - int index = CharOperation.lastIndexOf(File.separatorChar, relativeName); - if (index != -1) { - File currentFolder = new File(currentDestinationPath, relativeStringName.substring(0, index)); - currentFolder.mkdirs(); - } - } else { - // create the subfolfers is necessary - // need a way to retrieve the folders to create - String path = javaFileForOutput.toUri().getPath(); - int index = path.lastIndexOf('/'); - if (index != -1) { - File file = new File(path.substring(0, index)); - file.mkdirs(); - } - } - } - - OutputStream openOutputStream = javaFileForOutput.openOutputStream(); - BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(openOutputStream); - bufferedOutputStream.write(classFile.header, 0, classFile.headerOffset); - bufferedOutputStream.write(classFile.contents, 0, classFile.contentsOffset); - bufferedOutputStream.flush(); - bufferedOutputStream.close(); - } catch (IOException e) { - this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e); - } - LookupEnvironment env = EclipseCompiler.this.batchCompiler.lookupEnvironment; - if (classFile.isShared) env.classFilePool.release(classFile); - this.logger.logClassFile( - generateClasspathStructure, - currentDestinationPath, - relativeStringName); - this.exportedClassFilesCounter++; - } - } - } - /* * (non-Javadoc) * @@ -491,95 +215,4 @@ public class EclipseCompiler extends Main implements JavaCompiler { boolean succeed = new Main(new PrintWriter(new OutputStreamWriter(out)), new PrintWriter(new OutputStreamWriter(err)), true).compile(arguments); return succeed ? 0 : -1; } - - @Override - @SuppressWarnings("unchecked") - protected void setPaths(ArrayList bootclasspaths, - String sourcepathClasspathArg, - ArrayList sourcepathClasspaths, - ArrayList classpaths, - ArrayList extdirsClasspaths, - ArrayList endorsedDirClasspaths, - String customEncoding) throws InvalidInputException { - - ArrayList<FileSystem.Classpath> fileSystemClasspaths = new ArrayList<FileSystem.Classpath>(); - EclipseFileManager javaFileManager = null; - StandardJavaFileManager standardJavaFileManager = null; - if (this.fileManager instanceof EclipseFileManager) { - javaFileManager = (EclipseFileManager) this.fileManager; - } - if (this.fileManager instanceof StandardJavaFileManager) { - standardJavaFileManager = (StandardJavaFileManager) this.fileManager; - } - - if (javaFileManager != null) { - if ((javaFileManager.flags & EclipseFileManager.HAS_ENDORSED_DIRS) == 0 - && (javaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) { - fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleEndorseddirs(null)); - } - } - Iterable<? extends File> location = null; - if (standardJavaFileManager != null) { - location = standardJavaFileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH); - } - if (location != null) { - for (File file : location) { - Classpath classpath = FileSystem.getClasspath( - file.getAbsolutePath(), - null, - null); - if (classpath != null) { - fileSystemClasspaths.add(classpath); - } - } - } - if (javaFileManager != null) { - if ((javaFileManager.flags & EclipseFileManager.HAS_EXT_DIRS) == 0 - && (javaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) { - fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleExtdirs(null)); - } - } - if (standardJavaFileManager != null) { - location = standardJavaFileManager.getLocation(StandardLocation.SOURCE_PATH); - } else { - location = null; - } - if (location != null) { - for (File file : location) { - fileSystemClasspaths.add(FileSystem.getClasspath( - file.getAbsolutePath(), - null, - null)); - } - } - if (standardJavaFileManager != null) { - location = standardJavaFileManager.getLocation(StandardLocation.CLASS_PATH); - } else { - location = null; - } - if (location != null) { - for (File file : location) { - Classpath classpath = FileSystem.getClasspath( - file.getAbsolutePath(), - null, - null); - if (classpath != null) { - fileSystemClasspaths.add(classpath); - } - } - } - if (this.checkedClasspaths == null) { - fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleBootclasspath(null, null)); - fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleClasspath(null, null)); - } - fileSystemClasspaths = FileSystem.ClasspathNormalizer.normalize(fileSystemClasspaths); - final int size = fileSystemClasspaths.size(); - if (size != 0) { - this.checkedClasspaths = new FileSystem.Classpath[size]; - int i = 0; - for (FileSystem.Classpath classpath : fileSystemClasspaths) { - this.checkedClasspaths[i++] = classpath; - } - } - } } diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java new file mode 100644 index 0000000000..ae1f8a22f8 --- /dev/null +++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java @@ -0,0 +1,410 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.tool; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.annotation.processing.Processor; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + +import org.eclipse.jdt.core.compiler.CategorizedProblem; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.compiler.InvalidInputException; +import org.eclipse.jdt.internal.compiler.ClassFile; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; +import org.eclipse.jdt.internal.compiler.IProblemFactory; +import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; +import org.eclipse.jdt.internal.compiler.batch.FileSystem; +import org.eclipse.jdt.internal.compiler.batch.Main; +import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; +import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; +import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; +import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; +import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; +import org.eclipse.jdt.internal.compiler.util.Messages; +import org.eclipse.jdt.internal.compiler.util.SuffixConstants; + +public class EclipseCompilerImpl extends Main { + private static final CompilationUnit[] NO_UNITS = new CompilationUnit[0]; + private HashMap<CompilationUnit, JavaFileObject> javaFileObjectMap; + Iterable<? extends JavaFileObject> compilationUnits; + public JavaFileManager fileManager; + protected Processor[] processors; + public DiagnosticListener<? super JavaFileObject> diagnosticListener; + + public EclipseCompilerImpl(PrintWriter out, PrintWriter err, boolean systemExitWhenFinished) { + super(out, err, systemExitWhenFinished); + } + + public boolean call() { + try { + if (this.proceed) { + this.globalProblemsCount = 0; + this.globalErrorsCount = 0; + this.globalWarningsCount = 0; + this.globalTasksCount = 0; + this.lineCount = 0; + this.exportedClassFilesCounter = 0; + // request compilation + performCompilation(); + } + } catch (InvalidInputException e) { + this.logger.logException(e); + if (this.systemExitWhenFinished) { + cleanup(); + System.exit(-1); + } + return false; + } catch(IllegalArgumentException e) { + throw e; + } catch (RuntimeException e) { // internal compiler failure + this.logger.logException(e); + return false; + } finally { + cleanup(); + } + if (this.globalErrorsCount == 0) + return true; + return false; + } + + private void cleanup() { + this.logger.flush(); + this.logger.close(); + this.processors = null; + try { + if (this.fileManager != null) { + this.fileManager.flush(); + } + } catch (IOException e) { + // ignore + } + } + + public CompilationUnit[] getCompilationUnits() { + if (this.compilationUnits == null) return NO_UNITS; + ArrayList<CompilationUnit> units = new ArrayList<CompilationUnit>(); + for (final JavaFileObject javaFileObject : this.compilationUnits) { + if (javaFileObject.getKind() != JavaFileObject.Kind.SOURCE) { + throw new IllegalArgumentException(); + } + String name = javaFileObject.getName(); + name = name.replace('\\', '/'); + CompilationUnit compilationUnit = new CompilationUnit(null, + name, + null) { + + public char[] getContents() { + try { + return javaFileObject.getCharContent(true).toString().toCharArray(); + } catch(IOException e) { + e.printStackTrace(); + throw new AbortCompilationUnit(null, e, null); + } + } + }; + units.add(compilationUnit); + this.javaFileObjectMap.put(compilationUnit, javaFileObject); + } + CompilationUnit[] result = new CompilationUnit[units.size()]; + units.toArray(result); + return result; + } + /* + * Low-level API performing the actual compilation + */ + public IErrorHandlingPolicy getHandlingPolicy() { + // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match) + return new IErrorHandlingPolicy() { + public boolean proceedOnErrors() { + return false; // stop if there are some errors + } + public boolean stopOnFirstError() { + return false; + } + }; + } + + public IProblemFactory getProblemFactory() { + return new DefaultProblemFactory() { + @Override + public CategorizedProblem createProblem( + final char[] originatingFileName, + final int problemId, + final String[] problemArguments, + final String[] messageArguments, + final int severity, + final int startPosition, + final int endPosition, + final int lineNumber, + final int columnNumber) { + + DiagnosticListener<? super JavaFileObject> diagnosticListener = EclipseCompilerImpl.this.diagnosticListener; + if (diagnosticListener != null) { + diagnosticListener.report(new Diagnostic<JavaFileObject>() { + public String getCode() { + return Integer.toString(problemId); + } + public long getColumnNumber() { + return columnNumber; + } + public long getEndPosition() { + return endPosition; + } + public Kind getKind() { + if ((severity & ProblemSeverities.Error) != 0) { + return Diagnostic.Kind.ERROR; + } + if ((severity & ProblemSeverities.Optional) != 0) { + return Diagnostic.Kind.WARNING; + } + if ((severity & ProblemSeverities.Warning) != 0) { + return Diagnostic.Kind.MANDATORY_WARNING; + } + return Diagnostic.Kind.OTHER; + } + public long getLineNumber() { + return lineNumber; + } + public String getMessage(Locale locale) { + setLocale(locale); + return getLocalizedMessage(problemId, problemArguments); + } + public long getPosition() { + return startPosition; + } + public JavaFileObject getSource() { + try { + if (EclipseCompilerImpl.this.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) { + return EclipseCompilerImpl.this.fileManager.getJavaFileForInput( + StandardLocation.SOURCE_PATH, + new String(originatingFileName), + JavaFileObject.Kind.SOURCE); + } + } catch (IOException e) { + // ignore + } + return null; + } + public long getStartPosition() { + return startPosition; + } + }); + } + return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber, columnNumber); + } + }; + } + + @Override + @SuppressWarnings("unchecked") + protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map customDefaultOptions) { + super.initialize(outWriter, errWriter, systemExit, customDefaultOptions); + this.javaFileObjectMap = new HashMap<CompilationUnit, JavaFileObject>(); + } + + @Override + protected void initializeAnnotationProcessorManager() { + super.initializeAnnotationProcessorManager(); + if (this.batchCompiler.annotationProcessorManager != null && this.processors != null) { + this.batchCompiler.annotationProcessorManager.setProcessors(this.processors); + } else if (this.processors != null) { + throw new UnsupportedOperationException("Cannot handle annotation processing"); //$NON-NLS-1$ + } + } + + // Dump classfiles onto disk for all compilation units that where successful + // and do not carry a -d none spec, either directly or inherited from Main. + public void outputClassFiles(CompilationResult unitResult) { + if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) { + ClassFile[] classFiles = unitResult.getClassFiles(); + boolean generateClasspathStructure = this.fileManager.hasLocation(StandardLocation.CLASS_OUTPUT); + String currentDestinationPath = this.destinationPath; + File outputLocation = null; + if (currentDestinationPath != null) { + outputLocation = new File(currentDestinationPath); + outputLocation.mkdirs(); + } + for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) { + // retrieve the key and the corresponding classfile + ClassFile classFile = classFiles[i]; + char[] filename = classFile.fileName(); + int length = filename.length; + char[] relativeName = new char[length + 6]; + System.arraycopy(filename, 0, relativeName, 0, length); + System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6); + CharOperation.replace(relativeName, '/', File.separatorChar); + String relativeStringName = new String(relativeName); + if (this.compilerOptions.verbose) { + EclipseCompilerImpl.this.out.println( + Messages.bind( + Messages.compilation_write, + new String[] { + String.valueOf(this.exportedClassFilesCounter+1), + relativeStringName + })); + } + try { + JavaFileObject javaFileForOutput = + this.fileManager.getJavaFileForOutput( + StandardLocation.CLASS_OUTPUT, + new String(filename), + JavaFileObject.Kind.CLASS, + this.javaFileObjectMap.get(unitResult.compilationUnit)); + + if (generateClasspathStructure) { + if (currentDestinationPath != null) { + int index = CharOperation.lastIndexOf(File.separatorChar, relativeName); + if (index != -1) { + File currentFolder = new File(currentDestinationPath, relativeStringName.substring(0, index)); + currentFolder.mkdirs(); + } + } else { + // create the subfolfers is necessary + // need a way to retrieve the folders to create + String path = javaFileForOutput.toUri().getPath(); + int index = path.lastIndexOf('/'); + if (index != -1) { + File file = new File(path.substring(0, index)); + file.mkdirs(); + } + } + } + + OutputStream openOutputStream = javaFileForOutput.openOutputStream(); + BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(openOutputStream); + bufferedOutputStream.write(classFile.header, 0, classFile.headerOffset); + bufferedOutputStream.write(classFile.contents, 0, classFile.contentsOffset); + bufferedOutputStream.flush(); + bufferedOutputStream.close(); + } catch (IOException e) { + this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e); + } + LookupEnvironment env = EclipseCompilerImpl.this.batchCompiler.lookupEnvironment; + if (classFile.isShared) { + synchronized (env.classFilePool) { + env.classFilePool.release(classFile); + } + } + this.logger.logClassFile( + generateClasspathStructure, + currentDestinationPath, + relativeStringName); + this.exportedClassFilesCounter++; + } + } + } + + @Override + @SuppressWarnings("unchecked") + protected void setPaths(ArrayList bootclasspaths, + String sourcepathClasspathArg, + ArrayList sourcepathClasspaths, + ArrayList classpaths, + ArrayList extdirsClasspaths, + ArrayList endorsedDirClasspaths, + String customEncoding) throws InvalidInputException { + + ArrayList<FileSystem.Classpath> fileSystemClasspaths = new ArrayList<FileSystem.Classpath>(); + EclipseFileManager javaFileManager = null; + StandardJavaFileManager standardJavaFileManager = null; + if (this.fileManager instanceof EclipseFileManager) { + javaFileManager = (EclipseFileManager) this.fileManager; + } + if (this.fileManager instanceof StandardJavaFileManager) { + standardJavaFileManager = (StandardJavaFileManager) this.fileManager; + } + + if (javaFileManager != null) { + if ((javaFileManager.flags & EclipseFileManager.HAS_ENDORSED_DIRS) == 0 + && (javaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) { + fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleEndorseddirs(null)); + } + } + Iterable<? extends File> location = null; + if (standardJavaFileManager != null) { + location = standardJavaFileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH); + } + if (location != null) { + for (File file : location) { + Classpath classpath = FileSystem.getClasspath( + file.getAbsolutePath(), + null, + null); + if (classpath != null) { + fileSystemClasspaths.add(classpath); + } + } + } + if (javaFileManager != null) { + if ((javaFileManager.flags & EclipseFileManager.HAS_EXT_DIRS) == 0 + && (javaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) { + fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleExtdirs(null)); + } + } + if (standardJavaFileManager != null) { + location = standardJavaFileManager.getLocation(StandardLocation.SOURCE_PATH); + } else { + location = null; + } + if (location != null) { + for (File file : location) { + fileSystemClasspaths.add(FileSystem.getClasspath( + file.getAbsolutePath(), + null, + null)); + } + } + if (standardJavaFileManager != null) { + location = standardJavaFileManager.getLocation(StandardLocation.CLASS_PATH); + } else { + location = null; + } + if (location != null) { + for (File file : location) { + Classpath classpath = FileSystem.getClasspath( + file.getAbsolutePath(), + null, + null); + if (classpath != null) { + fileSystemClasspaths.add(classpath); + } + } + } + if (this.checkedClasspaths == null) { + fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleBootclasspath(null, null)); + fileSystemClasspaths.addAll((ArrayList<? extends FileSystem.Classpath>) this.handleClasspath(null, null)); + } + fileSystemClasspaths = FileSystem.ClasspathNormalizer.normalize(fileSystemClasspaths); + final int size = fileSystemClasspaths.size(); + if (size != 0) { + this.checkedClasspaths = new FileSystem.Classpath[size]; + int i = 0; + for (FileSystem.Classpath classpath : fileSystemClasspaths) { + this.checkedClasspaths[i++] = classpath; + } + } + } +} diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java index 17f96f692e..c220a1a0d3 100644 --- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java +++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java @@ -18,12 +18,15 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.Charset; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; import java.util.Set; import java.util.StringTokenizer; import java.util.zip.ZipException; @@ -34,9 +37,13 @@ import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; import javax.tools.JavaFileObject.Kind; +import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.eclipse.jdt.internal.compiler.batch.Main; +import org.eclipse.jdt.internal.compiler.batch.Main.ResourceBundleFactory; +import org.eclipse.jdt.internal.compiler.env.AccessRule; +import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; /** * Implementation of the Standard Java File Manager @@ -52,18 +59,14 @@ public class EclipseFileManager implements StandardJavaFileManager { Charset charset; Locale locale; Map<String, Iterable<? extends File>> locations; - Main compiler; int flags; + public ResourceBundle bundle; - public EclipseFileManager(Main eclipseCompiler, Locale locale, Charset charset) { - this.compiler = eclipseCompiler; + public EclipseFileManager(Locale locale, Charset charset) { this.locale = locale == null ? Locale.getDefault() : locale; this.charset = charset == null ? Charset.defaultCharset() : charset; this.locations = new HashMap<String, Iterable<? extends File>>(); this.archivesCache = new HashMap<File, Archive>(); - if (locale != null) { - this.compiler.setLocale(locale); - } try { this.setLocation(StandardLocation.PLATFORM_CLASS_PATH, getDefaultBootclasspath()); Iterable<? extends File> defaultClasspath = getDefaultClasspath(); @@ -72,6 +75,11 @@ public class EclipseFileManager implements StandardJavaFileManager { } catch (IOException e) { // ignore } + try { + this.bundle = ResourceBundleFactory.getBundle(this.locale); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$ + } } private void addFiles(File[][] jars, ArrayList<File> files) { @@ -266,7 +274,7 @@ public class EclipseFileManager implements StandardJavaFileManager { ArrayList<FileSystem.Classpath> paths = new ArrayList<FileSystem.Classpath>(); ArrayList<File> files = new ArrayList<File>(); try { - this.compiler.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); + this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); } catch (InvalidInputException e) { return null; } @@ -287,21 +295,28 @@ public class EclipseFileManager implements StandardJavaFileManager { /* * Handle >= JDK 1.6 */ - File javaHome = this.compiler.getJavaHome(); - addFilesFrom(javaHome, "java.endorsed.dirs", "/lib/endorsed", files);//$NON-NLS-1$//$NON-NLS-2$ + String javaHome = System.getProperty("java.home"); //$NON-NLS-1$ + File javaHomeFile = null; if (javaHome != null) { + javaHomeFile = new File(javaHome); + if (!javaHomeFile.exists()) + javaHomeFile = null; + } + + addFilesFrom(javaHomeFile, "java.endorsed.dirs", "/lib/endorsed", files);//$NON-NLS-1$//$NON-NLS-2$ + if (javaHomeFile != null) { File[] directoriesToCheck = null; if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$ - directoriesToCheck = new File[] { new File(javaHome, "../Classes"), //$NON-NLS-1$ + directoriesToCheck = new File[] { new File(javaHomeFile, "../Classes"), //$NON-NLS-1$ }; } else { - directoriesToCheck = new File[] { new File(javaHome, "lib") //$NON-NLS-1$ + directoriesToCheck = new File[] { new File(javaHomeFile, "lib") //$NON-NLS-1$ }; } File[][] jars = Main.getLibrariesFiles(directoriesToCheck); addFiles(jars, files); } - addFilesFrom(javaHome, "java.ext.dirs", "/lib/ext", files);//$NON-NLS-1$//$NON-NLS-2$ + addFilesFrom(javaHomeFile, "java.ext.dirs", "/lib/ext", files);//$NON-NLS-1$//$NON-NLS-2$ return files; } @@ -329,7 +344,7 @@ public class EclipseFileManager implements StandardJavaFileManager { ArrayList<FileSystem.Classpath> paths = new ArrayList<FileSystem.Classpath>(); ArrayList<File> files = new ArrayList<File>(); try { - this.compiler.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); + this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); } catch (InvalidInputException e) { return null; } @@ -343,7 +358,7 @@ public class EclipseFileManager implements StandardJavaFileManager { ArrayList<FileSystem.Classpath> paths = new ArrayList<FileSystem.Classpath>(); ArrayList<File> files = new ArrayList<File>(); try { - this.compiler.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); + this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.toString(), false, false); } catch (InvalidInputException e) { return null; } @@ -838,6 +853,299 @@ public class EclipseFileManager implements StandardJavaFileManager { } public void setLocale(Locale locale) { - this.locale = locale; + this.locale = locale == null ? Locale.getDefault() : locale; + try { + this.bundle = ResourceBundleFactory.getBundle(this.locale); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + } + + @SuppressWarnings("unchecked") + public void processPathEntries(final int defaultSize, final ArrayList paths, + final String currentPath, String customEncoding, boolean isSourceOnly, + boolean rejectDestinationPathOnJars) + throws InvalidInputException { + String currentClasspathName = null; + String currentDestinationPath = null; + ArrayList currentRuleSpecs = new ArrayList(defaultSize); + StringTokenizer tokenizer = new StringTokenizer(currentPath, + File.pathSeparator + "[]", true); //$NON-NLS-1$ + ArrayList tokens = new ArrayList(); + while (tokenizer.hasMoreTokens()) { + tokens.add(tokenizer.nextToken()); + } + // state machine + final int start = 0; + final int readyToClose = 1; + // 'path' 'path1[rule];path2' + final int readyToCloseEndingWithRules = 2; + // 'path[rule]' 'path1;path2[rule]' + final int readyToCloseOrOtherEntry = 3; + // 'path[rule];' 'path;' 'path1;path2;' + final int rulesNeedAnotherRule = 4; + // 'path[rule1;' + final int rulesStart = 5; + // 'path[' 'path1;path2[' + final int rulesReadyToClose = 6; + // 'path[rule' 'path[rule1;rule2' + final int destinationPathReadyToClose = 7; + // 'path[-d bin' + final int readyToCloseEndingWithDestinationPath = 8; + // 'path[-d bin]' 'path[rule][-d bin]' + final int destinationPathStart = 9; + // 'path[rule][' + final int bracketOpened = 10; + // '.*[.*' + final int bracketClosed = 11; + // '.*([.*])+' + + final int error = 99; + int state = start; + String token = null; + int cursor = 0, tokensNb = tokens.size(), bracket = -1; + while (cursor < tokensNb && state != error) { + token = (String) tokens.get(cursor++); + if (token.equals(File.pathSeparator)) { + switch (state) { + case start: + case readyToCloseOrOtherEntry: + case bracketOpened: + break; + case readyToClose: + case readyToCloseEndingWithRules: + case readyToCloseEndingWithDestinationPath: + state = readyToCloseOrOtherEntry; + addNewEntry(paths, currentClasspathName, currentRuleSpecs, + customEncoding, currentDestinationPath, isSourceOnly, + rejectDestinationPathOnJars); + currentRuleSpecs.clear(); + break; + case rulesReadyToClose: + state = rulesNeedAnotherRule; + break; + case destinationPathReadyToClose: + throw new InvalidInputException( + this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$ + currentPath)); + case bracketClosed: + cursor = bracket + 1; + state = rulesStart; + break; + default: + state = error; + } + } else if (token.equals("[")) { //$NON-NLS-1$ + switch (state) { + case start: + currentClasspathName = ""; //$NON-NLS-1$ + case readyToClose: + bracket = cursor - 1; + case bracketClosed: + state = bracketOpened; + break; + case readyToCloseEndingWithRules: + state = destinationPathStart; + break; + case readyToCloseEndingWithDestinationPath: + state = rulesStart; + break; + case bracketOpened: + default: + state = error; + } + } else if (token.equals("]")) { //$NON-NLS-1$ + switch (state) { + case rulesReadyToClose: + state = readyToCloseEndingWithRules; + break; + case destinationPathReadyToClose: + state = readyToCloseEndingWithDestinationPath; + break; + case bracketOpened: + state = bracketClosed; + break; + case bracketClosed: + default: + state = error; + } + } else { + // regular word + switch (state) { + case start: + case readyToCloseOrOtherEntry: + state = readyToClose; + currentClasspathName = token; + break; + case rulesStart: + if (token.startsWith("-d ")) { //$NON-NLS-1$ + if (currentDestinationPath != null) { + throw new InvalidInputException( + this.bind("configure.duplicateDestinationPathEntry", //$NON-NLS-1$ + currentPath)); + } + currentDestinationPath = token.substring(3).trim(); + state = destinationPathReadyToClose; + break; + } // else we proceed with a rule + case rulesNeedAnotherRule: + if (currentDestinationPath != null) { + throw new InvalidInputException( + this.bind("configure.accessRuleAfterDestinationPath", //$NON-NLS-1$ + currentPath)); + } + state = rulesReadyToClose; + currentRuleSpecs.add(token); + break; + case destinationPathStart: + if (!token.startsWith("-d ")) { //$NON-NLS-1$ + state = error; + } else { + currentDestinationPath = token.substring(3).trim(); + state = destinationPathReadyToClose; + } + break; + case bracketClosed: + for (int i = bracket; i < cursor ; i++) { + currentClasspathName += (String) tokens.get(i); + } + state = readyToClose; + break; + case bracketOpened: + break; + default: + state = error; + } + } + if (state == bracketClosed && cursor == tokensNb) { + cursor = bracket + 1; + state = rulesStart; + } + } + switch(state) { + case readyToCloseOrOtherEntry: + break; + case readyToClose: + case readyToCloseEndingWithRules: + case readyToCloseEndingWithDestinationPath: + addNewEntry(paths, currentClasspathName, currentRuleSpecs, + customEncoding, currentDestinationPath, isSourceOnly, + rejectDestinationPathOnJars); + break; + case bracketOpened: + case bracketClosed: + default : + // we go on anyway + } + } + @SuppressWarnings("unchecked") + protected void addNewEntry(ArrayList paths, String currentClasspathName, + ArrayList currentRuleSpecs, String customEncoding, + String destPath, boolean isSourceOnly, + boolean rejectDestinationPathOnJars) throws InvalidInputException { + + int rulesSpecsSize = currentRuleSpecs.size(); + AccessRuleSet accessRuleSet = null; + if (rulesSpecsSize != 0) { + AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()]; + boolean rulesOK = true; + Iterator i = currentRuleSpecs.iterator(); + int j = 0; + while (i.hasNext()) { + String ruleSpec = (String) i.next(); + char key = ruleSpec.charAt(0); + String pattern = ruleSpec.substring(1); + if (pattern.length() > 0) { + switch (key) { + case '+': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), 0); + break; + case '~': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.DiscouragedReference); + break; + case '-': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.ForbiddenReference); + break; + case '?': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.ForbiddenReference, true/*keep looking for accessible type*/); + break; + default: + rulesOK = false; + } + } else { + rulesOK = false; + } + } + if (rulesOK) { + String templates[] = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH]; + templates[0] = this.bind( + "template.restrictedAccess.type", //$NON-NLS-1$ + new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ + templates[1] = this.bind( + "template.restrictedAccess.constructor", //$NON-NLS-1$ + new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ + templates[2] = this.bind( + "template.restrictedAccess.method", //$NON-NLS-1$ + new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ + templates[3] = this.bind( + "template.restrictedAccess.field", //$NON-NLS-1$ + new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ + accessRuleSet = new AccessRuleSet(accessRules, templates); + } else { + return; + } + } + if (Main.NONE.equals(destPath)) { + destPath = Main.NONE; // keep == comparison valid + } + if (rejectDestinationPathOnJars && destPath != null && + (currentClasspathName.endsWith(".jar") || //$NON-NLS-1$ + currentClasspathName.endsWith(".zip"))) { //$NON-NLS-1$ + throw new InvalidInputException( + this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$ + currentClasspathName)); + } + FileSystem.Classpath currentClasspath = FileSystem.getClasspath( + currentClasspathName, + customEncoding, + isSourceOnly, + accessRuleSet, + destPath); + if (currentClasspath != null) { + paths.add(currentClasspath); + } + } + /* + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string. + */ + private String bind(String id, String binding) { + return bind(id, new String[] { binding }); + } + + /* + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string values. + */ + private String bind(String id, String[] arguments) { + if (id == null) + return "No message available"; //$NON-NLS-1$ + String message = null; + try { + message = this.bundle.getString(id); + } catch (MissingResourceException e) { + // If we got an exception looking for the message, fail gracefully by just returning + // the id we were looking for. In most cases this is semi-informative so is not too bad. + return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$ + } + return MessageFormat.format(message, (Object[]) arguments); } } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java index 060b2fa060..3dbe398a09 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java @@ -9156,4 +9156,44 @@ public class ASTConverter15Test extends ConverterTestSetup { annotations = binding.getAnnotations(); assertEquals("Wrong size", 1, annotations.length); } + + //https://bugs.eclipse.org/bugs/show_bug.cgi?id=192774 + //Test ability to distinguish AST nodes of multiple similar annotations. + public void test0276() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter15/src/X.java", true/*resolve*/); + String contents = + "@interface Annot {\n" + + " public int value();\n" + + "}\n" + + "\n" + + "public class X {\n" + + " @Annot(1) String foo1() { return null; }\n" + + " @Annot(1) String foo2() { return null; }\n" + + "}"; + this.workingCopy.getBuffer().setContents(contents); + + class CompilationUnitRequestor extends ASTRequestor { + public void acceptAST(ICompilationUnit source, CompilationUnit node) { + MethodDeclaration methodDeclaration = (MethodDeclaration)getASTNode(node, 1, 0); + IMethodBinding methodBinding = methodDeclaration.resolveBinding(); + IAnnotationBinding annoBinding = methodBinding.getAnnotations()[0]; + ASTNode annoNode = node.findDeclaringNode(annoBinding); + int position1 = annoNode.getStartPosition(); + + methodDeclaration = (MethodDeclaration)getASTNode(node, 1, 1); + methodBinding = methodDeclaration.resolveBinding(); + IAnnotationBinding annoBinding2 = methodBinding.getAnnotations()[0]; + annoNode = node.findDeclaringNode(annoBinding2); + int position2 = annoNode.getStartPosition(); + assertTrue("Anno 2 position <= anno 1 position", position2 > position1); + } + } + + CompilationUnitRequestor requestor = new CompilationUnitRequestor(); + ASTParser parser = ASTParser.newParser(AST.JLS3); + parser.setResolveBindings(true); + parser.setProject(this.getJavaProject("Converter15")); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + parser.createASTs(new ICompilationUnit[]{this.workingCopy}, new String[0], requestor, null); + } } diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java index dc07ff336a..68544f8cf5 100644 --- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java +++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java @@ -130,7 +130,7 @@ FileSystem(Classpath[] paths, String[] initialFileNames) { public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet) { return getClasspath(classpathName, encoding, false, accessRuleSet, null); } -static Classpath getClasspath(String classpathName, String encoding, +public static Classpath getClasspath(String classpathName, String encoding, boolean isSourceOnly, AccessRuleSet accessRuleSet, String destinationPath) { Classpath result = null; diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java index 7e0b298720..fd18dbcbea 100644 --- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java +++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java @@ -1403,63 +1403,63 @@ protected void addNewEntry(ArrayList paths, String currentClasspathName, AccessRuleSet accessRuleSet = null; if (rulesSpecsSize != 0) { AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()]; - boolean rulesOK = true; - Iterator i = currentRuleSpecs.iterator(); - int j = 0; - while (i.hasNext()) { - String ruleSpec = (String) i.next(); - char key = ruleSpec.charAt(0); - String pattern = ruleSpec.substring(1); - if (pattern.length() > 0) { - switch (key) { - case '+': - accessRules[j++] = new AccessRule(pattern - .toCharArray(), 0); - break; - case '~': - accessRules[j++] = new AccessRule(pattern - .toCharArray(), - IProblem.DiscouragedReference); - break; - case '-': - accessRules[j++] = new AccessRule(pattern - .toCharArray(), - IProblem.ForbiddenReference); - break; - case '?': - accessRules[j++] = new AccessRule(pattern - .toCharArray(), - IProblem.ForbiddenReference, true/*keep looking for accessible type*/); - break; - default: - rulesOK = false; - } - } else { - rulesOK = false; - } - } - if (rulesOK) { - String templates[] = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH]; - templates[0] = this.bind( - "template.restrictedAccess.type", //$NON-NLS-1$ - new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ - templates[1] = this.bind( - "template.restrictedAccess.constructor", //$NON-NLS-1$ - new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ - templates[2] = this.bind( - "template.restrictedAccess.method", //$NON-NLS-1$ - new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ - templates[3] = this.bind( - "template.restrictedAccess.field", //$NON-NLS-1$ - new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ - accessRuleSet = new AccessRuleSet(accessRules, templates); - } else { - if (currentClasspathName.length() != 0) { - // we go on anyway - this.logger.logIncorrectClasspath(currentClasspathName); - } - return; - } + boolean rulesOK = true; + Iterator i = currentRuleSpecs.iterator(); + int j = 0; + while (i.hasNext()) { + String ruleSpec = (String) i.next(); + char key = ruleSpec.charAt(0); + String pattern = ruleSpec.substring(1); + if (pattern.length() > 0) { + switch (key) { + case '+': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), 0); + break; + case '~': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.DiscouragedReference); + break; + case '-': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.ForbiddenReference); + break; + case '?': + accessRules[j++] = new AccessRule(pattern + .toCharArray(), + IProblem.ForbiddenReference, true/*keep looking for accessible type*/); + break; + default: + rulesOK = false; + } + } else { + rulesOK = false; + } + } + if (rulesOK) { + String templates[] = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH]; + templates[0] = this.bind( + "template.restrictedAccess.type", //$NON-NLS-1$ + new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ + templates[1] = this.bind( + "template.restrictedAccess.constructor", //$NON-NLS-1$ + new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$ + templates[2] = this.bind( + "template.restrictedAccess.method", //$NON-NLS-1$ + new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ + templates[3] = this.bind( + "template.restrictedAccess.field", //$NON-NLS-1$ + new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$ + accessRuleSet = new AccessRuleSet(accessRules, templates); + } else { + if (currentClasspathName.length() != 0) { + // we go on anyway + this.logger.logIncorrectClasspath(currentClasspathName); + } + return; + } } if (NONE.equals(destPath)) { destPath = NONE; // keep == comparison valid @@ -3811,7 +3811,7 @@ public void setLocale(Locale locale) { /* * External API */ -protected void setDestinationPath(String dest) { +public void setDestinationPath(String dest) { this.destinationPath = dest; } /* diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html index 5581c10143..2b0316cb57 100644 --- a/org.eclipse.jdt.core/buildnotes_jdt-core.html +++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html @@ -52,7 +52,13 @@ Eclipse SDK 3.4M1 - %date% - 3.4 MILESTONE 1 </ul> <h3>Problem Reports Fixed</h3> -<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=171703">171703</a> +<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=191082">191082</a> +AnnotationMirror.getPosition() returns wrong value +<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=189799">189799</a> +[jsr269] Make getDocComment() behave more like javac +<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=192774">192774</a> +Annotation AST nodes should have unique IAnnotationBindings +<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=171703">171703</a> Eclipse cannot find source for *.class files <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=193979">193979</a> AST parser generates wrong AST diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java index 2f0aed6c34..3d72759801 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java @@ -16,8 +16,8 @@ import org.eclipse.jdt.internal.compiler.impl.Constant; public class ElementValuePair { char[] name; - Object value; - MethodBinding binding; + public Object value; + public MethodBinding binding; public static Object getValue(Expression expression) { if (expression == null) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java index 5e52670598..e59270a033 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java @@ -62,7 +62,6 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants { private SimpleLookupTable uniqueRawTypeBindings; private SimpleLookupTable uniqueWildcardBindings; private SimpleLookupTable uniqueParameterizedGenericMethodBindings; - private SimpleLookupTable uniqueAnnotationBindings; public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units public Object missingClassFileLocation = null; // only set when resolving certain references, to help locating problems @@ -82,7 +81,6 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOpt this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50 this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3); this.uniqueRawTypeBindings = new SimpleLookupTable(3); - this.uniqueAnnotationBindings = new SimpleLookupTable(3); this.uniqueWildcardBindings = new SimpleLookupTable(3); this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3); this.accessRestrictions = new HashMap(3); @@ -539,63 +537,10 @@ public TypeBinding convertUnresolvedBinaryToRawType(TypeBinding type) { * Used to guarantee annotation identity. */ public AnnotationBinding createAnnotation(ReferenceBinding annotationType, ElementValuePair[] pairs) { - // cached info is array of already created annotation binding for this type - AnnotationBinding[] cachedInfo = (AnnotationBinding[])this.uniqueAnnotationBindings.get(annotationType); - boolean needToGrow = false; - int index = 0; if (pairs.length != 0) { AnnotationBinding.setMethodBindings(annotationType, pairs); } - if (cachedInfo != null){ - nextCachedType : - // iterate existing parameterized for reusing one with same type arguments if any - for (int max = cachedInfo.length; index < max; index++){ - AnnotationBinding cachedType = cachedInfo[index]; - if (cachedType == null) break nextCachedType; - ElementValuePair[] elementValuePairs = cachedType.pairs; - int length2 = pairs.length; - if (length2 != elementValuePairs.length) continue nextCachedType; - loop: for (int i = 0; i < length2; i++) { - ElementValuePair pair = elementValuePairs[i]; - // loop on the given pair to make sure one will match - for (int j = 0; j < length2; j++) { - ElementValuePair pair2 = pairs[j]; - if (pair.binding == pair2.binding) { - if (pair.value == null) { - if (pair2.value == null) { - continue loop; - } - continue nextCachedType; - } else { - if (pair2.value == null - || !pair2.value.equals(pair.value)) { - continue nextCachedType; - } - } - continue loop; - } - } - // no match found for pair so we create a new annotation binding - continue nextCachedType; - } - // cached type match, reuse current - return cachedType; - } - needToGrow = true; - } else { - cachedInfo = new AnnotationBinding[1]; - this.uniqueAnnotationBindings.put(annotationType, cachedInfo); - } - // grow cache ? - int length = cachedInfo.length; - if (needToGrow && index == length){ - System.arraycopy(cachedInfo, 0, cachedInfo = new AnnotationBinding[length*2], 0, length); - this.uniqueAnnotationBindings.put(annotationType, cachedInfo); - } - // add new binding - AnnotationBinding annotationBinding = new AnnotationBinding(annotationType, pairs); - cachedInfo[index] = annotationBinding; - return annotationBinding; + return new AnnotationBinding(annotationType, pairs); } /* @@ -1248,7 +1193,6 @@ public void reset() { this.uniqueRawTypeBindings = new SimpleLookupTable(3); this.uniqueWildcardBindings = new SimpleLookupTable(3); this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3); - this.uniqueAnnotationBindings = new SimpleLookupTable(3); for (int i = this.units.length; --i >= 0;) this.units[i] = null; |