### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java,v retrieving revision 1.65 diff -u -r1.65 BatchCompilerTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 26 Jun 2006 13:14:40 -0000 1.65 +++ src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 28 Jun 2006 09:07:45 -0000 @@ -865,10 +865,13 @@ " -sourcepath \n" + " specify location for application sources. Each directory\n" + " or file can specify access rules for types between ''[''\n" + - " and '']''.\n" + + " and '']''. Each directory can further specify a specific\n" + + " destination directory using a ''-d'' option between ''[''\n" + + " and '']''; this overrides the general ''-d'' option.\n" + " .class files created from source files contained in a\n" + " jar file are put in the user.dir folder in case no\n" + - " destination directory is specified.\n" + + " general ''-d'' option is specified. zip/jar files cannot\n" + + " override the general ''-d'' option\n" + " -extdirs \n" + " specify location for extension zip/jar files\n" + " -endorseddirs \n" + @@ -890,7 +893,8 @@ " -1.6 use 1.6 compliance level (implicit -source 1.6\n" + " -target 1.6)\n" + " -source set source level: 1.3 to 1.6 (or 5, 5.0, 6 or 6.0)\n" + - " -target set classfile target level: 1.1 to 1.6 (or 5, 5.0, 6 or 6.0)\n" + + " -target set classfile target level: 1.1 to 1.6 (or 5, 5.0, 6\n" + + " or 6.0)\n" + " \n" + " Warning options:\n" + " -deprecation + deprecation outside deprecated code\n" + @@ -3046,6 +3050,315 @@ "ERR: invalid spec", true); } + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// pre-existing case 1: using a single, definite output directory +public void test058_per_source_output_directory(){ + String source1 = "src1", + output1 = "bin1"; + this.runConformTest( + new String[] { + source1 + File.separator + "/X.java", + "public class X {}", + "Z.java", + "public class Z {\n" + + " X f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + + "Z.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + source1 + "\"" + + " -d \"" + OUTPUT_DIR + File.separator + output1 + "\"", + "", + "", + true); + String fileName = OUTPUT_DIR + File.separator + output1 + + File.separator + "X.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + output1 + + File.separator + "Z.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// pre-existing case 2: using no definite output directory +public void test059_per_source_output_directory(){ + String source1 = "src1"; + this.runConformTest( + new String[] { + source1 + File.separator + "/X.java", + "public class X {}", + "Z.java", + "public class Z {\n" + + " X f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + + "Z.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + source1 + "\"", + "", + "", + true); + String fileName = OUTPUT_DIR + File.separator + source1 + + File.separator + "X.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + "Z.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// new case 1: overriding the default output directory for one of the sources +public void test060_per_source_output_directory(){ + String source1 = "src1", + output1 = "bin1", output2 = "bin2"; + this.runConformTest( + new String[] { + source1 + File.separator + "/X.java", + "public class X {}", + "Z.java", + "public class Z {\n" + + " X f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + + "Z.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + source1 + "\"" + + "[-d \"" + OUTPUT_DIR + File.separator + output1 + "\"]" + + " -d \"" + OUTPUT_DIR + File.separator + output2 + "\"", + "", + "", + true); + String fileName = OUTPUT_DIR + File.separator + output1 + + File.separator + "X.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + source1 + + File.separator + "X.class"; + assertFalse("extraneous file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + output2 + + File.separator + "X.class"; + assertFalse("extraneous file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + output2 + + File.separator + "Z.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// new case 2: specifying an output directory for a given source directory only +public void test061_per_source_output_directory(){ + String source1 = "src1", + output1 = "bin1"; + this.runConformTest( + new String[] { + source1 + File.separator + "/X.java", + "public class X {}", + "Z.java", + "public class Z {\n" + + " X f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + + "Z.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + source1 + "\"" + + "[-d \"" + OUTPUT_DIR + File.separator + output1 + "\"]", + "", + "", + true); + String fileName = OUTPUT_DIR + File.separator + output1 + + File.separator + "X.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + source1 + + File.separator + "X.class"; + assertFalse("extraneous file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + "Z.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); +} + +// per sourcepath directory default encoding +// TODO (maxime) enter suggestion +public void _test062_per_sourcepath_directory_default_encoding(){ + String source1 = "src1"; + this.runConformTest( + new String[] { + source1 + File.separator + "/X.java", + "public class X {}", + "Z.java", + "public class Z {\n" + + " X f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + + "Z.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + source1 + + "[UTF-8]\"", + "", + "", + true); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// [-d none] is forbidden +public void test063_per_source_output_directory(){ + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " Zork z;\n" + + "}"}, + "\"" + OUTPUT_DIR + File.separator + + "X.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + "\"" + "[-d none]", + "", + "incorrect classpath: ---OUTPUT_DIR_PLACEHOLDER---[-d none]\n" + + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 2)\n" + + " Zork z;\n" + + " ^^^^\n" + + "Zork cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// [-d dir][rule] is forbidden +public void test064_per_source_output_directory(){ + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " Zork z;\n" + + "}"}, + "\"" + OUTPUT_DIR + File.separator + + "X.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + "\"" + "[-d dir][~**/internal/*]", + "", + "incorrect classpath: ---OUTPUT_DIR_PLACEHOLDER---[-d dir][~**/internal/*]\n" + + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 2)\n" + + " Zork z;\n" + + " ^^^^\n" + + "Zork cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// [rule][-d dir] is ok +public void test065_per_source_output_directory(){ + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " Zork z;\n" + + "}"}, + "\"" + OUTPUT_DIR + File.separator + + "X.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + "\"" + "[~**/internal/*][-d dir]", + "", + "----------\n" + + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 2)\n" + + " Zork z;\n" + + " ^^^^\n" + + "Zork cannot be resolved to a type\n" + + "----------\n" + + "1 problem (1 error)", + true); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// -cp dir[-d dir] is forbidden +public void test066_per_source_output_directory(){ + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " Zork z;\n" + + "}"}, + "\"" + OUTPUT_DIR + File.separator + + "X.java\"" + + " -1.5" + + " -cp \"" + OUTPUT_DIR + "\"" + "[-d dir]", + "", + "directory does not exist: dir]\n", + // not the best diagnostic we could imagine + true); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// -bootclasspath dir[-d dir] is forbidden +public void test067_per_source_output_directory(){ + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " Zork z;\n" + + "}"}, + "\"" + OUTPUT_DIR + File.separator + + "X.java\"" + + " -1.5" + + " -cp \"" + OUTPUT_DIR + "\"" + "[-d dir]", + "", + "directory does not exist: dir]\n", + // not the best diagnostic we could imagine + true); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=146554 +// per source directory output directory +// new case 3: overriding -d none for one of the sources +public void test068_per_source_output_directory(){ + String source1 = "src1", + output1 = "bin1", output2 = "bin2"; + this.runConformTest( + new String[] { + source1 + File.separator + "/X.java", + "public class X {}", + "Z.java", + "public class Z {\n" + + " X f;\n" + + "}", + }, + "\"" + OUTPUT_DIR + File.separator + + "Z.java\"" + + " -1.5" + + " -sourcepath \"" + OUTPUT_DIR + File.separator + source1 + "\"" + + "[-d \"" + OUTPUT_DIR + File.separator + output1 + "\"]" + + " -d none", + "", + "", + true); + String fileName = OUTPUT_DIR + File.separator + output1 + + File.separator + "X.class"; + assertTrue("missing file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + source1 + + File.separator + "X.class"; + assertFalse("extraneous file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + output2 + + File.separator + "X.class"; + assertFalse("extraneous file: " + fileName, (new File(fileName)).exists()); + fileName = OUTPUT_DIR + File.separator + output2 + + File.separator + "Z.class"; + assertFalse("extraneous file: " + fileName, (new File(fileName)).exists()); +} + public static Class testClass() { return BatchCompilerTest.class; } #P org.eclipse.jdt.core Index: batch/org/eclipse/jdt/internal/compiler/batch/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties,v retrieving revision 1.550 diff -u -r1.550 messages.properties --- batch/org/eclipse/jdt/internal/compiler/batch/messages.properties 20 Jun 2006 11:33:14 -0000 1.550 +++ batch/org/eclipse/jdt/internal/compiler/batch/messages.properties 28 Jun 2006 09:07:49 -0000 @@ -117,10 +117,13 @@ \ -sourcepath \n\ \ specify location for application sources. Each directory\n\ \ or file can specify access rules for types between ''[''\n\ -\ and '']''.\n\ +\ and '']''. Each directory can further specify a specific\n\ +\ destination directory using a ''-d'' option between ''[''\n\ +\ and '']''; this overrides the general ''-d'' option.\n\ \ .class files created from source files contained in a\n\ \ jar file are put in the user.dir folder in case no\n\ -\ destination directory is specified.\n\ +\ general ''-d'' option is specified. zip/jar files cannot\n\ +\ override the general ''-d'' option\n\ \ -extdirs \n\ \ specify location for extension zip/jar files\n\ \ -endorseddirs \n\ @@ -142,7 +145,8 @@ \ -1.6 use 1.6 compliance level (implicit -source 1.6\n\ \ -target 1.6)\n\ \ -source set source level: 1.3 to 1.6 (or 5, 5.0, 6 or 6.0)\n\ -\ -target set classfile target level: 1.1 to 1.6 (or 5, 5.0, 6 or 6.0)\n\ +\ -target set classfile target level: 1.1 to 1.6 (or 5, 5.0, 6\n\ +\ or 6.0)\n\ \ \n\ \ Warning options:\n\ \ -deprecation + deprecation outside deprecated code\n\ Index: batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java,v retrieving revision 1.39 diff -u -r1.39 FileSystem.java --- batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java 12 Apr 2006 15:31:24 -0000 1.39 +++ batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java 28 Jun 2006 09:07:47 -0000 @@ -94,16 +94,25 @@ initializeKnownFileNames(initialFileNames); } static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet) { - return getClasspath(classpathName, encoding, false, accessRuleSet); + return getClasspath(classpathName, encoding, false, accessRuleSet, null); } -static Classpath getClasspath(String classpathName, String encoding, boolean isSourceOnly, AccessRuleSet accessRuleSet) { +static Classpath getClasspath(String classpathName, String encoding, + boolean isSourceOnly, AccessRuleSet accessRuleSet, + String outputDirName) { Classpath result = null; File file = new File(convertPathSeparators(classpathName)); if (file.isDirectory()) { if (file.exists()) { - result = new ClasspathDirectory(file, encoding, isSourceOnly ? ClasspathLocation.SOURCE : ClasspathLocation.SOURCE | ClasspathLocation.BINARY, accessRuleSet); - } - } else { + result = new ClasspathDirectory(file, encoding, + isSourceOnly ? ClasspathLocation.SOURCE : + ClasspathLocation.SOURCE | ClasspathLocation.BINARY, + accessRuleSet, + outputDirName == null ? null : + new File(convertPathSeparators(outputDirName))); + } + } else if (outputDirName == null) { + // should not be non null for non directory entries (unless -d + // option becomes supported for jar/zip entries) String lowercaseClasspathName = classpathName.toLowerCase(); if (lowercaseClasspathName.endsWith(SUFFIX_STRING_jar) || lowercaseClasspathName.endsWith(SUFFIX_STRING_zip)) { Index: batch/org/eclipse/jdt/internal/compiler/batch/Main.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java,v retrieving revision 1.258 diff -u -r1.258 Main.java --- batch/org/eclipse/jdt/internal/compiler/batch/Main.java 26 Jun 2006 13:14:25 -0000 1.258 +++ batch/org/eclipse/jdt/internal/compiler/batch/Main.java 28 Jun 2006 09:07:49 -0000 @@ -1014,6 +1014,7 @@ public final static String bundleName = "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$ + public static final String NONE = "none"; //$NON-NLS-1$ static { relocalize(); } @@ -1171,7 +1172,9 @@ } } -private void addNewEntry(ArrayList paths, String currentClasspathName, ArrayList currentRuleSpecs, String customEncoding, boolean isSourceOnly) { +private void addNewEntry(ArrayList paths, String currentClasspathName, + ArrayList currentRuleSpecs, String customEncoding, String outputDirName, + boolean isSourceOnly) { AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()]; boolean rulesOK = true; Iterator i = currentRuleSpecs.iterator(); @@ -1227,7 +1230,8 @@ currentClasspathName, customEncoding, isSourceOnly, - accessRuleSet); + accessRuleSet, + outputDirName); if (currentClasspath != null) { paths.add(currentClasspath); } else { @@ -1322,12 +1326,14 @@ final int INSIDE_BOOTCLASSPATH = 8; final int INSIDE_MAX_PROBLEMS = 9; final int INSIDE_EXT_DIRS = 10; - final int INSIDE_SOURCE_PATH = 11; + final int INSIDE_SOURCE_PATH_start = 11; + final int INSIDE_SOURCE_PATH_bracket = 13; final int INSIDE_ENDORSED_DIRS = 12; final int DEFAULT = 0; final int DEFAULT_SIZE_CLASSPATH = 4; ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); + String sourcepathClasspathArg = null; ArrayList sourcepathClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); ArrayList classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); ArrayList extdirsClasspaths = null; @@ -1412,8 +1418,8 @@ switch(mode) { case DEFAULT : customEncoding = null; - if (currentArg.endsWith("]") && !(mode == INSIDE_BOOTCLASSPATH || mode == INSIDE_CLASSPATH || //$NON-NLS-1$ - mode == INSIDE_SOURCE_PATH) ) { + if (currentArg.endsWith("]") && !(mode == INSIDE_BOOTCLASSPATH || mode == INSIDE_CLASSPATH //$NON-NLS-1$ + ) ) { // look for encoding specification int encodingStart = currentArg.indexOf('[') + 1; int encodingEnd = currentArg.length() - 1; @@ -1560,7 +1566,7 @@ continue; } if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$ - if (sourcepathClasspaths.size() > 0) { + if (sourcepathClasspathArg != null) { StringBuffer errorMessage = new StringBuffer(); errorMessage.append(currentArg); if ((index + 1) < argCount) { @@ -1570,7 +1576,7 @@ throw new InvalidInputException( Main.bind("configure.duplicateSourcepath", errorMessage.toString())); //$NON-NLS-1$ } - mode = INSIDE_SOURCE_PATH; + mode = INSIDE_SOURCE_PATH_start; continue; } if (currentArg.equals("-extdirs")) {//$NON-NLS-1$ @@ -1692,7 +1698,7 @@ this.options.put( CompilerOptions.OPTION_SourceFileAttribute, CompilerOptions.DO_NOT_GENERATE); - if (length == 7 && debugOption.equals("-g:none")) //$NON-NLS-1$ + if (length == 7 && debugOption.equals("-g:" + NONE)) //$NON-NLS-1$ continue; StringTokenizer tokenizer = new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$ @@ -1729,7 +1735,7 @@ mode = DEFAULT; String warningOption = currentArg; int length = currentArg.length(); - if (length == 10 && warningOption.equals("-warn:none")) { //$NON-NLS-1$ + if (length == 10 && warningOption.equals("-warn:" + NONE)) { //$NON-NLS-1$ disableWarnings(); continue; } @@ -2230,9 +2236,53 @@ bootclasspaths.add(currentArg); mode = DEFAULT; continue; - case INSIDE_SOURCE_PATH : - sourcepathClasspaths.add(currentArg); + case INSIDE_SOURCE_PATH_start: + sourcepathClasspathArg = currentArg; mode = DEFAULT; + char[] currentArgChars = currentArg.toCharArray(); + for (int i = 0, length = currentArgChars.length; i < length; + i++) { + switch (currentArgChars[i]) { + case '[': + if (mode == INSIDE_SOURCE_PATH_bracket) { + // WORK error + } else { + mode = INSIDE_SOURCE_PATH_bracket; + } + break; + case ']': + if (mode != INSIDE_SOURCE_PATH_bracket) { + // WORK error + } else { + mode = DEFAULT; + } + break; + } + } + continue; + case INSIDE_SOURCE_PATH_bracket: + sourcepathClasspathArg += " " + currentArg; //$NON-NLS-1$ + mode = DEFAULT; + currentArgChars = currentArg.toCharArray(); + for (int i = 0, length = currentArgChars.length; i < length; + i++) { + switch (currentArgChars[i]) { + case '[': + if (mode == INSIDE_SOURCE_PATH_bracket) { + // WORK error + } else { + mode = INSIDE_SOURCE_PATH_bracket; + } + break; + case ']': + if (mode != INSIDE_SOURCE_PATH_bracket) { + // WORK error + } else { + mode = DEFAULT; + } + break; + } + } continue; case INSIDE_EXT_DIRS : StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator, false); @@ -2360,9 +2410,8 @@ if (current != null) { for (int j = 0, max2 = current.length; j < max2; j++) { FileSystem.Classpath classpath = - FileSystem.getClasspath( - current[j].getAbsolutePath(), - null, false, null); + FileSystem.getClasspath(current[j].getAbsolutePath(), + null, false, null, null); if (classpath != null) { bootclasspaths.add(classpath); } @@ -2402,14 +2451,9 @@ } } } - final int sourcepathClasspathsSize = sourcepathClasspaths.size(); - if (sourcepathClasspathsSize != 0) { - String[] paths = new String[sourcepathClasspathsSize]; - sourcepathClasspaths.toArray(paths); - sourcepathClasspaths.clear(); - for (int i = 0; i < sourcepathClasspathsSize; i++) { - processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepathClasspaths, paths[i], customEncoding, true); - } + if (sourcepathClasspathArg != null) { + processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepathClasspaths, + sourcepathClasspathArg, customEncoding, true); } if (filesCount != 0) @@ -2538,7 +2582,7 @@ if (this.destinationPath == null) { this.generatePackagesStructure = false; - } else if ("none".equals(this.destinationPath)) { //$NON-NLS-1$ + } else if (NONE.equals(this.destinationPath)) { this.destinationPath = null; } @@ -2802,10 +2846,25 @@ public void outputClassFiles(CompilationResult unitResult) { if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) { ClassFile[] classFiles = unitResult.getClassFiles(); - if (!this.generatePackagesStructure) { - this.destinationPath = extractDestinationPathFromSourceFile(unitResult); + String currentDestinationPath = null; + boolean currentGenerateClasspathStructure = false; + ClasspathDirectory classpathDirectory; + if ((classpathDirectory = ((CompilationUnit)unitResult.compilationUnit). + classpathDirectory) != null) { + currentDestinationPath = classpathDirectory. + getOutputDirectoryPath(); + currentGenerateClasspathStructure = true; + } + if (currentDestinationPath == null) { + if (this.generatePackagesStructure) { + currentDestinationPath = this.destinationPath; + currentGenerateClasspathStructure = true; + } else { + currentDestinationPath = + extractDestinationPathFromSourceFile(unitResult); + } } - if (this.destinationPath != null) { + if (currentDestinationPath != null) { for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) { // retrieve the key and the corresponding classfile ClassFile classFile = classFiles[i]; @@ -2826,19 +2885,19 @@ relativeStringName })); ClassFile.writeToDisk( - this.generatePackagesStructure, - this.destinationPath, + currentGenerateClasspathStructure, + currentDestinationPath, relativeStringName, classFile); LookupEnvironment env = this.batchCompiler.lookupEnvironment; if (classFile.isShared) env.classFilePool.release(classFile); this.logger.logClassFile( - this.generatePackagesStructure, - this.destinationPath, + currentGenerateClasspathStructure, + currentDestinationPath, relativeStringName); this.exportedClassFilesCounter++; } catch (IOException e) { - this.logger.logNoClassFileCreated(this.destinationPath, relativeStringName, e); + this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e); } } } @@ -2895,8 +2954,10 @@ this.logger.flush(); } -private void processPathEntries(final int defaultSize, final ArrayList paths, final String currentPath, String customEncoding, boolean isSourceOnly) { +private void processPathEntries(final int defaultSize, final ArrayList paths, + final String currentPath, String customEncoding, boolean isSourceOnly) { String currentClasspathName = null; + String currentOutputDirName = null; ArrayList currentRuleSpecs = new ArrayList(defaultSize); StringTokenizer tokenizer = new StringTokenizer(currentPath, File.pathSeparator + "[]", true); //$NON-NLS-1$ @@ -2914,20 +2975,28 @@ // 'path[' 'path1;path2[' final int rulesReadyToClose = 6; // 'path[rule' 'path[rule1;rule2' + final int outputDirReadyToClose = 7; + // 'path[-d bin' + final int readyToCloseEndingWithOutputDir = 8; + // 'path[-d bin]' 'path[rule][-d bin]' + final int outputDirStart = 9; + // 'path[rule][' final int error = 99; int state = start; String token = null; - while (tokenizer.hasMoreTokens()) { + while (tokenizer.hasMoreTokens() && state != error) { token = tokenizer.nextToken(); if (token.equals(File.pathSeparator)) { switch (state) { case start: + case readyToCloseOrOtherEntry: break; case readyToClose: case readyToCloseEndingWithRules: - case readyToCloseOrOtherEntry: + case readyToCloseEndingWithOutputDir: state = readyToCloseOrOtherEntry; - addNewEntry(paths, currentClasspathName, currentRuleSpecs, customEncoding, isSourceOnly); + addNewEntry(paths, currentClasspathName, currentRuleSpecs, + customEncoding, currentOutputDirName, isSourceOnly); currentRuleSpecs.clear(); break; case rulesReadyToClose: @@ -2941,6 +3010,9 @@ case readyToClose: state = rulesStart; break; + case readyToCloseEndingWithRules: + state = outputDirStart; + break; default: state = error; } @@ -2949,10 +3021,12 @@ case rulesReadyToClose: state = readyToCloseEndingWithRules; break; + case outputDirReadyToClose: + state = readyToCloseEndingWithOutputDir; + break; default: state = error; } - } else { // regular word switch (state) { @@ -2961,21 +3035,45 @@ state = readyToClose; currentClasspathName = token; break; - case rulesNeedAnotherRule: case rulesStart: + if (token.startsWith("-d ")) { //$NON-NLS-1$ + currentOutputDirName = token.substring(3).trim(); + if (NONE.equals(currentOutputDirName)) { + state = error; + } else { + state = outputDirReadyToClose; + } + break; + } // else we proceed with a rule + case rulesNeedAnotherRule: state = rulesReadyToClose; currentRuleSpecs.add(token); break; + case outputDirStart: + if (!token.startsWith("-d ")) { //$NON-NLS-1$ + state = error; + } else { + currentOutputDirName = token.substring(3).trim(); + if (NONE.equals(currentOutputDirName)) { + state = error; + } else { + state = outputDirReadyToClose; + } + } + break; default: state = error; } } } switch(state) { - case readyToClose : - case readyToCloseEndingWithRules : - case readyToCloseOrOtherEntry : - addNewEntry(paths, currentClasspathName, currentRuleSpecs, customEncoding, isSourceOnly); + case readyToCloseOrOtherEntry: + break; + case readyToClose: + case readyToCloseEndingWithRules: + case readyToCloseEndingWithOutputDir: + addNewEntry(paths, currentClasspathName, currentRuleSpecs, + customEncoding, currentOutputDirName, isSourceOnly); break; default : // we go on anyway Index: batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java,v retrieving revision 1.40 diff -u -r1.40 ClasspathDirectory.java --- batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java 12 Apr 2006 15:39:42 -0000 1.40 +++ batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java 28 Jun 2006 09:07:47 -0000 @@ -28,8 +28,10 @@ private String[] missingPackageHolder = new String[1]; private int mode; // ability to only consider one kind of files (source vs. binaries), by default use both private String encoding; // only useful if referenced in the source path +private String outputDirectoryPath; // only carried by sourcepath arguments -ClasspathDirectory(File directory, String encoding, int mode, AccessRuleSet accessRuleSet) { +ClasspathDirectory(File directory, String encoding, int mode, + AccessRuleSet accessRuleSet, File outputDirectory) { super(accessRuleSet); this.mode = mode; this.path = directory.getAbsolutePath(); @@ -37,6 +39,9 @@ this.path += File.separator; this.directoryCache = new Hashtable(11); this.encoding = encoding; + if (outputDirectory != null) { + this.outputDirectoryPath = outputDirectory.getAbsolutePath(); + } } String[] directoryList(String qualifiedPackageName) { String[] dirList = (String[]) this.directoryCache.get(qualifiedPackageName); @@ -88,14 +93,14 @@ String fullSourcePath = this.path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java; if (!binaryExists) return new NameEnvironmentAnswer(new CompilationUnit(null, - fullSourcePath, this.encoding), + fullSourcePath, this.encoding, this), fetchAccessRestriction(qualifiedBinaryFileName)); String fullBinaryPath = this.path + qualifiedBinaryFileName; long binaryModified = new File(fullBinaryPath).lastModified(); long sourceModified = new File(fullSourcePath).lastModified(); if (sourceModified > binaryModified) return new NameEnvironmentAnswer(new CompilationUnit(null, - fullSourcePath, this.encoding), + fullSourcePath, this.encoding, this), fetchAccessRestriction(qualifiedBinaryFileName)); } if (binaryExists) { @@ -132,6 +137,9 @@ } return this.normalizedPath; } +public String getOutputDirectoryPath() { + return this.outputDirectoryPath; +} public String getPath() { return this.path; } Index: batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java,v retrieving revision 1.30 diff -u -r1.30 CompilationUnit.java --- batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java 28 Mar 2006 20:30:01 -0000 1.30 +++ batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java 28 Jun 2006 09:07:47 -0000 @@ -23,8 +23,13 @@ public char[] fileName; public char[] mainTypeName; String encoding; + public ClasspathDirectory classpathDirectory; public CompilationUnit(char[] contents, String fileName, String encoding) { + this(contents, fileName, encoding, null); +} +public CompilationUnit(char[] contents, String fileName, String encoding, + ClasspathDirectory classpathDirectory) { this.contents = contents; char[] fileNameCharArray = fileName.toCharArray(); switch(File.separatorChar) { @@ -48,6 +53,9 @@ this.mainTypeName = CharOperation.subarray(fileNameCharArray, start, end); this.encoding = encoding; + this.classpathDirectory = classpathDirectory; + // set to null for all compilation unit locations but classpath + // directories } public char[] getContents() { if (this.contents != null)