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 d80b1ba commit e620924
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 27 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$

private 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 @@ -1741,13 +1742,38 @@ private boolean checkVMVersion(long minimalSupportedVersion) {
}
return ClassFileConstants.getComplianceLevelForJavaVersion(majorVersion) >=minimalSupportedVersion;
}

protected SourceInfo getSourceInfo(int index) {
if (this.sourceInfos == null) {
return new SourceInfo(index, getOrNull(this.filenames, index), getOrNull(this.encodings, index), getOrNull(this.modNames, index), getOrNull(this.destinationPaths, index));
}
return this.sourceInfos[index];
}

private String getOrNull(String[] arr, int i) {
if (arr == null) {
return null;
}
return arr[i];
}

/*
* Low-level API performing the actual compilation
*/
public boolean compile(String[] argv) {
// decode command line arguments
try {
configure(argv);
// 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
if (this.filenames != null) {
SourceInfo[] info = new SourceInfo[this.filenames.length];
for (int i = 0; i < info.length; i++) {
info[i] = getSourceInfo(i);
}
Arrays.sort(info, Comparator.comparing(SourceInfo::filename));
this.sourceInfos = info;
}
if (this.progress != null)
this.progress.begin(this.filenames == null ? 0 : this.filenames.length * this.maxRepetition);
if (this.proceed) {
Expand Down Expand Up @@ -3363,31 +3389,27 @@ public CompilationUnit[] getCompilationUnits() {
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 = getSourceInfo(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 +3430,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 @@ -3586,50 +3608,66 @@ protected ArrayList<FileSystem.Classpath> handleModuleSourcepath(String arg) {
String moduleName = mod == null ? null : new String(mod.name());
for(int j = 0; j < this.filenames.length; j++) {
Path filePath;
SourceInfo info = getSourceInfo(j);
int idx = info.index();
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.modNames[idx] = moduleName;
this.destinationPaths[idx] = destPath;
if (this.sourceInfos != null) {
this.sourceInfos [idx] = new SourceInfo(idx, info.filename(), info.encoding(), moduleName, destPath);
}
}
} 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.modNames[idx] = ""; //$NON-NLS-1$
if (this.sourceInfos != null) {
this.sourceInfos[idx] = new SourceInfo(idx, 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$
SourceInfo info = getSourceInfo(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) {
return;
}
IModule singleMod = null;
for (String filename : this.filenames) {
IModule mod = extractModuleDesc(filename);
for (int i = 0; i < this.filenames.length; i++) {
SourceInfo info = getSourceInfo(i);
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;
SourceInfo info = getSourceInfo(i);
int idx = info.index();
this.modNames[idx] = moduleName;
if (this.sourceInfos != null) {
this.sourceInfos[idx] = new SourceInfo(idx, 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(int index, 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,7 @@ public char[] getContents() {
units.toArray(result);
return result;
}

/*
* Low-level API performing the actual compilation
*/
Expand Down

0 comments on commit e620924

Please sign in to comment.