### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java,v retrieving revision 1.95.4.2 diff -u -r1.95.4.2 BinaryTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 6 Sep 2006 18:11:37 -0000 1.95.4.2 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 12 Oct 2006 11:00:16 -0000 @@ -144,7 +144,12 @@ return type; } - +/** + * Standard constructor for creating binary type bindings from binary models (classfiles) + * @param packageBinding + * @param binaryType + * @param environment + */ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) { this.compoundName = CharOperation.splitOn('/', binaryType.getName()); computeId(); @@ -183,6 +188,29 @@ } } +/** + * Special constructor for constructing proxies of missing binary types (114349) + * @param packageBinding + * @param compoundName + * @param environment + */ +BinaryTypeBinding(PackageBinding packageBinding, char[][] compoundName, LookupEnvironment environment) { + this.compoundName = compoundName; + computeId(); + this.tagBits |= TagBits.IsBinaryBinding; + this.environment = environment; + this.fPackage = packageBinding; + this.fileName = CharOperation.concatWith(compoundName, '/'); + this.sourceName = CharOperation.concatWith(compoundName, '.'); + this.modifiers = ClassFileConstants.AccPublic; + this.superclass = null; + this.superInterfaces = Binding.NO_SUPERINTERFACES; + this.typeVariables = Binding.NO_TYPE_VARIABLES; + this.memberTypes = Binding.NO_MEMBER_TYPES; + this.fields = Binding.NO_FIELDS; + this.methods = Binding.NO_METHODS; +} + public FieldBinding[] availableFields() { if ((this.tagBits & TagBits.AreFieldsComplete) != 0) return fields; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java,v retrieving revision 1.72 diff -u -r1.72 LookupEnvironment.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java 11 May 2006 10:14:34 -0000 1.72 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java 12 Oct 2006 11:00:17 -0000 @@ -173,6 +173,27 @@ return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods, accessRestriction); return null; // the type already exists & can be retrieved from the cache } + +public BinaryTypeBinding cacheMissingBinaryType(char[][] compoundName) { + PackageBinding packageBinding = getPackage0(compoundName[0]); + if (packageBinding == null || packageBinding == TheNotFoundPackage) { + packageBinding = new PackageBinding(compoundName[0], this); + knownPackages.put(compoundName[0], packageBinding); + } + for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) { + PackageBinding subPackageBinding = packageBinding.getPackage0(compoundName[i]); + if (subPackageBinding == null || subPackageBinding == TheNotFoundPackage) { + char[][] subName = CharOperation.subarray(compoundName, 0, i + 1); + subPackageBinding = new PackageBinding(subName, packageBinding, this); + packageBinding.addPackage(subPackageBinding); + packageBinding = subPackageBinding; + } + } + // create a proxy for the missing BinaryType + BinaryTypeBinding type = new BinaryTypeBinding(packageBinding, compoundName, this); + packageBinding.addType(type); + return type; +} /* * 1. Connect the type hierarchy for the type bindings created for parsedUnits. * 2. Create the field bindings @@ -859,8 +880,8 @@ ReferenceBinding type = getType(compoundName); if (type != null) return type; - problemReporter.isClassPathCorrect(compoundName, scope == null ? null : scope.referenceCompilationUnit()); - return null; // will not get here since the above error aborts the compilation + problemReporter.isClassPathCorrect(compoundName, scope == null ? this.unitBeingCompleted : scope.referenceCompilationUnit()); + return cacheMissingBinaryType(compoundName); // create a proxy for the missing BinaryType } /* Answer the top level package named name. * Ask the oracle for the package if its not in the cache. @@ -957,14 +978,15 @@ binding = new UnresolvedReferenceBinding(compoundName, packageBinding); packageBinding.addType(binding); } else if (binding == TheNotFoundType) { - problemReporter.isClassPathCorrect(compoundName, null); - return null; // will not get here since the above error aborts the compilation + problemReporter.isClassPathCorrect(compoundName, this.unitBeingCompleted); + return cacheMissingBinaryType(compoundName); // create a proxy for the missing BinaryType } else if (!isParameterized) { // check raw type, only for resolved types binding = (ReferenceBinding)convertUnresolvedBinaryToRawType(binding); } return binding; } + /* Answer the type corresponding to the name from the binary file. * Does not ask the oracle for the type if its not found in the cache... instead an * unresolved type is returned which must be resolved before used. Index: compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java,v retrieving revision 1.100.4.1 diff -u -r1.100.4.1 CompilationUnitScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java 2 Jul 2006 10:11:49 -0000 1.100.4.1 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java 12 Oct 2006 11:00:16 -0000 @@ -550,9 +550,12 @@ importBinding = ((PackageBinding) importBinding).getTypeOrPackage(JAVA_LANG[1]); // abort if java.lang cannot be found... - if (importBinding == null || !importBinding.isValidBinding()) + if (importBinding == null || !importBinding.isValidBinding()) { problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit()); + BinaryTypeBinding missingObject = environment.cacheMissingBinaryType(JAVA_LANG_OBJECT); // create a proxy for the missing BinaryType + importBinding = missingObject.fPackage; + } return environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)}; } // NOT Public API Index: compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java,v retrieving revision 1.26 diff -u -r1.26 UnresolvedReferenceBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java 10 May 2006 18:03:50 -0000 1.26 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java 12 Oct 2006 11:00:17 -0000 @@ -41,12 +41,11 @@ targetType = this.fPackage.getType0(this.compoundName[this.compoundName.length - 1]); if (targetType == this) targetType = environment.askForType(this.compoundName); - if (targetType != null && targetType != this) { // could not resolve any better, error was already reported against it - setResolvedType(targetType, environment); - } else { - environment.problemReporter.isClassPathCorrect(this.compoundName, null); - return null; // will not get here since the above error aborts the compilation + if (targetType == null || targetType == this) { // could not resolve any better, error was already reported against it + environment.problemReporter.isClassPathCorrect(this.compoundName, environment.unitBeingCompleted); + targetType = environment.cacheMissingBinaryType(this.compoundName); // create a proxy for the missing BinaryType } + setResolvedType(targetType, environment); } if (convertGenericToRawType) { targetType = (ReferenceBinding) environment.convertUnresolvedBinaryToRawType(targetType); Index: compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java,v retrieving revision 1.311.4.4 diff -u -r1.311.4.4 ProblemReporter.java --- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 6 Oct 2006 09:17:11 -0000 1.311.4.4 +++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 12 Oct 2006 11:00:21 -0000 @@ -3387,14 +3387,13 @@ argument.type.sourceStart, argument.sourceEnd); } -public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl) { +public void isClassPathCorrect(char[][] expectedTypeName, CompilationUnitDeclaration compUnitDecl) { this.referenceContext = compUnitDecl; - String[] arguments = new String[] {CharOperation.toString(wellKnownTypeName)}; + String[] arguments = new String[] {CharOperation.toString(expectedTypeName)}; this.handle( IProblem.IsClassPathCorrect, arguments, arguments, - ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal, 0, 0); } Index: model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java =================================================================== RCS file: model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java diff -N model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java --- model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java 10 May 2006 18:03:50 -0000 1.8 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,25 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 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.core.builder; - -/** - * Exception thrown when the build should be aborted because a referenced - * class file cannot be found. - */ -public class MissingClassFileException extends RuntimeException { - - protected String missingClassFile; - private static final long serialVersionUID = 3060418973806972616L; // backward compatible - -public MissingClassFileException(String missingClassFile) { - this.missingClassFile = missingClassFile; -} -} Index: model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java,v retrieving revision 1.96 diff -u -r1.96 AbstractImageBuilder.java --- model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java 25 Apr 2006 20:39:49 -0000 1.96 +++ model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java 12 Oct 2006 11:00:21 -0000 @@ -50,6 +50,7 @@ private boolean inCompiler; +protected String missingClassFileName; protected SimpleSet filesWithAnnotations = null; public static int MAX_AT_ONCE = 2000; // best compromise between space used and speed @@ -84,6 +85,7 @@ this.nameEnvironment = javaBuilder.nameEnvironment; this.sourceLocations = this.nameEnvironment.sourceLocations; this.notifier = javaBuilder.notifier; + this.missingClassFileName = null; if (buildStarting) { this.newState = newState == null ? new State(javaBuilder) : newState; @@ -545,8 +547,10 @@ */ protected void storeProblemsFor(SourceFile sourceFile, CategorizedProblem[] problems) throws CoreException { if (sourceFile == null || problems == null || problems.length == 0) return; + // once a classpath error is found, ignore all other problems for this project so the user can see the main error + // but still try to compile as many source files as possible to help the case when the base libraries are in source + if (this.missingClassFileName != null) return; - String missingClassFile = null; IResource resource = sourceFile.resource; HashSet managedMarkerTypes = JavaModelManager.getJavaModelManager().compilationParticipants.managedMarkerTypes(); for (int i = 0, l = problems.length; i < l; i++) { @@ -555,14 +559,20 @@ if (id == IProblem.IsClassPathCorrect) { JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject); // make this the only problem for this project String[] args = problem.getArguments(); - missingClassFile = args[0]; + this.missingClassFileName = args[0]; + + if (JavaBuilder.DEBUG) + System.out.println(Messages.bind(Messages.build_incompleteClassPath, this.missingClassFileName)); + IMarker marker = this.javaBuilder.currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_incompleteClassPath, this.missingClassFileName)); + marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); + marker.setAttribute(IJavaModelMarker.CATEGORY_ID, CategorizedProblem.CAT_BUILDPATH); } - + String markerType = problem.getMarkerType(); - if (IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER.equals(markerType) - || managedMarkerTypes.contains(markerType)) { + if (IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER.equals(markerType) || managedMarkerTypes.contains(markerType)) { IMarker marker = resource.createMarker(markerType); - + // standard attributes marker.setAttributes( JAVA_PROBLEM_MARKER_ATTRIBUTE_NAMES, @@ -584,8 +594,7 @@ marker.setAttributes(extraAttributeNames, problem.getExtraMarkerAttributeValues()); } } - if (missingClassFile != null) - throw new MissingClassFileException(missingClassFile); + if (this.missingClassFileName != null) return; // only want the one error recorded on this source file } } Index: model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java,v retrieving revision 1.122 diff -u -r1.122 JavaBuilder.java --- model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java 6 Apr 2006 19:15:52 -0000 1.122 +++ model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java 12 Oct 2006 11:00:21 -0000 @@ -209,14 +209,6 @@ marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_inconsistentProject, e.getLocalizedMessage())); marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); marker.setAttribute(IJavaModelMarker.CATEGORY_ID, CategorizedProblem.CAT_BUILDPATH); - } catch (MissingClassFileException e) { - // do not log this exception since its thrown to handle aborted compiles because of missing class files - if (DEBUG) - System.out.println(Messages.bind(Messages.build_incompleteClassPath, e.missingClassFile)); - IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_incompleteClassPath, e.missingClassFile)); - marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); - marker.setAttribute(IJavaModelMarker.CATEGORY_ID, CategorizedProblem.CAT_BUILDPATH); } catch (MissingSourceFileException e) { // do not log this exception since its thrown to handle aborted compiles because of missing source files if (DEBUG) #P org.eclipse.jdt.core.tests.builder Index: src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java,v retrieving revision 1.41 diff -u -r1.41 MultiProjectTests.java --- src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java 6 Apr 2006 19:16:04 -0000 1.41 +++ src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java 12 Oct 2006 11:00:23 -0000 @@ -780,6 +780,178 @@ } } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=114349 +// this one fails; compare with testCycle7 (only one change in Object source), +// which passes + public void testCycle6() throws JavaModelException { + Hashtable options = JavaCore.getOptions(); + Hashtable newOptions = JavaCore.getOptions(); + newOptions.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.WARNING); + + JavaCore.setOptions(newOptions); + + //---------------------------- + // Project1 + //---------------------------- + IPath p1 = env.addProject("P1"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p1, ""); + IPath root1 = env.addPackageFragmentRoot(p1, "src"); + env.setOutputFolder(p1, "bin"); + + env.addClass(root1, "java/lang", "Object", + "package java.lang;\n" + + "public class Object {\n" + + " Class getClass() { return null; }\n" + + " String toString() { return \"\"; }\n" + // the line that changes + "}\n" + ); + + //---------------------------- + // Project2 + //---------------------------- + IPath p2 = env.addProject("P2"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p2, ""); + IPath root2 = env.addPackageFragmentRoot(p2, "src"); + env.setOutputFolder(p2, "bin"); + + env.addClass(root2, "java/lang", "Class", + "package java.lang;\n" + + "public class Class {\n" + + " String getName() { return \"\"; };\n" + + "}\n" + ); + + //---------------------------- + // Project3 + //---------------------------- + IPath p3 = env.addProject("P3"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p3, ""); + IPath root3 = env.addPackageFragmentRoot(p3, "src"); + env.setOutputFolder(p3, "bin"); + + env.addClass(root3, "java/lang", "String", + "package java.lang;\n" + + "public class String {\n" + + "}\n" + ); + + // Dependencies + IPath[] accessiblePaths = new IPath[] {new Path("java/lang/*")}; + IPath[] forbiddenPaths = new IPath[] {new Path("**/*")}; + env.addRequiredProject(p1, p2, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p1, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p2, accessiblePaths, forbiddenPaths, false); + + try { + fullBuild(); + + expectingOnlySpecificProblemsFor(p1,new Problem[]{ + new Problem("p1", "A cycle was detected in the build path of project: P1", p1, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p2,new Problem[]{ + new Problem("p2", "A cycle was detected in the build path of project: P2", p2, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p3,new Problem[]{ + new Problem("p3", "A cycle was detected in the build path of project: P3", p3, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + + } finally { + JavaCore.setOptions(options); + } + } + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=114349 +// this one passes; compare with testCycle6 (only one change in Object source), +// which fails + public void testCycle7() throws JavaModelException { + Hashtable options = JavaCore.getOptions(); + Hashtable newOptions = JavaCore.getOptions(); + newOptions.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.WARNING); + + JavaCore.setOptions(newOptions); + + //---------------------------- + // Project1 + //---------------------------- + IPath p1 = env.addProject("P1"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p1, ""); + IPath root1 = env.addPackageFragmentRoot(p1, "src"); + env.setOutputFolder(p1, "bin"); + + env.addClass(root1, "java/lang", "Object", + "package java.lang;\n" + + "public class Object {\n" + + " Class getClass() { return null; }\n" + + " String toString() { return null; }\n" + // the line that changes + "}\n" + ); + + //---------------------------- + // Project2 + //---------------------------- + IPath p2 = env.addProject("P2"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p2, ""); + IPath root2 = env.addPackageFragmentRoot(p2, "src"); + env.setOutputFolder(p2, "bin"); + + env.addClass(root2, "java/lang", "Class", + "package java.lang;\n" + + "public class Class {\n" + + " String getName() { return \"\"; };\n" + + "}\n" + ); + + //---------------------------- + // Project3 + //---------------------------- + IPath p3 = env.addProject("P3"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p3, ""); + IPath root3 = env.addPackageFragmentRoot(p3, "src"); + env.setOutputFolder(p3, "bin"); + + env.addClass(root3, "java/lang", "String", + "package java.lang;\n" + + "public class String {\n" + + "}\n" + ); + + // Dependencies + IPath[] accessiblePaths = new IPath[] {new Path("java/lang/*")}; + IPath[] forbiddenPaths = new IPath[] {new Path("**/*")}; + env.addRequiredProject(p1, p2, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p1, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p2, accessiblePaths, forbiddenPaths, false); + + try { + fullBuild(); + + expectingOnlySpecificProblemsFor(p1,new Problem[]{ + new Problem("p1", "A cycle was detected in the build path of project: P1", p1, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p2,new Problem[]{ + new Problem("p2", "A cycle was detected in the build path of project: P2", p2, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p3,new Problem[]{ + new Problem("p3", "A cycle was detected in the build path of project: P3", p3, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + + } finally { + JavaCore.setOptions(options); + } + } + /* * Full buid case */