diff options
11 files changed, 504 insertions, 80 deletions
diff --git a/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java b/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java index 4ab05c968..5577a01af 100644 --- a/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java +++ b/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java @@ -37,6 +37,7 @@ import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; import org.aspectj.bridge.SourceLocation; import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.aspectj.util.LangUtil; @@ -277,6 +278,14 @@ public class AjdeCoreBuildManager { both.addAll(configClasspath); both.addAll(toAdd); config.setClasspath(both); + Classpath[] checkedClasspaths = config.getCheckedClasspaths(); + ArrayList<Classpath> cps = parser.handleClasspath(toAdd, compilerConfig.getProjectEncoding()); + Classpath[] newCheckedClasspaths = new Classpath[checkedClasspaths.length+cps.size()]; + System.arraycopy(checkedClasspaths, 0, newCheckedClasspaths, 0, checkedClasspaths.length); + for (int i=0;i<cps.size();i++) { + newCheckedClasspaths[checkedClasspaths.length+i] = cps.get(i); + } + config.setCheckedClasspaths(newCheckedClasspaths); } } @@ -295,18 +304,18 @@ public class AjdeCoreBuildManager { } // Process the INPATH - mergeInto(config.getInpath(), compilerConfig.getInpath()); + config.addToInpath(compilerConfig.getInpath()); // bug 168840 - calling 'setInPath(..)' creates BinarySourceFiles which // are used to see if there have been changes in classes on the inpath if (config.getInpath() != null) { - config.setInPath(config.getInpath()); + config.processInPath(); } // Process the SOURCE PATH RESOURCES config.setSourcePathResources(compilerConfig.getSourcePathResources()); // Process the ASPECTPATH - mergeInto(config.getAspectpath(), compilerConfig.getAspectPath()); + config.addToAspectpath(compilerConfig.getAspectPath()); // Process the JAVA OPTIONS MAP Map<String,String> jom = compilerConfig.getJavaOptionsMap(); @@ -347,17 +356,6 @@ public class AjdeCoreBuildManager { return config; } - private <T> void mergeInto(Collection<T> target, Collection<T> source) { - if ((null == target) || (null == source)) { - return; - } - for (T next : source) { - if (!target.contains(next)) { - target.add(next); - } - } - } - /** * Helper method for configure build options. This reads all command-line options specified in the non-standard options text * entry and sets any corresponding unset values in config. diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java index fae1aadd3..c061208f0 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java @@ -17,8 +17,10 @@ import org.aspectj.ajdt.internal.core.builder.AjBuildConfig; import org.aspectj.bridge.*; import org.aspectj.org.eclipse.jdt.core.compiler.CategorizedProblem; import org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.AptProblem; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.aspectj.org.eclipse.jdt.internal.compiler.batch.Main; import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModule; import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.aspectj.util.FileUtil; import org.aspectj.util.LangUtil; @@ -162,6 +164,11 @@ public class BuildArgParser extends Main { javaArgList.addAll(parser.getUnparsedArgs()); super.configure(javaArgList.toArray(new String[javaArgList.size()])); + if (parser.getModuleInfoArgument() != null) { + IModule moduleDesc = super.getModuleDesc(parser.getModuleInfoArgument()); + buildConfig.setModuleDesc(moduleDesc); + } + if (!proceed) { buildConfig.doNotProceed(); return buildConfig; @@ -181,8 +188,14 @@ public class BuildArgParser extends Main { } if (setClasspath) { + // This computed classpaths will be missing aspectpaths, inpaths, add those first buildConfig.setClasspath(getClasspath(parser)); + buildConfig.setModulepath(getModulepath(parser)); + buildConfig.setModulepathClasspathEntries(handleModulepath(parser.modulepath)); + buildConfig.setModulesourcepath(getModulesourcepath(parser)); + buildConfig.setModulesourcepathClasspathEntries(handleModuleSourcepath(parser.modulesourcepath)); buildConfig.setBootclasspath(getBootclasspath(parser)); + // TODO other paths (module/module source) } if (incrementalMode && (0 == buildConfig.getSourceRoots().size())) { @@ -214,8 +227,7 @@ public class BuildArgParser extends Main { } /* Search aspectpath */ - for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) { - File pathElement = (File) i.next(); + for (File pathElement: buildConfig.getAspectpath()) { if (!pathElement.isDirectory() && pathElement.equals(outjar)) { String message = WeaverMessages.format(WeaverMessages.OUTJAR_IN_INPUT_PATH); MessageUtil.error(handler, message); @@ -237,6 +249,28 @@ public class BuildArgParser extends Main { return buildConfig; } + private void augmentCheckedClasspaths(List<File> extraPathEntries, String encoding) { + if (extraPathEntries.size() == 0) { + return; + } + ArrayList<String> asList = toArrayList(extraPathEntries); + List<FileSystem.Classpath> newClasspathEntries = handleClasspath(asList, encoding); + FileSystem.Classpath[] newCheckedClasspaths = new FileSystem.Classpath[checkedClasspaths.length + newClasspathEntries.size()]; + System.arraycopy(checkedClasspaths, 0, newCheckedClasspaths, 0, checkedClasspaths.length); + for (int i = 0; i < newClasspathEntries.size();i++) { + newCheckedClasspaths[i + checkedClasspaths.length] = newClasspathEntries.get(i); + } + checkedClasspaths = newCheckedClasspaths; + } + + private ArrayList<String> toArrayList(java.util.List<File> files) { + ArrayList<String> arrayList = new ArrayList<String>(); + for (File file: files) { + arrayList.add(file.getAbsolutePath()); + } + return arrayList; + } + public void printVersion() { final String version = bind("misc.version", //$NON-NLS-1$ new String[] { bind("compiler.name"), //$NON-NLS-1$ @@ -325,7 +359,23 @@ public class BuildArgParser extends Main { } return ret; } + + public List<String> getModulepath(AjcConfigParser parser) { + List<String> ret = new ArrayList<String>(); + addClasspath(parser.modulepath, ret); + return ret; + } + public List<String> getModulesourcepath(AjcConfigParser parser) { + List<String> ret = new ArrayList<String>(); + addClasspath(parser.modulesourcepath, ret); + return ret; + } + + public ArrayList<FileSystem.Classpath> handleClasspath(ArrayList<String> classpaths, String customEncoding) { + return super.handleClasspath(classpaths, customEncoding); + } + /** * If the classpath is not set, we use the environment's java.class.path, but remove the aspectjtools.jar entry from that list * in order to prevent wierd bootstrap issues (refer to bug#39959). @@ -380,6 +430,9 @@ public class BuildArgParser extends Main { } private void addClasspath(String classpath, List<String> classpathCollector) { + if (classpath == null) { + return; + } StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator); while (tokenizer.hasMoreTokens()) { classpathCollector.add(tokenizer.nextToken()); @@ -389,10 +442,13 @@ public class BuildArgParser extends Main { private class AjcConfigParser extends ConfigParser { private String bootclasspath = null; private String classpath = null; + private String modulepath = null; + private String modulesourcepath = null; private String extdirs = null; private List unparsedArgs = new ArrayList(); private AjBuildConfig buildConfig; private IMessageHandler handler; + private String moduleInfoArgument; public AjcConfigParser(AjBuildConfig buildConfig, IMessageHandler handler) { this.buildConfig = buildConfig; @@ -402,38 +458,48 @@ public class BuildArgParser extends Main { public List getUnparsedArgs() { return unparsedArgs; } + + public String getModuleInfoArgument() { + return this.moduleInfoArgument; + } /** * Extract AspectJ-specific options (except for argfiles). Caller should warn when sourceroots is empty but in incremental * mode. Signals warnings or errors through handler set in constructor. */ - public void parseOption(String arg, LinkedList args) { // XXX use ListIterator.remove() + public void parseOption(String arg, LinkedList<Arg> args) { // XXX use ListIterator.remove() int nextArgIndex = args.indexOf(arg) + 1; // XXX assumes unique // trim arg? buildConfig.setXlazyTjp(true); // now default - MINOR could be pushed down and made default at a lower level if (LangUtil.isEmpty(arg)) { showWarning("empty arg found"); + } else if (arg.endsWith("module-info.java")) { + moduleInfoArgument = arg; } else if (arg.equals("-inpath")) { if (args.size() > nextArgIndex) { // buildConfig.getAjOptions().put(AjCompilerOptions.OPTION_Inpath, CompilerOptions.PRESERVE); - List<File> inPath = buildConfig.getInpath(); StringTokenizer st = new StringTokenizer(((ConfigParser.Arg) args.get(nextArgIndex)).getValue(), File.pathSeparator); + boolean inpathChange = false; while (st.hasMoreTokens()) { String filename = st.nextToken(); File file = makeFile(filename); if (FileUtil.isZipFile(file)) { - inPath.add(file); + buildConfig.addToInpath(file); + inpathChange = true; } else { if (file.isDirectory()) { - inPath.add(file); + buildConfig.addToInpath(file); + inpathChange = true; } else { showWarning("skipping missing, empty or corrupt inpath entry: " + filename); } } } - buildConfig.setInPath(inPath); + if (inpathChange) { + buildConfig.processInPath(); + } args.remove(args.get(nextArgIndex)); } } else if (arg.equals("-injars")) { @@ -467,7 +533,8 @@ public class BuildArgParser extends Main { String filename = st.nextToken(); File jarFile = makeFile(filename); if (FileUtil.isZipFile(jarFile) || jarFile.isDirectory()) { - buildConfig.getAspectpath().add(jarFile); +// buildConfig.getAspectpath().add(jarFile); + buildConfig.addToAspectpath(jarFile); } else { showWarning("skipping missing, empty or corrupt aspectpath entry: " + filename); } @@ -659,10 +726,47 @@ public class BuildArgParser extends Main { } } classpath = cp.toString(); - args.remove(args.get(nextArgIndex)); + Arg pathArg = args.get(nextArgIndex); + unparsedArgs.add("-classpath"); + unparsedArgs.add(pathArg.getValue()); + args.remove(pathArg); } else { showError("-classpath requires classpath entries"); } + } else if (arg.equals("--module-path") || arg.equals("-p")) { + if (args.size() > nextArgIndex) { + String mpArg = ((ConfigParser.Arg) args.get(nextArgIndex)).getValue(); + modulepath = mpArg; +// StringBuffer mp = new StringBuffer(); +// StringTokenizer strTok = new StringTokenizer(mpArg, File.pathSeparator); +// while (strTok.hasMoreTokens()) { +// mp.append(makeFile(strTok.nextToken())); +// if (strTok.hasMoreTokens()) { +// mp.append(File.pathSeparator); +// } +// } +// modulepath = mp.toString(); + args.remove(args.get(nextArgIndex)); + } else { + showError("--module-path requires modulepath entries"); + } + } else if (arg.equals("--module-source-path") || arg.equals("-p")) { + if (args.size() > nextArgIndex) { + String mspArg = ((ConfigParser.Arg) args.get(nextArgIndex)).getValue(); + modulesourcepath = mspArg; +// StringBuffer mp = new StringBuffer(); +// StringTokenizer strTok = new StringTokenizer(mpArg, File.pathSeparator); +// while (strTok.hasMoreTokens()) { +// mp.append(makeFile(strTok.nextToken())); +// if (strTok.hasMoreTokens()) { +// mp.append(File.pathSeparator); +// } +// } +// modulepath = mp.toString(); + args.remove(args.get(nextArgIndex)); + } else { + showError("--module-source-path requires modulepath entries"); + } } else if (arg.equals("-extdirs")) { if (args.size() > nextArgIndex) { String extdirsArg = ((ConfigParser.Arg) args.get(nextArgIndex)).getValue(); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java index afa936db3..b92a4b439 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java @@ -176,7 +176,7 @@ public class ConfigParser { } } - protected void parseOption(String arg, LinkedList args) { + protected void parseOption(String arg, LinkedList<Arg> args) { showWarning("unrecognized option: " + arg); } @@ -191,22 +191,22 @@ public class ConfigParser { throw new ParseException(CONFIG_MSG + message, location); } - void parseArgs(LinkedList args) { + void parseArgs(LinkedList<Arg> args) { while (args.size() > 0) { parseOneArg(args); } } - protected Arg removeArg(LinkedList args) { + protected Arg removeArg(LinkedList<Arg> args) { if (args.size() == 0) { showError("value missing"); return null; } else { - return (Arg) args.removeFirst(); + return args.removeFirst(); } } - protected String removeStringArg(LinkedList args) { + protected String removeStringArg(LinkedList<Arg> args) { Arg arg = removeArg(args); if (arg == null) { return null; @@ -235,7 +235,7 @@ public class ConfigParser { return false; } - void parseOneArg(LinkedList args) { + void parseOneArg(LinkedList<Arg> args) { Arg arg = removeArg(args); String v = arg.getValue(); location = arg.getLocation(); @@ -245,6 +245,9 @@ public class ConfigParser { parseConfigFileHelper(makeFile(removeArg(args).getValue())); } else if (isSourceFileName(v)) { addFileOrPattern(makeFile(v)); + if (v.endsWith("module-info.java")) { + parseOption(arg.getValue(), args); + } } else if (isXml(v)) { addXmlFile(makeFile(v)); } else { @@ -284,6 +287,10 @@ public class ConfigParser { private Location location; private String value; + public String toString() { + return "Arg[location="+location+" value="+value+"]"; + } + public Arg(String value, Location location) { this.value = value; this.location = location; diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java index 52ad76f5b..935eb3cee 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -107,6 +107,10 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC INameEnvironment nameEnvironment) { super(typeRequestor, options, problemReporter, nameEnvironment); } + + public AjLookupEnvironment(LookupEnvironment env, ModuleBinding moduleBinding) { + super(env, moduleBinding); + } // ??? duplicates some of super's code public void completeTypeBindings() { @@ -1474,6 +1478,13 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC this.factory.cleanup(); super.reset(); } + + @Override + public LookupEnvironment wrapInModuleEnvironment(ModuleBinding moduleBinding) { + AjLookupEnvironment newAjLookupEnvironment = new AjLookupEnvironment(this, moduleBinding); + newAjLookupEnvironment.factory = this.factory; + return newAjLookupEnvironment; + } } // commented out, supplied as info on how to manipulate annotations in an diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java index 98bd0484e..0587c4462 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java @@ -20,14 +20,29 @@ import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.StringTokenizer; import org.aspectj.ajdt.ajc.BuildArgParser; import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager; +import org.aspectj.org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathJar; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathJrt; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathLocation; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.Main; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ModuleFinder; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; +import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModule; +import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; +import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.aspectj.util.FileUtil; /** @@ -35,7 +50,9 @@ import org.aspectj.util.FileUtil; * an AjCompilerOptions instance */ public class AjBuildConfig implements CompilerConfigurationChangeFlags { - + + public static final Classpath[] NO_CHECKED_CLASSPATHS = new Classpath[0]; + private boolean shouldProceed = true; public static final String AJLINT_IGNORE = "ignore"; @@ -59,8 +76,16 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { private Map<String, File> sourcePathResources = new HashMap<String, File>(); private List<File> aspectpath = new ArrayList<File>(); private List<String> classpath = new ArrayList<String>(); + private List<String> modulepath = new ArrayList<String>(); + // Expensive to compute (searching modules, parsing module-info) + private ArrayList<Classpath> modulepathClasspathEntries = null; + private List<String> modulesourcepath = new ArrayList<String>(); + // Expensive to compute (searching modules, parsing module-info) + private ArrayList<Classpath> modulesourcepathClasspathEntries = null; + private Classpath[] checkedClasspaths = null; private List<String> bootclasspath = new ArrayList<String>(); private List<String> cpElementsWithModifiedContents = new ArrayList<String>(); + private IModule moduleDesc; private File configFile; private String lintMode = AJLINT_DEFAULT; @@ -205,6 +230,53 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public void setClasspath(List<String> classpath) { this.classpath = classpath; + checkedClasspaths = null; + } + + public List<String> getModulepath() { + return modulepath; + } + + public List<String> getModulesourcepath() { + return modulesourcepath; + } + + public void setModulepath(List<String> modulepath) { + this.modulepath = modulepath; + checkedClasspaths = null; + } + + public void setModulesourcepath(List<String> modulesourcepath) { + this.modulesourcepath = modulesourcepath; + checkedClasspaths = null; + } + + public void setCheckedClasspaths(Classpath[] checkedClasspaths) { + this.checkedClasspaths = checkedClasspaths; + checkedClasspaths = null; + } + + private List<Classpath> processFilePath(List<File> path, java.lang.String encoding) { + List<Classpath> entries = new ArrayList<Classpath>(); + for (File file: path) { + entries.add(FileSystem.getClasspath(file.getAbsolutePath(), encoding, null, ClasspathLocation.BINARY)); + } + return entries; + } + + private List<Classpath> processStringPath(List<String> path, java.lang.String encoding) { + List<Classpath> entries = new ArrayList<Classpath>(); + for (String file: path) { + entries.add(FileSystem.getClasspath(file, encoding, null, ClasspathLocation.BINARY)); + } + return entries; + } + + public Classpath[] getCheckedClasspaths() { + if (checkedClasspaths == null) { + computeCheckedClasspath(); + } + return checkedClasspaths; } public List<String> getBootclasspath() { @@ -225,7 +297,7 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public List<File> getInpath() { // Elements of the list are either archives (jars/zips) or directories - return inPath; + return Collections.unmodifiableList(inPath); } public List<File> getInJars() { @@ -246,11 +318,10 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public void setInJars(List<File> sourceJars) { this.inJars = sourceJars; + checkedClasspaths = null; } - public void setInPath(List<File> dirsOrJars) { - inPath = dirsOrJars; - + public void processInPath() { // remember all the class files in directories on the inpath binaryFiles = new ArrayList<BinarySourceFile>(); FileFilter filter = new FileFilter() { @@ -258,7 +329,7 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { return pathname.getPath().endsWith(".class"); } }; - for (Iterator<File> iter = dirsOrJars.iterator(); iter.hasNext();) { + for (Iterator<File> iter = inPath.iterator(); iter.hasNext();) { File inpathElement = iter.next(); if (inpathElement.isDirectory()) { File[] files = FileUtil.listFiles(inpathElement, filter); @@ -269,6 +340,12 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { } } + public void setInPath(List<File> dirsOrJars) { + inPath = dirsOrJars; + checkedClasspaths = null; + processInPath(); + } + public List<File> getSourceRoots() { return sourceRoots; } @@ -308,16 +385,18 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public List<String> getFullClasspath() { List<String> full = new ArrayList<String>(); full.addAll(getBootclasspath()); // XXX Is it OK that boot classpath overrides inpath/injars/aspectpath? - for (Iterator<File> i = inJars.iterator(); i.hasNext();) { - full.add((i.next()).getAbsolutePath()); + for (File file: inJars) { + full.add(file.getAbsolutePath()); } - for (Iterator<File> i = inPath.iterator(); i.hasNext();) { - full.add((i.next()).getAbsolutePath()); + for (File file: inPath) { + full.add(file.getAbsolutePath()); } - for (Iterator<File> i = aspectpath.iterator(); i.hasNext();) { - full.add((i.next()).getAbsolutePath()); + for (File file: aspectpath) { + full.add(file.getAbsolutePath()); } full.addAll(getClasspath()); + full.addAll(getModulepath()); + full.addAll(getModulesourcepath()); // if (null != outputDir) { // full.add(outputDir.getAbsolutePath()); // } else if (null != outputJar) { @@ -335,11 +414,22 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { } public List<File> getAspectpath() { - return aspectpath; + return Collections.unmodifiableList(aspectpath); } public void setAspectpath(List<File> aspectpath) { this.aspectpath = aspectpath; + checkedClasspaths = null; + } + + public void addToAspectpath(File file) { + this.aspectpath.add(file); + checkedClasspaths = null; + } + + public void addToInjars(File file) { + this.inJars.add(file); + checkedClasspaths = null; } /** @return true if any config file, sourceroots, sourcefiles, injars or inpath */ @@ -765,4 +855,116 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public void setProjectEncoding(String projectEncoding) { options.defaultEncoding = projectEncoding; } + + public String getProjectEncoding() { + return options.defaultEncoding; + } + + public void setModuleDesc(IModule moduleDesc) { + this.moduleDesc = moduleDesc; + } + + public IModule getModuleDesc() { + return moduleDesc; + } + + public void addToInpath(Set<File> newInpathEntries) { + if (newInpathEntries != null && newInpathEntries.size() != 0) { + for (File newInpathEntry: newInpathEntries) { + if (!inPath.contains(newInpathEntry)) { + inPath.add(newInpathEntry); + } + } + checkedClasspaths = null; + } + } + + public void addToInpath(File newInpathEntry) { +// if (!inPath.contains(newInpathEntry)) { + inPath.add(newInpathEntry); +// } + checkedClasspaths = null; + } + + public void addToAspectpath(Set<File> newAspectpathEntries) { + if (newAspectpathEntries != null && newAspectpathEntries.size() != 0) { + for (File newAspectpathEntry: newAspectpathEntries) { + if (!aspectpath.contains(newAspectpathEntry)) { + aspectpath.add(newAspectpathEntry); + } + } + checkedClasspaths = null; + } + } + + public void setModulepathClasspathEntries(ArrayList<Classpath> modulepathClasspathEntries) { + this.modulepathClasspathEntries = modulepathClasspathEntries; + } + + public void setModulesourcepathClasspathEntries(ArrayList<Classpath> modulesourcepathClasspathEntries) { + this.modulesourcepathClasspathEntries = modulesourcepathClasspathEntries; + } + + public File removeAspectPathEntry(int i) { + checkedClasspaths = null; + return aspectpath.remove(i); + } + + public String removeClasspathEntry(int i) { + checkedClasspaths = null; + return classpath.remove(i); + } + + public File removeInpathEntry(int i) { + checkedClasspaths = null; + return inPath.remove(i); + } + + public File removeInjarsEntry(int i) { + checkedClasspaths = null; + return inJars.remove(0); + } + + + // This is similar to the calculation done in Main.setPaths() but it isn't as sophisticated + // as that one (doesn't need to be) and it also considers the additional paths for an + // AspectJ project (aspectpath/inpath/injars) + private void computeCheckedClasspath() { + // Follow what we do in getFullClasspath(): + // bootclasspath, injars, inpath, aspectpath, classpath, modulepath + + String encoding = getProjectEncoding(); + // What to do about bootclasspath on java 9? + + // ArrayList<Classpath> allPaths = handleBootclasspath(bootclasspaths, customEncoding); + ArrayList<FileSystem.Classpath> allPaths = new ArrayList<FileSystem.Classpath>(); + allPaths.addAll(processStringPath(bootclasspath, encoding)); + allPaths.addAll(processFilePath(inJars, encoding)); + allPaths.addAll(processFilePath(inPath, encoding)); + allPaths.addAll(processFilePath(aspectpath, encoding)); + if (modulepathClasspathEntries != null) { + allPaths.addAll(modulepathClasspathEntries); + } + if (modulesourcepathClasspathEntries != null) { + allPaths.addAll(modulesourcepathClasspathEntries); + } + // The classpath is done after modules to give precedence to modules that share the + // same paths as classpath elements (the upcoming normalize will remove later dups) + allPaths.addAll(processStringPath(classpath, encoding)); + for (Iterator<FileSystem.Classpath> iter = allPaths.iterator();iter.hasNext();) { + Classpath next = iter.next(); + if (next == null) { + iter.remove(); + } + } + allPaths = FileSystem.ClasspathNormalizer.normalize(allPaths); + this.checkedClasspaths = new FileSystem.Classpath[allPaths.size()]; + allPaths.toArray(this.checkedClasspaths); + for (int i=0;i<checkedClasspaths.length;i++) { + if (checkedClasspaths[i] == null) { + throw new IllegalStateException(); + } + } + } + } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java index 164af6629..85b665dcd 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java @@ -79,6 +79,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathLocation; import org.aspectj.org.eclipse.jdt.internal.compiler.batch.CompilationUnit; import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModule; import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; @@ -865,8 +866,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider, IBinarySour bcelWorld.getLint().setFromProperties(buildConfig.getLintSpecFile()); } - for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) { - File f = (File) i.next(); + for (File f: buildConfig.getAspectpath()) { if (!f.exists()) { IMessage message = new Message("invalid aspectpath entry: " + f.getName(), null, true); handler.handleMessage(message); @@ -943,7 +943,19 @@ public class AjBuildManager implements IOutputClassFileNameProvider, IBinarySour // a classpathDirectory object that will attempt to look for source when it can't find binary. // int[] classpathModes = new int[classpaths.length]; // for (int i =0 ;i<classpaths.length;i++) classpathModes[i]=ClasspathDirectory.BINARY; - return new FileSystem(classpaths, filenames, defaultEncoding, ClasspathLocation.BINARY); + + FileSystem nameEnvironment = null; + // TODO J9 The compiler likes to work in terms of checked classpath objects - these will be different + // depending on where the code came from (classpath, modulepath). If working with just the raw + // 'classpaths' object it isn't recording where the code came from. This will be an issue later for + // weaving, the distinction will need to be maintained for proper 'module aware/respecting' weaving. + if (buildConfig.getCheckedClasspaths() == null) { + nameEnvironment = new FileSystem(classpaths, filenames, defaultEncoding, ClasspathLocation.BINARY); + } else { + nameEnvironment = new FileSystem(buildConfig.getCheckedClasspaths(), filenames, false); + } + nameEnvironment.module = buildConfig.getModuleDesc(); + return nameEnvironment; } public IProblemFactory getProblemFactory() { @@ -962,9 +974,30 @@ public class AjBuildManager implements IOutputClassFileNameProvider, IBinarySour if ("".equals(defaultEncoding)) {//$NON-NLS-1$ defaultEncoding = null; } - + CompilationUnit moduleCU = null; + + // TODO building with multiple module-infos? + int moduleIndex = -1; + IModule moduleDesc = buildConfig.getModuleDesc(); + String moduleName = moduleDesc == null? null: new String(moduleDesc.name()); + for (int i=0;i<fileCount;i++) { + if (filenames[i].endsWith("module-info.java")) { + moduleIndex = i; + moduleCU = new CompilationUnit(null, filenames[i], defaultEncoding, null, false, moduleName); + } + } + for (int i = 0; i < fileCount; i++) { - units[i] = new CompilationUnit(null, filenames[i], defaultEncoding); +// units[i] = new CompilationUnit(null, filenames[i], defaultEncoding); + if (i == moduleIndex) { + units[i] = moduleCU; + } else { + units[i] = new CompilationUnit(null, filenames[i], defaultEncoding, null, false, moduleName); + units[i].setModule(moduleCU); + } +// new CompilationUnit(null, fileName, encoding, this.destinationPaths[i], +// shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()), +// this.modNames[i]); } return units; } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java index 71c3041e8..b3cb0e2d1 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java @@ -26,18 +26,18 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModule; -import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; import org.aspectj.org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.aspectj.util.FileUtil; -public class StatefulNameEnvironment implements INameEnvironment { +public class StatefulNameEnvironment implements IModuleAwareNameEnvironment { private Map<String,File> classesFromName; private Map<String,NameEnvironmentAnswer> inflatedClassFilesCache; private Set<String> packageNames; private AjState state; - private INameEnvironment baseEnvironment; + private IModuleAwareNameEnvironment baseEnvironment; - public StatefulNameEnvironment(INameEnvironment baseEnvironment, Map<String,File> classesFromName, AjState state) { + public StatefulNameEnvironment(IModuleAwareNameEnvironment baseEnvironment, Map<String,File> classesFromName, AjState state) { this.classesFromName = classesFromName; this.inflatedClassFilesCache = new HashMap<String,NameEnvironmentAnswer>(); this.baseEnvironment = baseEnvironment; @@ -130,4 +130,34 @@ public class StatefulNameEnvironment implements INameEnvironment { this.classesFromName = classNameToFileMap; } + @Override + public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName) { + return baseEnvironment.findType(compoundName, moduleName); + } + + @Override + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) { + return baseEnvironment.findType(typeName, packageName, moduleName); + } + + @Override + public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) { + return baseEnvironment.getModulesDeclaringPackage(parentPackageName, name, moduleName); + } + + @Override + public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) { + return baseEnvironment.hasCompilationUnit(qualifiedPackageName, moduleName, checkCUs); + } + + @Override + public IModule getModule(char[] moduleName) { + return baseEnvironment.getModule(moduleName); + } + + @Override + public char[][] getAllAutomaticModules() { + return baseEnvironment.getAllAutomaticModules(); + } + } diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java index 3799b4cda..c4be26936 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java @@ -57,10 +57,10 @@ public class AjBuildManagerTest extends TestCase { } public void testSimpleStructure() throws IOException /* , CoreException */{ - AjBuildManager manager = new AjBuildManager(messageWriter); BuildArgParser parser = new BuildArgParser(messageWriter); String javaClassPath = System.getProperty("java.class.path"); + System.out.println(javaClassPath); String sandboxName = Ajc.createEmptySandbox().getAbsolutePath(); AjBuildConfig buildConfig = parser.genBuildConfig(new String[] { "-d", sandboxName, "-classpath", javaClassPath, AjdtAjcTests.TESTDATA_PATH + "/src1/A.java", diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java index 1693178e3..101fdade1 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java @@ -48,44 +48,48 @@ public class AjStateTest extends TestCase { } public void testAddEntryToAspectpath() { - newConfig.getAspectpath().add(new File("anotherEntry.jar")); + newConfig.addToAspectpath(new File("anotherEntry.jar")); +// newConfig.getAspectpath().add(new File("anotherEntry.jar")); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testRemoveEntryFromAspectpath() { - newConfig.getAspectpath().remove(0); + newConfig.removeAspectPathEntry(0); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testReorderAspectpath() { - String o = newConfig.getClasspath().remove(0); - newConfig.getAspectpath().add(new File(o)); + String o = newConfig.removeClasspathEntry(0); + newConfig.addToAspectpath(new File(o)); +// newConfig.getAspectpath().add(new File(o)); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testAddEntryToInpath() { - newConfig.getInpath().add(new File("anotherEntry")); + newConfig.addToInpath(new File("anotherEntry")); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testRemoveEntryFromInpath() { - newConfig.getInpath().remove(0); + newConfig.removeInpathEntry(0);//getInpath().remove(0); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testReorderInpath() { - String o = newConfig.getClasspath().remove(0); - newConfig.getInpath().add(new File(o)); + String o = newConfig.removeClasspathEntry(0);//getClasspath().remove(0); + newConfig.addToInpath(new File(o));//getInpath().add(new File(o)); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testAddEntryToInjars() { - newConfig.getInJars().add(new File("anotherEntry.jar")); + newConfig.addToInjars(new File("anotherEntry.jar")); +// newConfig.getInJars().add(new File("anotherEntry.jar")); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testRemoveEntryFromInjars() { - newConfig.getInJars().remove(0); + newConfig.removeInjarsEntry(0); +// newConfig.getInJars().remove(0); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java index 12b1e3508..b665afeba 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java @@ -581,7 +581,7 @@ public class AjcTestCase extends TestCase { } public RunResult run(String className, String[] args, String classpath) { - return run(className, args, "", null, false,false); + return run(className, null, args, "", "", null, false,false); } /** @@ -593,7 +593,7 @@ public class AjcTestCase extends TestCase { * be appended to the classpath, as will any jars in the sandbox. * @param runSpec */ - public RunResult run(String className, String[] args, String vmargs, final String classpath, boolean useLTW, boolean useFullLTW) { + public RunResult run(String className, String moduleName, String[] args, String vmargs, final String classpath, String modulepath, boolean useLTW, boolean useFullLTW) { if (args != null) { for (int i = 0; i < args.length; i++) { @@ -607,8 +607,16 @@ public class AjcTestCase extends TestCase { cp.append(substituteSandbox(classpath)); cp.append(File.pathSeparator); } - cp.append(ajc.getSandboxDirectory().getAbsolutePath()); - getAnyJars(ajc.getSandboxDirectory(), cp); + if (moduleName == null) { + // When running modules, we want more control so don't try to be helpful by adding all jars + cp.append(ajc.getSandboxDirectory().getAbsolutePath()); + getAnyJars(ajc.getSandboxDirectory(), cp); + } + StringBuffer mp = new StringBuffer(); + if (modulepath != null) { + mp.append(substituteSandbox(modulepath)); + mp.append(File.pathSeparator); + } URLClassLoader sandboxLoader; ClassLoader parentLoader = getClass().getClassLoader().getParent(); @@ -639,7 +647,6 @@ public class AjcTestCase extends TestCase { String absPath = directory.getAbsolutePath(); String javaagent= absPath+File.separator+".."+File.separator+"aj-build"+File.separator+"dist"+File.separator+"tools"+File.separator+"lib"+File.separator+"aspectjweaver.jar"; try { - String command ="java " +vmargs+ " -classpath " + cp +" -javaagent:"+javaagent + " " + className ; // Command is executed using ProcessBuilder to allow setting CWD for ajc sandbox compliance @@ -654,10 +661,35 @@ public class AjcTestCase extends TestCase { System.out.println("Error executing full LTW test: " + e); e.printStackTrace(); } - return lastRunResult; - - }else{ + } else if (moduleName != null) { + // CODE FOR RUNNING MODULES + if(vmargs == null){ + vmargs =""; + } + try { + if (mp.indexOf("$runtime") != -1) { + mp = mp.replace(mp.indexOf("$runtime"),"$runtime".length(),TestUtil.aspectjrtPath().toString()); + } + if (cp.indexOf("aspectjrt")==-1) { + cp.append(TestUtil.aspectjrtPath().getPath()).append(File.pathSeparator); + } + String command = LangUtil.getJavaExecutable().getAbsolutePath() + " " +vmargs+ (cp.length()==0?"":" -classpath " + cp) + " -p "+mp+" --module "+moduleName ; + System.out.println("Command is "+command); + // Command is executed using ProcessBuilder to allow setting CWD for ajc sandbox compliance + ProcessBuilder pb = new ProcessBuilder(tokenizeCommand(command)); + pb.directory( new File(ajc.getSandboxDirectory().getAbsolutePath())); + exec = pb.start(); + BufferedReader stdInput = new BufferedReader(new InputStreamReader(exec.getInputStream())); + BufferedReader stdError = new BufferedReader(new InputStreamReader(exec.getErrorStream())); + exec.waitFor(); + lastRunResult = createResultFromBufferReaders(command,stdInput, stdError); + } catch (Exception e) { + System.out.println("Error executing module test: " + e); + e.printStackTrace(); + } + return lastRunResult; + } else { cp.append(DEFAULT_CLASSPATH_ENTRIES); URL[] urls = getURLs(cp.toString()); sandboxLoader = new URLClassLoader(urls, parentLoader); @@ -666,7 +698,8 @@ public class AjcTestCase extends TestCase { ByteArrayOutputStream baosErr = new ByteArrayOutputStream(); - StringBuffer command = new StringBuffer("java -classpath "); + StringBuffer command = new StringBuffer(); + command.append("java -classpath "); command.append(cp.toString()); command.append(" "); command.append(className); @@ -834,15 +867,15 @@ public class AjcTestCase extends TestCase { return urls; } - private String substituteSandbox(String classpath) { - // the longhand form of the non 1.3 API: classpath.replace("$sandbox", ajc.getSandboxDirectory().getAbsolutePath()); - while (classpath.indexOf("$sandbox") != -1) { - int pos = classpath.indexOf("$sandbox"); - String firstbit = classpath.substring(0, pos); - String endbit = classpath.substring(pos + 8); - classpath = firstbit + ajc.getSandboxDirectory().getAbsolutePath() + endbit; + private String substituteSandbox(String path) { + // the longhand form of the non 1.3 API: path.replace("$sandbox", ajc.getSandboxDirectory().getAbsolutePath()); + while (path.indexOf("$sandbox") != -1) { + int pos = path.indexOf("$sandbox"); + String firstbit = path.substring(0, pos); + String endbit = path.substring(pos + 8); + path = firstbit + ajc.getSandboxDirectory().getAbsolutePath() + endbit; } - return classpath; + return path; } /** @@ -864,6 +897,8 @@ public class AjcTestCase extends TestCase { args[i + 1] = substituteSandbox(args[i + 1]); String next = args[i + 1]; hasruntime = ((null != next) && (-1 != next.indexOf("aspectjrt.jar"))); + } else if ("-p".equals(args[i]) || "--module-path".equals(args[i])) { + args[i + 1] = substituteSandbox(args[i + 1]); } } if (-1 == cpIndex) { diff --git a/util/src/org/aspectj/util/SoftHashMap.java b/util/src/org/aspectj/util/SoftHashMap.java index f7971bddb..94ae83441 100644 --- a/util/src/org/aspectj/util/SoftHashMap.java +++ b/util/src/org/aspectj/util/SoftHashMap.java @@ -12,7 +12,7 @@ import java.util.*; public class SoftHashMap<K,V> extends AbstractMap<K,V> { private Map<K, SpecialValue> map; - private ReferenceQueue<? super V> rq = new ReferenceQueue<>(); + private ReferenceQueue<? super V> rq = new ReferenceQueue(); public SoftHashMap() { this.map = new HashMap<K,SpecialValue>(); |