Skip to content

Commit

Permalink
Capture all information of a source file into one SourceInfo record
Browse files Browse the repository at this point in the history
To get a consistent compilation order that is independent of the order
of arguments one needs to sort the files to process by name. As the name
might be related to to other information all of these are first captured
inside a SourceInfo record and are the sort this array by name, in the
following code always this sorted array is used and possibly updated
with additional information.
  • Loading branch information
laeubi committed Feb 1, 2024
1 parent 15503ea commit 7e45b2c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
import java.util.Set;
import java.util.StringTokenizer;
import java.util.function.Function;
import java.util.stream.IntStream;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
Expand Down Expand Up @@ -1446,6 +1445,8 @@ public static synchronized ResourceBundle getBundle(Locale locale) {

public static final String NONE = "none"; //$NON-NLS-1$

protected SourceInfo[] sourceInfos;

/**
* @deprecated - use {@link BatchCompiler#compile(String, PrintWriter, PrintWriter, CompilationProgress)} instead
* e.g. BatchCompiler.compile(commandLine, new PrintWriter(System.out), new PrintWriter(System.err), null);
Expand Down Expand Up @@ -1748,6 +1749,17 @@ public boolean compile(String[] argv) {
// decode command line arguments
try {
configure(argv);
if (this.filenames == null) {
this.sourceInfos = new SourceInfo[0];
} else {
this.sourceInfos = new SourceInfo[this.filenames.length];
for (int i = 0; i < this.sourceInfos.length; i++) {
this.sourceInfos[i] = new SourceInfo(this.filenames[i], this.encodings[i], this.modNames[i], this.destinationPaths[i]);
}
// sort array by file names so we have a consistent order of compiling / handling them
// this is important as the order can influence the way for example lamda numbers are generated
Arrays.sort(this.sourceInfos, Comparator.comparing(SourceInfo::filename));
}
if (this.progress != null)
this.progress.begin(this.filenames == null ? 0 : this.filenames.length * this.maxRepetition);
if (this.proceed) {
Expand Down Expand Up @@ -3356,38 +3368,34 @@ public ICompilerRequestor getBatchRequestor() {
* Build the set of compilation source units
*/
public CompilationUnit[] getCompilationUnits() {
int fileCount = this.filenames.length;
int fileCount = this.sourceInfos.length;
CompilationUnit[] units = new CompilationUnit[fileCount];
HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);

String defaultEncoding = this.options.get(CompilerOptions.OPTION_Encoding);
if (Util.EMPTY_STRING.equals(defaultEncoding))
defaultEncoding = null;
// sort index by file names so we have a consistent order of compiling / handling them
// this is important as the order can influence the way for example lamda numbers are generated
int[] orderedIndex = IntStream.range(0, fileCount).boxed().sorted((i1, i2) -> {
return this.filenames[i1].compareTo(this.filenames[i2]);
}).mapToInt(i -> i).toArray();
for (int round = 0; round < 2; round++) {
for (int i : orderedIndex) {
char[] charName = this.filenames[i].toCharArray();
for (int unit = 0; unit < units.length; unit++) {
SourceInfo info = this.sourceInfos[unit];
char[] charName = info.filename().toCharArray();
boolean isModuleInfo = CharOperation.endsWith(charName, TypeConstants.MODULE_INFO_FILE_NAME);
if (isModuleInfo == (round==0)) { // 1st round: modules, 2nd round others (to ensure populating pathToModCU well in time)
if (knownFileNames.get(charName) != null)
throw new IllegalArgumentException(this.bind("unit.more", this.filenames[i])); //$NON-NLS-1$
throw new IllegalArgumentException(this.bind("unit.more", info.filename())); //$NON-NLS-1$
knownFileNames.put(charName, charName);
File file = new File(this.filenames[i]);
File file = new File(info.filename());
if (!file.exists())
throw new IllegalArgumentException(this.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$
String encoding = this.encodings[i];
throw new IllegalArgumentException(this.bind("unit.missing", info.filename())); //$NON-NLS-1$
String encoding = info.encoding();
if (encoding == null)
encoding = defaultEncoding;
String fileName;
try {
fileName = file.getCanonicalPath();
} catch (IOException e) {
// if we got exception during canonicalization, fall back to the name that was specified
fileName = this.filenames[i];
fileName = info.filename();
}
Function<String,String> annotationPathProvider = null;
if (this.annotationsFromClasspath) {
Expand All @@ -3408,9 +3416,9 @@ public CompilationUnit[] getCompilationUnits() {
return null;
};
}
units[i] = new CompilationUnit(null, fileName, encoding, this.destinationPaths[i],
units[unit] = new CompilationUnit(null, fileName, encoding, info.destinationPath(),
shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()),
this.modNames[i], annotationPathProvider);
info.moduleName(), annotationPathProvider);
}
}
}
Expand Down Expand Up @@ -3464,7 +3472,9 @@ public File getJavaHome() {
}

public FileSystem getLibraryAccess() {
FileSystem nameEnvironment = new FileSystem(this.checkedClasspaths, this.filenames,
String[] names = this.sourceInfos == null ? this.filenames
: Arrays.stream(this.sourceInfos).map(SourceInfo::filename).toArray(String[]::new);
FileSystem nameEnvironment = new FileSystem(this.checkedClasspaths, names,
this.annotationsFromClasspath && CompilerOptions.ENABLED.equals(this.options.get(CompilerOptions.OPTION_AnnotationBasedNullAnalysis)),
this.limitedModules);
nameEnvironment.module = this.module;
Expand Down Expand Up @@ -3584,52 +3594,54 @@ protected ArrayList<FileSystem.Classpath> handleModuleSourcepath(String arg) {
String destPath = classpath.getDestinationPath();
IModule mod = classpath.getModule();
String moduleName = mod == null ? null : new String(mod.name());
for(int j = 0; j < this.filenames.length; j++) {
for(int s = 0; s < this.sourceInfos.length; s++) {
Path filePath;
SourceInfo info = this.sourceInfos[s];
try {
// Get canonical path just as the classpath location is stored with the same.
// To avoid mismatch of /USER_JAY and /USE~1 in windows systems.
filePath = new File(this.filenames[j]).getCanonicalFile().toPath();
filePath = new File(info.filename()).getCanonicalFile().toPath();
if (filePath.startsWith(modLocation)) {
this.modNames[j] = moduleName;
this.destinationPaths[j] = destPath;
this.sourceInfos[s] = new SourceInfo(info.filename(), info.encoding(), destPath, moduleName);
}
} catch (IOException e) {
// Files doesn't exist and perhaps doesn't belong in a module, move on to other files
// Use empty module name to distinguish from missing module case
this.modNames[j] = ""; //$NON-NLS-1$
this.sourceInfos[s] = new SourceInfo(info.filename(), info.encoding(), "", info.destinationPath()); //$NON-NLS-1$
}
}
}
}
}
for(int j = 0; j < this.filenames.length; j++) {
if (this.modNames[j] == null) {
throw new IllegalArgumentException(this.bind("configure.notOnModuleSourcePath", new String[] {this.filenames[j]})); //$NON-NLS-1$
for(int j = 0; j < this.sourceInfos.length; j++) {
SourceInfo info = this.sourceInfos[j];
if (info.moduleName() == null) {
throw new IllegalArgumentException(this.bind("configure.notOnModuleSourcePath", new String[] {info.filename()})); //$NON-NLS-1$
}
}
}
return result;
}
private void handleSingleModuleCompilation() {
if (this.filenames == null) {
if (this.sourceInfos == null) {
return;
}
IModule singleMod = null;
for (String filename : this.filenames) {
IModule mod = extractModuleDesc(filename);
for (SourceInfo info : this.sourceInfos) {
IModule mod = extractModuleDesc(info.filename());
if (mod != null) {
if (singleMod == null) {
singleMod = mod;
} else {
addPendingErrors(this.bind("configure.duplicateModuleInfo", filename)); //$NON-NLS-1$
addPendingErrors(this.bind("configure.duplicateModuleInfo", info.filename())); //$NON-NLS-1$
}
}
}
if (singleMod != null) {
String moduleName = new String(singleMod.name());
for (int i = 0; i < this.modNames.length; i++) {
this.modNames[i] = moduleName;
for (int i = 0; i < this.sourceInfos.length; i++) {
SourceInfo info = this.sourceInfos[i];
this.sourceInfos[i] = new SourceInfo(info.filename(),info.encoding(), moduleName, info.destinationPath());
}
this.module = singleMod;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2024 Christoph Läubrich.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christoph Läubrich - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.batch;

/**
* Collects all information of a source file
*/
public record SourceInfo(String filename, String encoding, String moduleName, String destinationPath) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
import org.eclipse.jdt.internal.compiler.batch.Main;
import org.eclipse.jdt.internal.compiler.batch.SourceInfo;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
Expand Down Expand Up @@ -174,11 +175,12 @@ public CompilationUnit[] getCompilationUnits() {
throw new IllegalArgumentException(this.bind("unit.missing", name)); //$NON-NLS-1$
}

SourceInfo sourceInfo = getSourceInfo(i);
CompilationUnit cu = new CompilationUnit(null,
name,
null,
this.destinationPaths[i],
shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, name.toCharArray()), this.modNames[i]) {
sourceInfo.destinationPath(),
shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, name.toCharArray()), sourceInfo.moduleName()) {

@Override
public char[] getContents() {
Expand All @@ -200,6 +202,14 @@ public char[] getContents() {
units.toArray(result);
return result;
}

private SourceInfo getSourceInfo(int index) {
if (this.sourceInfos!=null) {
return this.sourceInfos[index];
} else {
return new SourceInfo("", "", this.modNames[index], this.destinationPaths[index]); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/*
* Low-level API performing the actual compilation
*/
Expand Down

0 comments on commit 7e45b2c

Please sign in to comment.