diff options
author | wisberg <wisberg> | 2002-12-16 17:58:19 +0000 |
---|---|---|
committer | wisberg <wisberg> | 2002-12-16 17:58:19 +0000 |
commit | d842c4f1139629c1f062b74ba818d233b2c31043 (patch) | |
tree | 842d3871620bc0eb60edcd95e55804d67e0f61fa /org.aspectj.ajdt.core | |
parent | 3ce247199704eae6b2c92c6e38c69584e3250c52 (diff) | |
download | aspectj-d842c4f1139629c1f062b74ba818d233b2c31043.tar.gz aspectj-d842c4f1139629c1f062b74ba818d233b2c31043.zip |
initial version
Diffstat (limited to 'org.aspectj.ajdt.core')
159 files changed, 17740 insertions, 0 deletions
diff --git a/org.aspectj.ajdt.core/.classpath b/org.aspectj.ajdt.core/.classpath new file mode 100644 index 000000000..f1022a482 --- /dev/null +++ b/org.aspectj.ajdt.core/.classpath @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/> + <classpathentry kind="src" path="/org.eclipse.jdt.core"/> + <classpathentry kind="src" path="/bridge"/> + <classpathentry kind="src" path="/weaver"/> + <classpathentry kind="src" path="/asm"/> + <classpathentry kind="src" path="/util"/> + <classpathentry kind="src" path="/runtime"/> + <classpathentry kind="src" path="testsrc"/> + <classpathentry kind="lib" path="/lib/bcel/bcel.jar" + rootpath="bcel-5.0/src/java" sourcepath="/lib/bcel/bcel-src.zip"/> + <classpathentry kind="lib" path="/lib/junit/junit.jar" sourcepath="/lib/junit/junit-src.jar"/> + <classpathentry kind="lib" path="/lib/eclipse2.0/jdtDepends.jar" sourcepath="/lib/eclipse2.0/jdtDependsSrc.zip"/> + <classpathentry kind="src" path="/testing-util"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/org.aspectj.ajdt.core/.project b/org.aspectj.ajdt.core/.project new file mode 100644 index 000000000..301a33091 --- /dev/null +++ b/org.aspectj.ajdt.core/.project @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.aspectj.ajdt.core</name> + <comment></comment> + <projects> + <project>asm</project> + <project>weaver</project> + <project>bridge</project> + <project>org.eclipse.jdt.core</project> + <project>runtime</project> + <project>testing-util</project> + <project>util</project> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/org.aspectj.ajdt.core/scripts/makedelegate.py b/org.aspectj.ajdt.core/scripts/makedelegate.py new file mode 100644 index 000000000..682a338f0 --- /dev/null +++ b/org.aspectj.ajdt.core/scripts/makedelegate.py @@ -0,0 +1,28 @@ +inputFile = "c:/eclipse/workspace/org.eclipse.jdt.core/aspectj/org/aspectj/workbench/resources/FileAdapter.java" + +text = open(inputFile, 'r').read() + +#print text + +import re, string + +methodPat = re.compile(r"public [^{]*\([^{]*{[^}]*}") #^[{]\)^[{]{", re.DOTALL) #{ .* }", re.DOTALL) + +throwException = """throw new RuntimeException("unimplemented");""" + +for method in methodPat.findall(text): + print method + + newMethod = method[:len(method)-1] + + startBody = newMethod.find("{") + newMethod = newMethod[:startBody+1] + + + newMethod = newMethod + "\n\t" + throwException + "\n\t}" + text = text.replace(method, newMethod) + +print text + +open(inputFile, 'w').write(text) + diff --git a/org.aspectj.ajdt.core/scripts/makeparser.py b/org.aspectj.ajdt.core/scripts/makeparser.py new file mode 100644 index 000000000..1b2af4191 --- /dev/null +++ b/org.aspectj.ajdt.core/scripts/makeparser.py @@ -0,0 +1,126 @@ +# set these first four variables appropriately for your system +eclipseWorkspace = "c:/eclipse/workspace" +workingDir = "c:/apps/jikespg/jdt/tmp" + +jikespg = "c:/apps/jikespg/src/a.exe" +makersc = "c:/jdk1.4/bin/java -classpath c:/eclipse/workspace/org.eclipse.jdt.core/bin;c:/apps/jikespg/jdt;c:/eclipse/workspace/bcweaver/bin UpdateParserFiles" + +# the rest of this should never change +ajCompilerHomeRel = "org.aspectj.ajdt.core/src/" +javaCompilerHomeRel = "org.eclipse.jdt.core/compiler/" + +compilerHomeRel = ajCompilerHomeRel +parserHomeRel = ajCompilerHomeRel + "org/aspectj/ajdt/internal/compiler/parser" +parserInfoFileRel = javaCompilerHomeRel + "org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java" +symbolsHomeRel = javaCompilerHomeRel + "org/eclipse/jdt/core/compiler/ITerminalSymbols.java" +# symbolsHomeRel = "org/aspectj/ajdt/compiler/IAjTerminalSymbols.java" +parserClass = "AjParser.java" +grammarFileRel = javaCompilerHomeRel + "org/eclipse/jdt/internal/compiler/parser/aj_grammar.txt" + + +import os +from os import path +import re + +def readFile(name, mode=''): + f = open(name, 'r'+mode) + text = f.read() + f.close() + return text + +def writeFile(name, text, mode=''): + f = open(name, 'w'+mode) + f.write(text) + f.close() + +compilerHome = path.join(eclipseWorkspace, compilerHomeRel) +parserHome = path.join(eclipseWorkspace, parserHomeRel) +symbolFile = path.join(eclipseWorkspace, symbolsHomeRel) +parserInfoFile = path.join(eclipseWorkspace, parserInfoFileRel) + +parserFile = path.join(parserHome, parserClass) +parserText = readFile(parserFile) + +if grammarFileRel == None: + r = re.compile(r"public final static void grammar\(\){.*(--main.*\$end\n)-- need", re.DOTALL) + match = r.search(parserText) + grammar = match.group(1) +else: + grammar = readFile(path.join(eclipseWorkspace, grammarFileRel)) +#print grammar + +grammarFile = path.join(workingDir, "java.g") +writeFile(grammarFile, grammar) +os.chdir(workingDir) +os.system("%s java.g" % jikespg) + +#3.1 Copy the contents of the JavaAction.java file into the consumeRule(int) method of the org.eclipse.jdt.internal.compiler.parser.Parser class. + +newConsumeRule = readFile(path.join(workingDir, "JavaAction.java")) +#print newConsumeRule + +r = re.compile(r"(// This method is part of an automatic generation : do NOT edit-modify\W+protected void consumeRule\(int act\) {.*)protected void consumeSimpleAssertStatement\(\) {", re.DOTALL) + +match = r.search(parserText) +parserText = parserText.replace(match.group(1), newConsumeRule) + + +#3.2 The definition of the Parser needs to be updated with two tables from javadcl.java. Those are rhs[] and name[]. + +newTables = readFile(path.join(workingDir, "javadcl.java")) +r = re.compile(r"(public final static byte rhs\[\] = \{[^}]*\};)", re.DOTALL) +rhsTable = r.search(newTables).group(0) + +parserText = parserText.replace(r.search(parserText).group(0), rhsTable) + + +r = re.compile(r"(public final static String name\[\] = \{[^}]*\}[^}]*\};)", re.DOTALL) +nameTable = r.search(newTables).group(0) +nameTable = nameTable.replace("\"$eof\"", "UNEXPECTED_EOF") +nameTable = nameTable.replace("$error", "Invalid Character") + +parserText = parserText.replace(r.search(parserText).group(0), nameTable) + + +#we're done w/ Parser.java +writeFile(parserFile, parserText) + + + +#3.3 The class org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation needs to be updated with the content of the file javadef.java. + +defs = readFile(path.join(workingDir, "javadef.java")) +r = re.compile(r"(public final static int[^;]*;)", re.DOTALL) +syms = r.search(defs).group(0) +#print syms + +text = readFile(parserInfoFile) +text = text.replace(r.search(text).group(0), syms) + +writeFile(parserInfoFile, text) + +#3.4 This is the contents of the class org.eclipse.jdt.internal.compiler.parser.TerminalSymbols. + +defs = readFile(path.join(workingDir, "javasym.java")) +r = re.compile(r"(public final static int[^;]*;)", re.DOTALL) +syms = r.search(defs).group(0) +syms = syms.replace("$eof", "EOF") +syms = syms.replace("$error", "ERROR") + +print syms + +text = readFile(symbolFile) +text = text.replace(r.search(text).group(0), syms) + +writeFile(symbolFile, text) + +#3.5 The last step is to update the resource files: + +os.chdir(workingDir) +os.system("%s javadcl.java" % makersc) + +for i in range(1,6): + name = "parser%d.rsc" % i + print "moving", name + t = readFile(path.join(workingDir, name), 'b') + writeFile(path.join(parserHome, name), t, 'b') diff --git a/org.aspectj.ajdt.core/src/.cvsignore b/org.aspectj.ajdt.core/src/.cvsignore new file mode 100644 index 000000000..a3f0b1b77 --- /dev/null +++ b/org.aspectj.ajdt.core/src/.cvsignore @@ -0,0 +1 @@ +*.lst diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/AjdtCommand.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/AjdtCommand.java new file mode 100644 index 000000000..1cecb4a76 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/AjdtCommand.java @@ -0,0 +1,125 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.ajc; + +import org.aspectj.ajdt.internal.core.builder.AjBuildConfig; +import org.aspectj.ajdt.internal.core.builder.AjBuildManager; +import org.aspectj.bridge.*; +import org.aspectj.util.LangUtil; +import org.eclipse.jdt.internal.core.builder.MissingSourceFileException; + +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; + +/** + * ICommand adapter for the AspectJ eclipse-based compiler. + */ +public class AjdtCommand implements ICommand { + + /** Message String for any AbortException thrown from ICommand API's */ + public static final String ABORT_MESSAGE = "ABORT"; + + private boolean canRepeatCommand = true; + + AjBuildManager buildManager = null; + String[] savedArgs = null; + + /** + * Run AspectJ compiler, wrapping any exceptions thrown as + * ABORT messages (containing ABORT_MESSAGE String). + * @param args the String[] for the compiler + * @param handler the IMessageHandler for any messages + * @see org.aspectj.bridge.ICommand#runCommand(String[], IMessageHandler) + * @return false if command failed + */ + public boolean runCommand(String[] args, IMessageHandler handler) { + try { + buildManager = new AjBuildManager(handler); + savedArgs = new String[args.length]; + System.arraycopy(args, 0, savedArgs, 0, savedArgs.length); + CountingMessageHandler counter = new CountingMessageHandler(handler); + AjBuildConfig config = genBuildConfig(savedArgs, counter); + return (!counter.hasErrors() + && buildManager.batchBuild(config, counter) + && !counter.hasErrors()); + } catch (AbortException ae) { + if (AbortException.ABORT.equals(ae)) { + throw ae; + } else { + MessageUtil.abort(handler, ABORT_MESSAGE, ae); + return false; + } + } catch (MissingSourceFileException t) { // XXX special handling - here only? + MessageUtil.error(handler, t.getMessage()); + return false; + } catch (Throwable t) { + //System.err.println("caught: " + t); + MessageUtil.abort(handler, ABORT_MESSAGE, t); + return false; + } + } + + /** + * Run AspectJ compiler, wrapping any exceptions thrown as + * ABORT messages (containing ABORT_MESSAGE String). + * @see org.aspectj.bridge.ICommand#repeatCommand(IMessageHandler) + * @return false if command failed + */ + public boolean repeatCommand(IMessageHandler handler) { + if (null == buildManager) { + MessageUtil.abort(handler, "repeatCommand called before runCommand"); + return false; + } + try { + //buildManager.setMessageHandler(handler); + CountingMessageHandler counter = new CountingMessageHandler(handler); + // regenerate configuration b/c world might have changed (?) + AjBuildConfig config = genBuildConfig(savedArgs, counter); + return (!counter.hasErrors() + && buildManager.incrementalBuild(config, handler) + && !counter.hasErrors()); + } catch (MissingSourceFileException t) { + return false; // already converted to error + } catch (Throwable t) { + MessageUtil.abort(handler, ABORT_MESSAGE, t); + return false; + } + } + + /** @throws AbortException.ABORT on error after logging message */ + AjBuildConfig genBuildConfig(String[] args, IMessageHandler handler) { + BuildArgParser parser = new BuildArgParser(); + AjBuildConfig config = parser.genBuildConfig(args, handler); + String message = parser.getOtherMessages(true); + + if (null != message) { + IMessage.Kind kind = inferKind(message); + handler.handleMessage(new Message(message, kind, null, null)); + throw AbortException.ABORT; // XXX tangled - assumes handler prints? + } + return config; + } + + /** @return IMessage.WARNING unless message contains error or info */ + protected IMessage.Kind inferKind(String message) { // XXX dubious + if (-1 == message.indexOf("error")) { + return IMessage.ERROR; + } else if (-1 == message.indexOf("info")) { + return IMessage.INFO; + } else { + return IMessage.WARNING; + } + } +} 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 new file mode 100644 index 000000000..81cabdb69 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java @@ -0,0 +1,415 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + + +package org.aspectj.ajdt.ajc; + +import java.io.*; +import java.util.*; +import org.aspectj.ajdt.internal.core.builder.*; +import org.aspectj.weaver.bcel.*; +import org.apache.bcel.util.ClassPath; +import org.aspectj.bridge.*; +import org.aspectj.bridge.IMessage.Kind; +import org.aspectj.util.*; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.compiler.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.batch.*; +import org.eclipse.jdt.internal.compiler.problem.*; +import org.eclipse.jdt.internal.core.util.*; +import org.aspectj.ajdt.internal.core.builder.AjCompilerOptions; +import org.aspectj.util.ConfigParser; +import org.eclipse.jdt.core.compiler.InvalidInputException; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +public class BuildArgParser extends org.eclipse.jdt.internal.compiler.batch.Main { + + private static final String BUNDLE_NAME = "org.aspectj.ajdt.ajc.messages"; + + /** to initialize super's PrintWriter but refer to underlying StringWriter */ + private static class StringPrintWriter extends PrintWriter { + public final StringWriter stringWriter; + StringPrintWriter(StringWriter sw) { + super(sw); + this.stringWriter = sw; + } + } + + /** + * StringWriter sink for some errors. + * This only captures errors not handled by any IMessageHandler parameter + * and only when no PrintWriter is set in the constructor. + * XXX This relies on (Sun's) implementation of StringWriter, + * which returns the actual (not copy) internal StringBuffer. + */ + private final StringBuffer errorSink; + + /** + * Overrides super's bundle. + */ + public BuildArgParser(PrintWriter writer) { + super(writer, false); + bundle = ResourceBundle.getBundle(BUNDLE_NAME); + if (writer instanceof StringPrintWriter) { + errorSink = ((StringPrintWriter) writer).stringWriter.getBuffer(); + } else { + errorSink = null; + } + } + + /** Set up to capture messages using getOtherMessages(boolean) */ + public BuildArgParser() { + this(new StringPrintWriter(new StringWriter())); + } + + public AjBuildConfig genBuildConfig(String[] args, IMessageHandler handler) { + AjBuildConfig buildConfig = new AjBuildConfig(); + try { + // sets filenames to be non-null in order to make sure that file paramters are ignored + super.filenames = new String[] { "" }; + + List optionsList = new ArrayList(Arrays.asList(args)); + List fileList = new ArrayList(); + boolean incrementalMode = false; + if (optionsList.remove("-incremental")) { + incrementalMode = true; + args = (String[])optionsList.toArray(new String[optionsList.size()]); + } + + AjcConfigParser parser = new AjcConfigParser(buildConfig, handler, incrementalMode); + parser.parseCommandLine(args); + + if (!incrementalMode) { + if (parser.getFiles() != null) { + for (Iterator it = parser.getFiles().iterator(); it.hasNext(); ) { + fileList.add((File)it.next()); + } + } + } else { + if (parser.getFiles() != null && !parser.getFiles().isEmpty()) { + handler.handleMessage(new Message("can not directly specify files in incremental mode, use -sourceroots instead", + Message.ERROR, null, null)); + } + } + + List javaArgList = parser.getUnparsedArgs(); + if (javaArgList.size() != 0) { + super.configure((String[])javaArgList.toArray(new String[javaArgList.size()])); + } + + if (buildConfig.getSourceRoots() != null) { + for (Iterator i = buildConfig.getSourceRoots().iterator(); i.hasNext(); ) { + fileList.addAll(collectSourceRootFiles((File)i.next())); + } + } + + buildConfig.setFiles(fileList); + if (destinationPath != null) { + buildConfig.setOutputDir(new File(destinationPath)); + } + + buildConfig.setClasspath(getClasspath(parser)); + + if (incrementalMode) { + if (buildConfig.getSourceRoots().size() == 0) { + handler.handleMessage(new Message("must specify a source root when in incremental mode", + Message.ERROR, null, null)); + } + } + + setDebugOptions(); + buildConfig.setJavaOptions(options); + } catch (InvalidInputException iie) { + handler.handleMessage(new Message(iie.getMessage(), Message.ERROR, null, null)); + printUsage(); + } + return buildConfig; + } + + /** + * Get messages not dumped to handler or any PrintWriter. + * @param flush if true, empty errors + * @return null if none, String otherwise + * @see BuildArgParser() + */ + public String getOtherMessages(boolean flush) { + if (null == errorSink) { + return null; + } + + String result = errorSink.toString().trim(); + if (0 == result.length()) { + result = null; + } + if (flush) { + errorSink.setLength(0); + } + return result; + } + + private void setDebugOptions() { + options.put( + CompilerOptions.OPTION_LocalVariableAttribute, + CompilerOptions.GENERATE); + options.put( + CompilerOptions.OPTION_LineNumberAttribute, + CompilerOptions.GENERATE); + options.put( + CompilerOptions.OPTION_SourceFileAttribute, + CompilerOptions.GENERATE); + } + + + private Collection collectSourceRootFiles(File dir) { + return Arrays.asList(FileUtil.listFiles(dir, FileUtil.aspectjSourceFileFilter)); + } + + + public List getClasspath(AjcConfigParser parser) { + List ret = new ArrayList(); + + if (parser.bootclasspath == null) { + addClasspath(System.getProperty("sun.boot.class.path", ""), ret); + } else { + addClasspath(parser.bootclasspath, ret); + } + + String extdirs = parser.extdirs; + if (extdirs == null) { + extdirs = System.getProperty("java.ext.dirs", ""); + } + addExtDirs(extdirs, ret); + + if ((classpaths == null || classpaths.length == 0) || + (classpaths != null && classpaths[0] == ".")) { + //??? this puts the compiler's classes on the classpath + //??? this is ajc-1.0 compatible + addClasspath(System.getProperty("java.class.path", ""), ret); + } else { + ret.addAll(Arrays.asList(classpaths)); + } + + //??? eclipse seems to put outdir on the classpath + //??? we're brave and believe we don't need it + + return ret; + } + + private void addExtDirs(String extdirs, List classpathCollector) { + StringTokenizer tokenizer = new StringTokenizer(extdirs, File.pathSeparator); + while (tokenizer.hasMoreTokens()) { +// classpathCollector.add(tokenizer.nextToken()); + File dirFile = new File((String)tokenizer.nextToken()); + if (dirFile.exists() && dirFile.isDirectory()) { + File[] files = FileUtil.listFiles(dirFile, new FileFilter() { + public boolean accept(File pathname) { + return pathname.isFile() && pathname.getName().endsWith(".jar"); + } + }); + for (int i = 0; i < files.length; i++) { + classpathCollector.add(files[i].getAbsolutePath()); + } + } + } + } + + + private void addClasspath(String classpath, List classpathCollector) { + StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator); + while (tokenizer.hasMoreTokens()) { + classpathCollector.add(tokenizer.nextToken()); + } + } + + // !!! extract error handling to be common so that the IDEs can use it + private class AjcConfigParser extends ConfigParser { + private String bootclasspath = null; + private String extdirs = null; + private boolean incrementalArgsMode = false; + private List unparsedArgs = new ArrayList(); + private AjBuildConfig buildConfig; + private IMessageHandler handler; + + public AjcConfigParser(AjBuildConfig buildConfig, IMessageHandler handler, boolean incrementalMode) { + this.buildConfig = buildConfig; + this.handler = handler; + this.incrementalArgsMode = incrementalMode; + } + + public List getUnparsedArgs() { + return unparsedArgs; + } + + public void parseOption(String arg, LinkedList args) { + int nextArgIndex = args.indexOf(arg)+1; + if (arg.equals("-Xlint")) {; + buildConfig.getAjOptions().put( + AjCompilerOptions.OPTION_Xlint, + CompilerOptions.GENERATE); + } else if (arg.equals("-injars")) {; + if (args.size() > nextArgIndex) { + buildConfig.getAjOptions().put(AjCompilerOptions.OPTION_InJARs, CompilerOptions.PRESERVE); + + StringTokenizer st = new StringTokenizer( + ((ConfigParser.Arg)args.get(nextArgIndex)).getValue(), + File.pathSeparator); + while (st.hasMoreTokens()) { + String filename = st.nextToken(); + File jarFile = makeFile(filename); + if (filename.endsWith(".jar") && jarFile.exists()) { + buildConfig.getInJars().add(jarFile); + } else { + handler.handleMessage(new Message( + "ignoring bad injar: " + filename, + Message.WARNING, null, null)); + } + } + + args.remove(args.get(nextArgIndex)); + } + } else if (arg.equals("-aspectpath")) {; + if (args.size() > nextArgIndex) { + StringTokenizer st = new StringTokenizer( + ((ConfigParser.Arg)args.get(nextArgIndex)).getValue(), + File.pathSeparator); + while (st.hasMoreTokens()) { + String filename = st.nextToken(); + File jarFile = makeFile(filename); + if (filename.endsWith(".jar") && jarFile.exists()) { + buildConfig.getAspectpath().add(jarFile); + } else { + handler.handleMessage(new Message( + "ignoring bad injar: " + filename, + Message.WARNING, null, null)); + } + } + + args.remove(args.get(nextArgIndex)); + } + } else if (arg.equals("-sourceroots")) { + if (args.size() > nextArgIndex) { + List sourceRoots = new ArrayList(); + StringTokenizer st = new StringTokenizer( + ((ConfigParser.Arg)args.get(nextArgIndex)).getValue(), + File.pathSeparator); + while (st.hasMoreTokens()) { + File f = makeFile(st.nextToken()); + if (f.isDirectory()) { + sourceRoots.add(f); + } else { + handler.handleMessage(new Message( + f.getName() + " is not a file, not adding to sourceroots", + Message.WARNING, null, null)); + } + } + + +// if (sourceRoots.size() > 1) { +// handler.handleMessage(new Message( +// "can not specify more than one source root (compiler limitation)\n" +// + "using source root: " + sourceRoots.get(0), +// Message.WARNING, null, null)); +// } else + if (sourceRoots.size() < 1) { + out.println("must specify a valid source root in incremental mode"); + } else { + buildConfig.setSourceRoots(sourceRoots); + } + args.remove(args.get(nextArgIndex)); + } else { + out.println("must specify a valid source root in incremental mode"); + } + } else if (arg.equals("-outjar")) { + if (args.size() > nextArgIndex) { + buildConfig.getAjOptions().put(AjCompilerOptions.OPTION_OutJAR, CompilerOptions.GENERATE); + File jarFile = makeFile(((ConfigParser.Arg)args.get(nextArgIndex)).getValue()); + if (jarFile.getName().endsWith(".jar")) { + try { + if (!jarFile.exists()) jarFile.createNewFile(); + } catch (IOException ioe) { + // fail siltenty + } + buildConfig.setOutputJar(jarFile); + } else { + out.println("file specified with -outjar is not a valid JAR file, ignoring"); + buildConfig.setLintSpecFile(null); + } + args.remove(args.get(nextArgIndex)); + } else { + out.println("must specify a file for -outjar"); + } + } else if (arg.equals("-emacssym")) { + buildConfig.setEmacsSymMode(true); + buildConfig.setGenerateModelMode(true); + } else if (arg.equals("-emacssym")) { + buildConfig.setEmacsSymMode(true); + buildConfig.setGenerateModelMode(true); + } else if (arg.equals("-noweave")) { + buildConfig.setNoWeave(true); + } else if (arg.equals("-XserializableAspects")) { + buildConfig.setXserializableAspects(true); + } else if (arg.equals("-Xlintfile")) { + if (args.size() > nextArgIndex) { + File lintSpecFile = makeFile(((ConfigParser.Arg)args.get(nextArgIndex)).getValue()); + if (lintSpecFile.exists() && lintSpecFile.getName().endsWith(".properties")) { + buildConfig.setLintSpecFile(lintSpecFile); + } else { + out.println("file specified with -Xlintfile does not exist, ignoring"); + buildConfig.setLintSpecFile(null); + } + args.remove(args.get(nextArgIndex)); + } else { + out.println("must specify a file for -outjar"); + } + } else if (arg.startsWith("-Xlint")) { + int index = arg.indexOf(":"); + if (index != -1) { + buildConfig.setLintMode(arg.substring(index+1)); + } else { + buildConfig.setLintMode(AjBuildConfig.AJLINT_DEFAULT); + } + } else if (arg.equals("-bootclasspath")) { + if (args.size() > nextArgIndex) { + bootclasspath = ((ConfigParser.Arg)args.get(nextArgIndex)).getValue(); + args.remove(args.get(nextArgIndex)); + } + } else if (arg.equals("-extdirs")) { + if (args.size() > nextArgIndex) { + extdirs = ((ConfigParser.Arg)args.get(nextArgIndex)).getValue(); + args.remove(args.get(nextArgIndex)); + } + } else { +// if (arg.equals("-d")) { +// int nextArgIndex = args.indexOf(arg)+1; +// if (args.size() > nextArgIndex) { +// ConfigParser.Arg path = (ConfigParser.Arg)args.get(nextArgIndex); +// path.setValue(makeFile(path.getValue()).getPath()); +// } +// } + unparsedArgs.add(arg); + } + } + + public void showError(String message) { +// out.println(message); + handler.handleMessage(new Message(message, Message.ERROR, null, null)); + } + + + protected void showWarning(String message) { + handler.handleMessage(new Message(message, Message.WARNING, null, null)); + } + + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties new file mode 100644 index 000000000..3db1d2dc7 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties @@ -0,0 +1,117 @@ + +### AspectJ-specific messages +configure.version = AspectJ Compiler 1.1beta1 +configure.directoryNotExist = invalid option or directory does not exist: {0} + +### miscellaneous +misc.usage = AspectJ Compiler 1.1beta1\n\n\ + Usage: <options> <source files | directories>\n\n\ + AspectJ-specific options:\n\ + -Xlint generate crosscutting-specific warnings\n\ + -injars <jar 1>;<jar 2>;...;<jar P>\n\ + -outjar <file> generate a single JAR instead of multiple .class files\n\ + -incremental persistant incremental compiler, requires -sourceroots\n\ + -sourceroots <dir> find and build all source files under <dir>;<dir 2>;...\n\n\ + Standard Eclipse compiler options:\n\ + -help display this help message\n\ + -version compiler version number\n\ + -classpath <dir 1>;<dir 2>;...;<dir P>\n\ + -d <dir> destination dir (if omitted no pkg structure created)\n\ + \t-d none no classfile is generated\n\ + -target <ver> classfile target setting (1.1 or 1.2, default is 1.1)\n\ + -1.3 set compliance level to 1.3 (default)\n\ + -1.4 set compliance level to 1.4\n\ + -source <ver> assertions toggle (1.3 or 1.4, default is 1.3 \n\t\t\tin -1.3 mode and 1.4 in -1.4 mode)\n\ + -nowarn no warning (equivalent to ''-warn:none'')\n\ + -warn: <level> set warning level (eg ''-warn:unusedLocals,deprecation'')\n\ + \tconstructorName warn method with constructor name\n\ + \tpackageDefaultMethod warn attempt to override package-default method\n\ + \tdeprecation warn usage of deprecated type or member\n\ + \tmaskedCatchBlocks warn hidden catch block\n\ + \tunusedLocals warn on unused local variable (never read)\n\ + \tunusedArguments warn on unused method argument (never read)\n\ + \tunusedImports warn on unused imports\n\ + \tsyntheticAccess warn when performing synthetic access \n\t\t\t\tfor innerclass\n\ + \tassertIdentifier warn occurrence of ''assert'' used as identifier\n\ + -deprecation equivalent to -warn:deprecation.\n\ + -g[:<level>] debug attributes level\n\ + \t-g all debug info (''-g:lines,vars,source'')\n\ + \t-g:none no debug info\n\ + \t-g:[lines,vars,source] selective debug info\n\ + -preserveAllLocals code gen preserve all local variables (for debug)\n\ + -noImportError no errors for unresolved imports\n\ + -encoding specify default source encoding format (custom encoding\n\t\t\tcan also be specifed on\ + a per file basis by suffixing\n\t\t\teach input source file/folder name with '[encoding]')\n\ + -log <filename> specify a log file\n\ + -proceedOnError keep compiling when error, dumping class files with\n\t\t\tproblem methods\n\ + -verbose print accessed/processed compilation units \n\ + -referenceInfo compute reference info\n\ + -progress show progress (only in -log mode)\n\ + -time display speed information\n\ + -noExit do not call System.exit(n) at end of compilation\n\t\t\t(n=0 if no error)\n\ + -repeat <n> repeat compilation process <n> times (perf analysis)\n + +########################################## +### JavaBatchCompiler messages. + +### compiler version id +compiler.version = 0.265 +### scanning +scanning.start = Collecting source files inside {0} + +### progress +progress.compiling = Compiling + +### compile +compile.repetition = Repetition {0}/{1} +compile.instantTime = Compiled {0} lines in {1} ms ({2} lines/s) +compile.totalTime = Total compilation time: {0} +compile.oneProblem = 1 problem +compile.severalProblems = {0} problems +compile.oneError = 1 error +compile.severalErrors = {0} errors +compile.oneWarning = 1 warning +compile.severalWarnings = {0} warnings +compile.oneClassFileGenerated = 1 .class file generated +compile.severalClassFilesGenerated = {0} .class files generated + +### configure +configure.noSourceFile = no source file specified +configure.duplicateLog = duplicate log specification: {0} +configure.duplicateRepeat = duplicate repeat specification: {0} +configure.duplicateCompliance = duplicate compliance setting specification: {0} +configure.source = invalid source option, source is either ''1.3'' or ''1.4'': {0} +configure.jck = invalid jck option, jck compliance level is either ''1.3'' or ''1.4'': {0} +configure.duplicateOutputPath = duplicate output path specification: {0} +configure.duplicateClasspath = duplicate classpath specification: {0} +configure.invalidDebugOption = invalid debug option: {0} +configure.duplicateWarningConfiguration = duplicate usage of warning configuration +configure.invalidWarningConfiguration = invalid warning configuration: {0} +configure.invalidWarning = invalid warning: {0} +configure.invalidWarningOption = invalid warning option: {0} +configure.targetJDK = target JDK should be comprised in between ''1.1'' and ''1.4'': {0} +configure.incompatibleTargetForSource14 = ''1.4'' source mode requires ''-target 1.4'' : {0} +configure.incompatibleComplianceForSource14 = ''1.4'' source mode requires ''-1.4'' compliance mode: {0} +configure.incompatibleComplianceForTarget14 = ''1.4'' target mode requires ''-1.4'' compliance mode: {0} +configure.repetition = repetition must be a positive integer: {0} +configure.IOError = i/o error : unable to retrieve .JAVA files in directory: {0} +configure.noClasspath = +configure.incorrectClasspath = incorrect classpath: {0} +configure.noSource = no source file specified +configure.cannotOpenLog = cannot open .log file +configure.unexpectedCustomEncoding = unexpected custom encoding specification: {0}[{1}] +configure.unsupportedEncoding = unsupported encoding format: {0} +configure.duplicateDefaultEncoding = duplicate default encoding format specification: {0} + +### requestor +requestor.error = ERROR +requestor.warning = WARNING +requestor.in = in {0} +requestor.notRetrieveErrorMessage = Cannot retrieve the error message for {0} + +### unit +unit.more = File {0} is specified more than once +unit.missing = File {0} is missing + +### output +output.noClassFileCreated = No .class file created for file named {0} because of an IOException. diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/compiler/IAjTerminalSymbols.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/compiler/IAjTerminalSymbols.java new file mode 100644 index 000000000..3883dd3d2 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/compiler/IAjTerminalSymbols.java @@ -0,0 +1,24 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.compiler; + +import org.eclipse.jdt.core.compiler.ITerminalSymbols; + +/** + * This should contain a list of symbols unique to AspectJ grammar, but + * getting jikespg to do that is too much work right now. + */ +public interface IAjTerminalSymbols extends ITerminalSymbols { + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java new file mode 100644 index 000000000..79eb39f4b --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java @@ -0,0 +1,65 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler; + +import java.util.Map; + +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.Compiler; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; + + +public class AjCompiler extends Compiler { + + public AjCompiler( + INameEnvironment environment, + IErrorHandlingPolicy policy, + Map settings, + ICompilerRequestor requestor, + IProblemFactory problemFactory) { + super(environment, policy, settings, requestor, problemFactory); + } + + public AjCompiler( + INameEnvironment environment, + IErrorHandlingPolicy policy, + Map settings, + ICompilerRequestor requestor, + IProblemFactory problemFactory, + boolean parseLiteralExpressionsAsConstants) { + super( + environment, + policy, + settings, + requestor, + problemFactory, + parseLiteralExpressionsAsConstants); + } + + /** + * In addition to processing each compilation unit in the normal ways, + * we also need to do weaving for inter-type declarations. This + * must be done before we use the signatures of these types to do any + * name binding. + */ + protected void process(CompilationUnitDeclaration unit, int i) { + super.process(unit, i); + + EclipseWorld world = + EclipseWorld.forLookupEnvironment(lookupEnvironment); + world.finishedCompilationUnit(unit); + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java new file mode 100644 index 000000000..6e057f6bf --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java @@ -0,0 +1,350 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.ajdt.internal.compiler.lookup.AjTypeConstants; +import org.aspectj.weaver.*; +//import org.aspectj.weaver.bcel.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.parser.Parser; +import org.eclipse.jdt.internal.core.util.CharArrayOps; + + +public class AdviceDeclaration extends MethodDeclaration implements IAjDeclaration { + public PointcutDesignator pointcutDesignator; + int baseArgumentCount; + + public Argument extraArgument; + + public AdviceKind kind; // adviceMunger; + + private int extraArgumentFlags = 0; + + public MethodBinding proceedMethodBinding; + + public AdviceDeclaration(CompilationResult result, AdviceKind kind) { + super(result); + this.returnType = TypeReference.baseTypeReference(T_void, 0); + this.kind = kind; + } + + + protected int generateInfoAttributes(ClassFile classFile) { + List l = new ArrayList(1); + l.add(new EclipseAttributeAdapter(makeAttribute())); + + return classFile.generateMethodInfoAttribute(binding, l); + } + + public AjAttribute makeAttribute() { + return new AjAttribute.AdviceAttribute(kind, pointcutDesignator.getPointcut(), + extraArgumentFlags, sourceStart, sourceEnd, null); + } + + public void resolveStatements(ClassScope upperScope) { + if (binding == null || ignoreFurtherInvestigation) return; + + modifiers = binding.modifiers = checkAndSetModifiers(modifiers, upperScope); + + + pointcutDesignator.finishResolveTypes(this, this.binding, + baseArgumentCount, upperScope.referenceContext.binding); + + + if (kind == AdviceKind.Around && binding != null) { + ReferenceBinding[] exceptions = + new ReferenceBinding[] { upperScope.getJavaLangThrowable() }; + proceedMethodBinding = new MethodBinding(Modifier.STATIC, + "proceed".toCharArray(), binding.returnType, + resize(baseArgumentCount+1, binding.parameters), + exceptions, binding.declaringClass); + proceedMethodBinding.selector = + CharArrayOps.concat(selector, proceedMethodBinding.selector); + } + + super.resolveStatements(upperScope); + if (binding != null) determineExtraArgumentFlags(); + } + + + public int getDeclaredParameterCount() { + // this only works before code generation + return this.arguments.length - 3 - ((extraArgument == null) ? 0 : 1); + //Advice.countOnes(extraArgumentFlags); + } + + public void generateProceedMethod(ClassScope classScope, ClassFile classFile) { + MethodBinding binding = (MethodBinding)proceedMethodBinding; + + classFile.generateMethodInfoHeader(binding); + int methodAttributeOffset = classFile.contentsOffset; + int attributeNumber = classFile.generateMethodInfoAttribute(binding, AstUtil.getAjSyntheticAttribute()); + int codeAttributeOffset = classFile.contentsOffset; + classFile.generateCodeAttributeHeader(); + CodeStream codeStream = classFile.codeStream; + codeStream.reset(this, classFile); + + // push the closure + int nargs = binding.parameters.length; + int closureIndex = 0; + for (int i=0; i < nargs-1; i++) { + closureIndex += AstUtil.slotsNeeded(binding.parameters[i]); + } + + + codeStream.loadObject(closureIndex); + + // build the Object[] + + codeStream.generateInlinedValue(nargs-1); + codeStream.anewarrayJavaLangObject(); + + int index = 0; + for (int i=0; i < nargs-1; i++) { + TypeBinding type = binding.parameters[i]; + codeStream.dup(); + codeStream.generateInlinedValue(i); + codeStream.load(type, index); + index += AstUtil.slotsNeeded(type); + if (type.isBaseType()) { + codeStream.invokestatic(AjTypeConstants.getConversionMethodToObject(classScope, type)); + } + + codeStream.aastore(); + } + + // call run + ReferenceBinding closureType = (ReferenceBinding)binding.parameters[nargs-1]; + MethodBinding runMethod = closureType.getMethods("run".toCharArray())[0]; + codeStream.invokevirtual(runMethod); + + TypeBinding returnType = binding.returnType; + if (returnType.isBaseType()) { + codeStream.invokestatic(AjTypeConstants.getConversionMethodFromObject(classScope, returnType)); + } else { + codeStream.checkcast(returnType); + } + AstUtil.generateReturn(returnType, codeStream); + + classFile.completeCodeAttribute(codeAttributeOffset); + attributeNumber++; + classFile.completeMethodInfo(methodAttributeOffset, attributeNumber); + } + + + + public void generateCode(ClassScope classScope, ClassFile classFile) { + if (proceedMethodBinding != null) { +// MethodDeclaration dec = +// AstUtil.makeMethodDeclaration(proceedMethodBinding); +// +// List stmts = new ArrayList(); +// +// Expression expr = AstUtil.makeLocalVariableReference(dec.arguments[0].binding); +// +// +// stmts.add(AstUtil.makeReturnStatement(expr)); +// +// AstUtil.setStatements(dec, stmts); +// dec.scope = this.scope; +// dec.generateCode(classScope, classFile); + } + super.generateCode(classScope, classFile); + if (proceedMethodBinding != null) { + generateProceedMethod(classScope, classFile); + } + } + + + private void determineExtraArgumentFlags() { + if (extraArgument != null) extraArgumentFlags |= Advice.ExtraArgument; + + ThisJoinPointVisitor tjp = new ThisJoinPointVisitor(this); + extraArgumentFlags |= tjp.removeUnusedExtraArguments(); + } + + private static TypeBinding[] resize(int newSize, TypeBinding[] bindings) { + int len = bindings.length; + TypeBinding[] ret = new TypeBinding[newSize]; + System.arraycopy(bindings, 0, ret, 0, Math.min(newSize, len)); + return ret; + } + + + + public void finishParsing() { + //kind = AdviceKind.stringToKind(new String(selector)); + //System.out.println(this + " kind " + kind + " name " + new String(selector)); + //selector = ("ajc_" + kind.toString() + "_" + Integer.toHexString(position)).toCharArray(); + //System.out.println(this + " kind " + kind + " name " + new String(selector)); + + if (arguments != null) { + baseArgumentCount = arguments.length; + } + + if (kind == AdviceKind.Around) { + extraArgument = makeFinalArgument("ajc_aroundClosure", + AjTypeConstants.getAroundClosureType()); + } + + int addedArguments = 3; + if (extraArgument != null) { + addedArguments += 1; + } + + arguments = extendArgumentsLength(arguments, addedArguments); + + int index = baseArgumentCount; + if (extraArgument != null) { + arguments[index++] = extraArgument; + } + + arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType()); + arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType()); + arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType()); + + //modifiers = checkAndSetModifiers(modifiers); + + if (pointcutDesignator.isError()) { + //System.err.println("ignoring further investigation for: " + this); + this.ignoreFurtherInvestigation = true; + } + + + } + + private int checkAndSetModifiers(int modifiers, ClassScope scope) { + if (modifiers == 0) return Modifier.PUBLIC; + else if (modifiers == Modifier.STRICT) return Modifier.PUBLIC | Modifier.STRICT; + else { + tagAsHavingErrors(); + scope.problemReporter().signalError(declarationSourceStart, sourceStart-1, "illegal modifier on advice, only strictfp is allowed"); + return Modifier.PUBLIC; + } + } + + + public static Argument[] addTjpArguments(Argument[] arguments) { + int index = arguments.length; + arguments = extendArgumentsLength(arguments, 3); + + arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType()); + arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType()); + arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType()); + + return arguments; + } + + + + private static Argument makeFinalArgument(String name, TypeReference typeRef) { + long pos = 0; //XXX encode start and end location + return new Argument(name.toCharArray(), pos, typeRef, Modifier.FINAL); + } + + + private static Argument[] extendArgumentsLength(Argument[] args, int addedArguments) { + if (args == null) { + return new Argument[addedArguments]; + } + int len = args.length; + Argument[] ret = new Argument[len + addedArguments]; + System.arraycopy(args, 0, ret, 0, len); + return ret; + } + + + public String toString(int tab) { + String s = tabString(tab); + if (modifiers != AccDefault) { + s += modifiersString(modifiers); + } + + if (kind == AdviceKind.Around) { + s += returnTypeToString(0); + } + + s += new String(selector) + "("; //$NON-NLS-1$ + if (arguments != null) { + for (int i = 0; i < arguments.length; i++) { + s += arguments[i].toString(0); + if (i != (arguments.length - 1)) + s = s + ", "; //$NON-NLS-1$ + }; + }; + s += ")"; //$NON-NLS-1$ + + if (extraArgument != null) { + s += "(" + extraArgument.toString(0) + ")"; + } + + + + if (thrownExceptions != null) { + s += " throws "; //$NON-NLS-1$ + for (int i = 0; i < thrownExceptions.length; i++) { + s += thrownExceptions[i].toString(0); + if (i != (thrownExceptions.length - 1)) + s = s + ", "; //$NON-NLS-1$ + }; + }; + + s += ": "; + if (pointcutDesignator != null) { + s += pointcutDesignator.toString(0); + } + + s += toStringStatements(tab + 1); + return s; + } + + public void modifyKind(char[] name) { + this.selector = CharArrayOps.concat(selector, name); + } + +// public boolean finishResolveTypes(SourceTypeBinding sourceTypeBinding) { +// if (this.ignoreFurtherInvestigation) { +// return false; +// } +// +// if ((binding.modifiers & AccUnresolved) == 0) return true; +// +// //System.err.println("this " + this + ", " + binding.modifiers); +// binding.modifiers ^= AccUnresolved; +// //System.err.println(" post " + binding.modifiers); +// +// +// return super.finishResolveTypes(sourceTypeBinding) && +// pointcutDesignator.finishResolveTypes(this, this.binding, baseArgumentCount, sourceTypeBinding) +// ; +// } + + + public void postParse(TypeDeclaration typeDec) { + this.selector = + NameMangler.adviceName(EclipseWorld.fromBinding(typeDec.binding), kind, sourceStart).toCharArray(); + finishParsing(); + pointcutDesignator.postParse(typeDec, this); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectClinit.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectClinit.java new file mode 100644 index 000000000..d1e77d4c2 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectClinit.java @@ -0,0 +1,48 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.weaver.AjcMemberMaker; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.Clinit; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; + +public class AspectClinit extends Clinit { + public AspectClinit(Clinit old, CompilationResult compilationResult) { + super(compilationResult); + this.needFreeReturn = old.needFreeReturn; + this.sourceEnd = old.sourceEnd; + this.sourceStart = old.sourceStart; + this.declarationSourceEnd = old.declarationSourceEnd; + this.declarationSourceStart = old.declarationSourceStart; + } + + protected void generateSyntheticCode( + ClassScope classScope, + CodeStream codeStream) + { + if (!classScope.referenceContext.binding.isAbstract()) { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + + codeStream.invokestatic(world.makeMethodBindingForCall( + AjcMemberMaker.ajcClinitMethod( + world.fromBinding(classScope.referenceContext.binding) + ))); + } + super.generateSyntheticCode(classScope, codeStream); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java new file mode 100644 index 000000000..ef48a39db --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java @@ -0,0 +1,705 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.io.*; +import java.lang.reflect.Modifier; + +import org.apache.bcel.classfile.AccessFlags; +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.weaver.*; +import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.patterns.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.codegen.*; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; + + +// making all aspects member types avoids a nasty hierarchy pain +public class AspectDeclaration extends MemberTypeDeclaration { + //public IAjDeclaration[] ajDeclarations; + + private AjAttribute.Aspect aspectAttribute; + public PerClause perClause; + public ResolvedMember aspectOfMethod; + public ResolvedMember hasAspectMethod; + + + public boolean isPrivileged; + + public EclipseObjectType typeX; + public EclipseWorld world; //??? should use this consistently + + + // for better error messages in 1.0 to 1.1 transition + public TypePattern dominatesPattern; + + public AspectDeclaration(CompilationResult compilationResult) { + super(compilationResult); + //perClause = new PerSingleton(); + } + + public boolean isAbstract() { + return (modifiers & AccAbstract) != 0; + } + + public void checkSpec(ClassScope scope) { + if (ignoreFurtherInvestigation) return; + if (dominatesPattern != null) { + scope.problemReporter().signalError( + dominatesPattern.getStart(), dominatesPattern.getEnd(), + "dominates has changed for 1.1, use 'declare dominates: " + + new String(this.name) + ", " + dominatesPattern.toString() + ";' " + + "in the body of the aspect instead"); + } + + if (!isAbstract()) { + MethodBinding[] methods = binding.methods(); + for (int i=0, len = methods.length; i < len; i++) { + MethodBinding m = methods[i]; + if (m.isConstructor()) { + // this make all constructors in aspects invisible and thus uncallable + //XXX this only works for aspects that come from source + methods[i] = new MethodBinding(m, binding) { + public boolean canBeSeenBy( + InvocationSite invocationSite, + Scope scope) { + return false; + } + }; + + if (m.parameters != null && m.parameters.length != 0) { + scope.problemReporter().signalError(m.sourceStart(), m.sourceEnd(), + "only zero-argument constructors allowed in concrete aspect"); + } + } + } + } + + if (this.enclosingType != null) { + if (!Modifier.isStatic(modifiers)) { + scope.problemReporter().signalError(sourceStart, sourceEnd, + "inner aspects must be static"); + ignoreFurtherInvestigation = true; + return; + } + } + + + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(scope); + ResolvedTypeX myType = world.fromEclipse(binding); + ResolvedTypeX superType = myType.getSuperclass().resolve(world); + + // can't be Serializable/Cloneable unless -XserializableAspects + if (!world.buildManager.buildConfig.isXserializableAspects()) { + if (world.resolve(TypeX.SERIALIZABLE).isAssignableFrom(myType)) { + scope.problemReporter().signalError(sourceStart, sourceEnd, + "aspects may not implement Serializable"); + ignoreFurtherInvestigation = true; + return; + } + if (world.resolve(TypeX.CLONEABLE).isAssignableFrom(myType)) { + scope.problemReporter().signalError(sourceStart, sourceEnd, + "aspects may not implement Cloneable"); + ignoreFurtherInvestigation = true; + return; + } + + } + + + + if (superType.isAspect()) { + if (!superType.isAbstract()) { + scope.problemReporter().signalError(sourceStart, sourceEnd, + "can not extend a concrete aspect"); + ignoreFurtherInvestigation = true; + return; + } + } + + //XXX need to move this somewhere that it will be applied to classes and interfaces + // as well as to aspects, also need to handle inheritance and overriding +// ResolvedMember[] pointcuts = myType.getDeclaredPointcuts(); +// for (int i=0, len=pointcuts.length; i < len; i++) { +// for (int j=i+1; j < len; j++) { +// if (pointcuts[i].getName().equals(pointcuts[j].getName())) { +// scope.problemReporter().signalError(0, 0, +// "duplicate pointcut name: " + pointcuts[i].getName()); +// } +// } +// } + } + + + + public void generateCode(ClassFile enclosingClassFile) { + if (ignoreFurtherInvestigation) { + if (binding == null) + return; + ClassFile.createProblemType( + this, + scope.referenceCompilationUnit().compilationResult); + return; + } + + + // make me and my binding public + this.modifiers = AstUtil.makePublic(this.modifiers); + this.binding.modifiers = AstUtil.makePublic(this.binding.modifiers); + + + if (!isAbstract()) { + if (perClause == null) { + // we've already produced an error for this + } else if (perClause.getKind() == PerClause.SINGLETON) { + binding.addField(world.makeFieldBinding(AjcMemberMaker.perSingletonField( + typeX))); + methods[0] = new AspectClinit((Clinit)methods[0], compilationResult); + } else if (perClause.getKind() == PerClause.PERCFLOW) { + binding.addField( + world.makeFieldBinding( + AjcMemberMaker.perCflowField( + typeX))); + methods[0] = new AspectClinit((Clinit)methods[0], compilationResult); + } else if (perClause.getKind() == PerClause.PEROBJECT) { +// binding.addField( +// world.makeFieldBinding( +// AjcMemberMaker.perCflowField( +// typeX))); + } else { + throw new RuntimeException("unimplemented"); + } + } + + if (EclipseWorld.DEBUG) System.out.println(toString(0)); + + super.generateCode(enclosingClassFile); + } + + public boolean needClassInitMethod() { + return true; + } + + + protected void generateAttributes(ClassFile classFile) { + if (!isAbstract()) generatePerSupportMembers(classFile); + + classFile.extraAttributes.add( + new EclipseAttributeAdapter(new AjAttribute.Aspect(perClause))); + + if (binding.privilegedHandler != null) { + ResolvedMember[] members = ((PrivilegedHandler)binding.privilegedHandler).getMembers(); + classFile.extraAttributes.add( + new EclipseAttributeAdapter(new AjAttribute.PrivilegedAttribute(members))); + } + + //XXX need to get this attribute on anyone with a pointcut for good errors + classFile.extraAttributes.add( + new EclipseAttributeAdapter(new AjAttribute.SourceContextAttribute( + new String(compilationResult().getFileName()), + compilationResult().lineSeparatorPositions))); + + super.generateAttributes(classFile); + } + + private void generatePerSupportMembers(ClassFile classFile) { + if (isAbstract()) return; + + //XXX otherwise we need to have this (error handling?) + if (aspectOfMethod == null) return; + if (perClause == null) { + System.err.println("has null perClause: " + this); + return; + } + + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + + if (perClause.getKind() == PerClause.SINGLETON) { + generatePerSingletonAspectOfMethod(classFile); + generatePerSingletonHasAspectMethod(classFile); + generatePerSingletonAjcClinitMethod(classFile); + } else if (perClause.getKind() == PerClause.PERCFLOW) { + generatePerCflowAspectOfMethod(classFile); + generatePerCflowHasAspectMethod(classFile); + generatePerCflowPushMethod(classFile); + generatePerCflowAjcClinitMethod(classFile); + } else if (perClause.getKind() == PerClause.PEROBJECT) { + TypeBinding interfaceType = + generatePerObjectInterface(classFile); + world.addTypeBinding(interfaceType); + generatePerObjectAspectOfMethod(classFile, interfaceType); + generatePerObjectHasAspectMethod(classFile, interfaceType); + generatePerObjectBindMethod(classFile, interfaceType); + } else { + throw new RuntimeException("unimplemented"); + } + } + + + private static interface BodyGenerator { + public void generate(CodeStream codeStream); + } + + + private void generateMethod(ClassFile classFile, ResolvedMember member, BodyGenerator gen) { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, world.makeMethodBinding(member), gen); + } + + private void generateMethod(ClassFile classFile, MethodBinding methodBinding, BodyGenerator gen) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + classFile.generateMethodInfoHeader(methodBinding); + int methodAttributeOffset = classFile.contentsOffset; + int attributeNumber = classFile.generateMethodInfoAttribute(methodBinding, AstUtil.getAjSyntheticAttribute()); + int codeAttributeOffset = classFile.contentsOffset; + classFile.generateCodeAttributeHeader(); + CodeStream codeStream = classFile.codeStream; + codeStream.init(classFile); + codeStream.initializeMaxLocals(methodBinding); + // body starts here + gen.generate(codeStream); + // body ends here + classFile.completeCodeAttribute(codeAttributeOffset); + attributeNumber++; + classFile.completeMethodInfo(methodAttributeOffset, attributeNumber); + } + + + private void generatePerCflowAspectOfMethod( + ClassFile classFile) + { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, aspectOfMethod, new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + codeStream.getstatic( + world.makeFieldBinding( + AjcMemberMaker.perCflowField( + typeX))); + codeStream.invokevirtual(world.makeMethodBindingForCall( + AjcMemberMaker.cflowStackPeekInstance())); + codeStream.checkcast(binding); + codeStream.areturn(); + // body ends here + }}); + + } + + + private void generatePerCflowHasAspectMethod(ClassFile classFile) { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, hasAspectMethod, new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + codeStream.getstatic( + world.makeFieldBinding( + AjcMemberMaker.perCflowField( + typeX))); + codeStream.invokevirtual(world.makeMethodBindingForCall( + AjcMemberMaker.cflowStackIsValid())); + codeStream.ireturn(); + // body ends here + }}); + } + + private void generatePerCflowPushMethod( + ClassFile classFile) + { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, world.makeMethodBinding(AjcMemberMaker.perCflowPush( + world.fromBinding(binding))), + new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + codeStream.getstatic( + world.makeFieldBinding( + AjcMemberMaker.perCflowField( + typeX))); + codeStream.new_(binding); + codeStream.dup(); + codeStream.invokespecial( + new MethodBinding(0, "<init>".toCharArray(), + BaseTypes.VoidBinding, new TypeBinding[0], + new ReferenceBinding[0], binding)); + + + codeStream.invokevirtual(world.makeMethodBindingForCall( + AjcMemberMaker.cflowStackPushInstance())); + codeStream.return_(); + // body ends here + }}); + + } + + + + + private void generatePerCflowAjcClinitMethod( + ClassFile classFile) + { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, world.makeMethodBinding(AjcMemberMaker.ajcClinitMethod( + world.fromBinding(binding))), + new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + codeStream.new_(world.makeTypeBinding(AjcMemberMaker.CFLOW_STACK_TYPE)); + codeStream.dup(); + codeStream.invokespecial(world.makeMethodBindingForCall(AjcMemberMaker.cflowStackInit())); + codeStream.putstatic( + world.makeFieldBinding( + AjcMemberMaker.perCflowField( + typeX))); + codeStream.return_(); + // body ends here + }}); + + } + + + private TypeBinding generatePerObjectInterface( + ClassFile classFile) + { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + TypeX interfaceTypeX = + AjcMemberMaker.perObjectInterfaceType(typeX); + HelperInterfaceBinding interfaceType = + new HelperInterfaceBinding(this.binding, interfaceTypeX); + world.addTypeBinding(interfaceType); + interfaceType.addMethod(world, AjcMemberMaker.perObjectInterfaceGet(typeX)); + interfaceType.addMethod(world, AjcMemberMaker.perObjectInterfaceSet(typeX)); + interfaceType.generateClass(compilationResult, classFile); + return interfaceType; + } + + + private void generatePerObjectAspectOfMethod( + ClassFile classFile, + final TypeBinding interfaceType) + { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, aspectOfMethod, new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + Label wrongType = new Label(codeStream); + Label popWrongType = new Label(codeStream); + codeStream.aload_0(); + codeStream.instance_of(interfaceType); + codeStream.ifeq(wrongType); + codeStream.aload_0(); + codeStream.checkcast(interfaceType); + codeStream.invokeinterface(world.makeMethodBindingForCall( + AjcMemberMaker.perObjectInterfaceGet(typeX))); + + codeStream.dup(); + codeStream.ifnull(popWrongType); + codeStream.areturn(); + + popWrongType.place(); + codeStream.pop(); + + wrongType.place(); + codeStream.new_(world.makeTypeBinding(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION)); + codeStream.dup(); + codeStream.invokespecial(world.makeMethodBindingForCall( + AjcMemberMaker.noAspectBoundExceptionInit() + )); + codeStream.athrow(); + // body ends here + }}); + + } + + + private void generatePerObjectHasAspectMethod(ClassFile classFile, + final TypeBinding interfaceType) { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, hasAspectMethod, new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + Label wrongType = new Label(codeStream); + codeStream.aload_0(); + codeStream.instance_of(interfaceType); + codeStream.ifeq(wrongType); + codeStream.aload_0(); + codeStream.checkcast(interfaceType); + codeStream.invokeinterface(world.makeMethodBindingForCall( + AjcMemberMaker.perObjectInterfaceGet(typeX))); + codeStream.ifnull(wrongType); + codeStream.iconst_1(); + codeStream.ireturn(); + + wrongType.place(); + codeStream.iconst_0(); + codeStream.ireturn(); + // body ends here + }}); + } + + private void generatePerObjectBindMethod( + ClassFile classFile, + final TypeBinding interfaceType) + { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, AjcMemberMaker.perObjectBind(world.fromBinding(binding)), + new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + Label wrongType = new Label(codeStream); + codeStream.aload_0(); + codeStream.instance_of(interfaceType); + codeStream.ifeq(wrongType); //XXX this case might call for screaming + codeStream.aload_0(); + codeStream.checkcast(interfaceType); + codeStream.invokeinterface(world.makeMethodBindingForCall( + AjcMemberMaker.perObjectInterfaceGet(typeX))); + //XXX should do a check for null here and throw a NoAspectBound + codeStream.ifnonnull(wrongType); + + codeStream.aload_0(); + codeStream.checkcast(interfaceType); + codeStream.new_(binding); + codeStream.dup(); + codeStream.invokespecial( + new MethodBinding(0, "<init>".toCharArray(), + BaseTypes.VoidBinding, new TypeBinding[0], + new ReferenceBinding[0], binding)); + codeStream.invokeinterface(world.makeMethodBindingForCall( + AjcMemberMaker.perObjectInterfaceSet(typeX))); + + wrongType.place(); + codeStream.return_(); + // body ends here + }}); + } + + + + private void generatePerSingletonAspectOfMethod(ClassFile classFile) { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, aspectOfMethod, new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + codeStream.getstatic(world.makeFieldBinding(AjcMemberMaker.perSingletonField( + typeX))); + codeStream.areturn(); + // body ends here + }}); + } + + private void generatePerSingletonHasAspectMethod(ClassFile classFile) { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, hasAspectMethod, new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + codeStream.getstatic(world.makeFieldBinding(AjcMemberMaker.perSingletonField( + typeX))); + Label isNull = new Label(codeStream); + codeStream.ifnull(isNull); + codeStream.iconst_1(); + codeStream.ireturn(); + isNull.place(); + codeStream.iconst_0(); + codeStream.ireturn(); + // body ends here + }}); + } + + + private void generatePerSingletonAjcClinitMethod( + ClassFile classFile) + { + final EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(this.scope); + generateMethod(classFile, world.makeMethodBinding(AjcMemberMaker.ajcClinitMethod( + world.fromBinding(binding))), + new BodyGenerator() { + public void generate(CodeStream codeStream) { + // body starts here + codeStream.new_(binding); + codeStream.dup(); + codeStream.invokespecial( + new MethodBinding(0, "<init>".toCharArray(), + BaseTypes.VoidBinding, new TypeBinding[0], + new ReferenceBinding[0], binding)); + + codeStream.putstatic( + world.makeFieldBinding( + AjcMemberMaker.perSingletonField( + typeX))); + codeStream.return_(); + // body ends here + }}); + + } + + + private PerClause.Kind lookupPerClauseKind(ReferenceBinding binding) { + if (binding instanceof SourceTypeBinding) { + SourceTypeBinding sourceSc = (SourceTypeBinding)binding; + if (sourceSc.scope.referenceContext instanceof AspectDeclaration) { + PerClause perClause = ((AspectDeclaration)sourceSc.scope.referenceContext).perClause; + if (perClause == null) return lookupPerClauseKind(binding.superclass()); + else return perClause.getKind(); + } else { + return null; + } + } else { + //XXX need to handle this too + return null; + } + } + + + private void buildPerClause(ClassScope scope) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(scope); + + if (perClause == null) { + PerClause.Kind kind = lookupPerClauseKind(binding.superclass); + if (kind == null) { + perClause = new PerSingleton(); + } else { + perClause = new PerFromSuper(kind); + } + } + + + //perClause.concretize(world.fromEclipse(binding)); + aspectAttribute = new AjAttribute.Aspect(perClause); + + if (ignoreFurtherInvestigation) return; //??? + + + if (!isAbstract()) { + if (perClause.getKind() == PerClause.SINGLETON) { + aspectOfMethod = AjcMemberMaker.perSingletonAspectOfMethod(typeX); + hasAspectMethod = AjcMemberMaker.perSingletonHasAspectMethod(typeX); + } else if (perClause.getKind() == PerClause.PERCFLOW) { + aspectOfMethod = AjcMemberMaker.perCflowAspectOfMethod(typeX); + hasAspectMethod = AjcMemberMaker.perCflowHasAspectMethod(typeX); + } else if (perClause.getKind() == PerClause.PEROBJECT) { + aspectOfMethod = AjcMemberMaker.perObjectAspectOfMethod(typeX); + hasAspectMethod = AjcMemberMaker.perObjectHasAspectMethod(typeX); + } else { + throw new RuntimeException("bad per clause: " + perClause); + } + + binding.addMethod(world.makeMethodBinding(aspectOfMethod)); + binding.addMethod(world.makeMethodBinding(hasAspectMethod)); + } + resolvePerClause(); //XXX might be too soon for some error checking + } + + + private PerClause resolvePerClause() { + EclipseScope iscope = new EclipseScope(new FormalBinding[0], scope); + perClause.resolve(iscope); + return perClause; + } + + + + public void buildInterTypeAndPerClause(ClassScope classScope) { + checkSpec(classScope); + if (ignoreFurtherInvestigation) return; + + world = EclipseWorld.fromScopeLookupEnvironment(scope); + typeX = (EclipseObjectType)world.fromEclipse(binding); + + if (isPrivileged) { + binding.privilegedHandler = new PrivilegedHandler(this); + } + + CrosscuttingMembers xcut = new CrosscuttingMembers(typeX); + typeX.crosscuttingMembers = xcut; + //XXXxcut.setPerClause(buildPerClause(scope)); + buildPerClause(scope); + + if (methods != null) { + for (int i = 0; i < methods.length; i++) { + if (methods[i] instanceof InterTypeDeclaration) { + ((InterTypeDeclaration)methods[i]).build(classScope, xcut); + } else if (methods[i] instanceof DeclareDeclaration) { + ((DeclareDeclaration)methods[i]).build(classScope, xcut); + } + } + } + + world.getCrosscuttingMembersSet().addOrReplaceAspect(typeX); + } + + + public String toString(int tab) { + return tabString(tab) + toStringHeader() + toStringBody(tab); + } + + public String toStringBody(int tab) { + + String s = " {"; //$NON-NLS-1$ + + + if (memberTypes != null) { + for (int i = 0; i < memberTypes.length; i++) { + if (memberTypes[i] != null) { + s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$ + } + } + } + if (fields != null) { + for (int fieldI = 0; fieldI < fields.length; fieldI++) { + if (fields[fieldI] != null) { + s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$ + if (fields[fieldI].isField()) + s += ";"; //$NON-NLS-1$ + } + } + } + if (methods != null) { + for (int i = 0; i < methods.length; i++) { + if (methods[i] != null) { + s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$ + } + } + } + s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$ + return s; + } + + public String toStringHeader() { + + String s = ""; //$NON-NLS-1$ + if (modifiers != AccDefault) { + s += modifiersString(modifiers); + } + s += "aspect " + new String(name);//$NON-NLS-1$ //$NON-NLS-2$ + if (superclass != null) + s += " extends " + superclass.toString(0); //$NON-NLS-1$ + if (superInterfaces != null && superInterfaces.length > 0) { + s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$ + for (int i = 0; i < superInterfaces.length; i++) { + s += superInterfaces[i].toString(0); + if (i != superInterfaces.length - 1) + s += ", "; //$NON-NLS-1$ + }; + }; + return s; + } + + +} + diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AstUtil.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AstUtil.java new file mode 100644 index 000000000..9d17dddb7 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AstUtil.java @@ -0,0 +1,256 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.List; + +import org.aspectj.weaver.*; +import org.aspectj.weaver.AjAttribute.AjSynthetic; +import org.aspectj.weaver.ast.ASTNode; +import org.aspectj.weaver.patterns.WildTypePattern; +import org.eclipse.jdt.internal.compiler.ClassFile; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.env.IConstants; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + +public class AstUtil { + + private AstUtil() {} + + public static void addMethodBinding(SourceTypeBinding sourceType, MethodBinding method) { + int len = sourceType.methods.length; + MethodBinding[] temp = new MethodBinding[len + 1]; + System.arraycopy(sourceType.methods, 0, temp, 0, len); + temp[len] = method; + sourceType.methods = temp; + } + + + public static void addMethodDeclaration(TypeDeclaration typeDec, AbstractMethodDeclaration dec) { + AbstractMethodDeclaration[] methods = typeDec.methods; + int len = methods.length; + AbstractMethodDeclaration[] newMethods = new AbstractMethodDeclaration[len+1]; + System.arraycopy(methods, 0, newMethods, 0, len); + newMethods[len] = dec; + typeDec.methods = newMethods; + } + + + public static Argument makeFinalArgument(char[] name, TypeBinding typeBinding) { + long pos = 0; //XXX encode start and end location + LocalVariableBinding binding = + new LocalVariableBinding(name, typeBinding, Modifier.FINAL, true); + Argument ret = new Argument(name, pos, makeTypeReference(typeBinding), Modifier.FINAL); + ret.binding = binding; + return ret; + } + + public static TypeReference makeTypeReference(TypeBinding binding) { + // ??? does this work for primitives + QualifiedTypeReference ref = + new QualifiedTypeReference(new char[][] {binding.sourceName()}, binding, new long[] {0}); //??? + ref.constant = Constant.NotAConstant; + return ref; + } + + + public static NameReference makeNameReference(TypeBinding binding) { + QualifiedNameReference ref = + new QualifiedNameReference(new char[][] {binding.sourceName()}, 0, 0); + ref.binding = binding; ref.constant = Constant.NotAConstant; + return ref; + } + + + + + + public static ReturnStatement makeReturnStatement(Expression expr) { + return new ReturnStatement(expr, 0, 0); + } + + public static MethodDeclaration makeMethodDeclaration( + MethodBinding binding) + { + MethodDeclaration ret = new MethodDeclaration(null); + ret.binding = binding; + int nargs = binding.parameters.length; + ret.arguments = new Argument[nargs]; + for (int i=0; i < nargs; i++) { + ret.arguments[i] = makeFinalArgument(("arg"+i).toCharArray(), + binding.parameters[i]); + } + return ret; + } + + public static void setStatements( + MethodDeclaration ret, List statements) + { + ret.statements = + (Statement[])statements.toArray(new Statement[statements.size()]); + } + + public static SingleNameReference makeLocalVariableReference( + LocalVariableBinding binding) + { + SingleNameReference ret = new SingleNameReference(binding.name, 0); + ret.binding = binding; + ret.codegenBinding = binding; + ret.constant = AstNode.NotAConstant; + ret.bits &= ~AstNode.RestrictiveFlagMASK; // clear bits + ret.bits |= BindingIds.VARIABLE; + return ret; + } + + public static SingleNameReference makeResolvedLocalVariableReference( + LocalVariableBinding binding) + { + SingleNameReference ret = new SingleNameReference(binding.name, 0); + ret.binding = binding; + ret.codegenBinding = binding; + ret.constant = AstNode.NotAConstant; + ret.bits &= ~AstNode.RestrictiveFlagMASK; // clear bits + ret.bits |= BindingIds.LOCAL; + return ret; + } + + public static int makePublic(int modifiers) { + modifiers &= ~(IConstants.AccPublic | IConstants.AccPrivate | IConstants.AccProtected); + return modifiers | IConstants.AccPublic; + } + + public static CompilationUnitScope getCompilationUnitScope(Scope scope) { + if (scope instanceof CompilationUnitScope) { + return (CompilationUnitScope)scope; + } + return getCompilationUnitScope(scope.parent); + } + + + public static void generateReturn(TypeBinding returnType, CodeStream codeStream) { + if (returnType.id == TypeIds.T_void) { + codeStream.return_(); + } else if (returnType.isBaseType()) { + switch (returnType.id) { + case TypeBinding.T_boolean : + case TypeBinding.T_int : + case TypeBinding.T_byte : + case TypeBinding.T_short : + case TypeBinding.T_char : + codeStream.ireturn(); + break; + case TypeBinding.T_float : + codeStream.freturn(); + break; + case TypeBinding.T_long : + codeStream.lreturn(); + break; + case TypeBinding.T_double : + codeStream.dreturn(); + break; + default : + throw new RuntimeException("huh"); + } + } else { + codeStream.areturn(); + } + } + + //XXX this could be inconsistent for wierd case, i.e. a class named "java_lang_String" + public static char[] makeMangledName(ReferenceBinding type) { + return CharOperation.concatWith(type.compoundName, '_'); + } + + + + public static final char[] PREFIX = "ajc".toCharArray(); + + //XXX not efficient + public static char[] makeAjcMangledName(char[] kind, ReferenceBinding type, char[] name) { + return CharOperation.concat( + CharOperation.concat(PREFIX, new char[] {'$'}, kind), '$', makeMangledName(type), '$', name); + } + + public static char[] makeAjcMangledName(char[] kind, char[] p, char[] name) { + return CharOperation.concat( + CharOperation.concat(PREFIX, new char[] {'$'}, kind), '$', p, '$', name); + } + + public static List getAjSyntheticAttribute() { + ArrayList ret = new ArrayList(1); + ret.add(new EclipseAttributeAdapter(new AjAttribute.AjSynthetic())); + return ret; + } + + public static long makeLongPos(int start, int end) { + return (long)end | ((long)start << 32); + } + public static char[][] getCompoundName(String string) { + return WildTypePattern.splitNames(string); + } + + public static TypeBinding[] insert( + TypeBinding first, + TypeBinding[] rest) { + if (rest == null) { + return new TypeBinding[] {first}; + } + + int len = rest.length; + TypeBinding[] ret = new TypeBinding[len+1]; + ret[0] = first; + System.arraycopy(rest, 0, ret, 1, len); + return ret; + } + public static Argument[] insert( + Argument first, + Argument[] rest) { + if (rest == null) { + return new Argument[] {first}; + } + + int len = rest.length; + Argument[] ret = new Argument[len+1]; + ret[0] = first; + System.arraycopy(rest, 0, ret, 1, len); + return ret; + } + public static Argument[] copyArguments(Argument[] inArgs) { + if (inArgs == null) return new Argument[] {}; + int len = inArgs.length; + Argument[] outArgs = new Argument[len]; + //??? we're not sure whether or not copying these is okay + System.arraycopy(inArgs, 0, outArgs, 0, len); + return outArgs; + } + + public static Statement[] remove(int i, Statement[] statements) { + int len = statements.length; + Statement[] ret = new Statement[len-1]; + System.arraycopy(statements, 0, ret, 0, i); + System.arraycopy(statements, i+1, ret, i, len-i-1); + return ret; + } + public static int slotsNeeded(TypeBinding type) { + if (type == BaseTypes.DoubleBinding || type == BaseTypes.LongBinding) return 2; + else return 1; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareDeclaration.java new file mode 100644 index 000000000..3433a0db1 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareDeclaration.java @@ -0,0 +1,114 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope; +import org.aspectj.weaver.*; +import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.patterns.*; +import org.aspectj.weaver.patterns.Declare; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; +import org.eclipse.jdt.internal.compiler.parser.Parser; + +public class DeclareDeclaration extends MethodDeclaration implements IAjDeclaration { + public Declare declare; + + /** + * Constructor for IntraTypeDeclaration. + */ + static int counter = 0; //XXX evil + public DeclareDeclaration(CompilationResult result, Declare symbolicDeclare) { + super(result); + this.declare = symbolicDeclare; + if (declare != null) { + sourceStart = declare.getStart(); + sourceEnd = declare.getEnd(); + } + //??? we might need to set parameters to be empty + this.returnType = TypeReference.baseTypeReference(T_void, 0); + this.selector = ("ajc$declare_"+counter++).toCharArray(); //??? performance + } + + + /** + * A pointcut declaration exists in a classfile only as an attibute on the + * class. Unlike advice and inter-type declarations, it has no corresponding + * method. + */ + public void generateCode(ClassScope classScope, ClassFile classFile) { + classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.DeclareAttribute(declare))); + return; + } + + public void parseStatements( + Parser parser, + CompilationUnitDeclaration unit) { + // do nothing + } + + public void resolveStatements(ClassScope upperScope) { + // do nothing + } + +// public boolean finishResolveTypes(SourceTypeBinding sourceTypeBinding) { +// // there's nothing for our super to resolve usefully +// //if (!super.finishResolveTypes(sourceTypeBinding)) return false; +//// if (declare == null) return true; +//// +//// EclipseScope scope = new EclipseScope(new FormalBinding[0], this.scope); +//// +//// declare.resolve(scope); +//// return true; +// } + + + public void build(ClassScope classScope, CrosscuttingMembers xcut) { + if (declare == null) return; + + EclipseScope scope = new EclipseScope(new FormalBinding[0], classScope); + + declare.resolve(scope); + xcut.addDeclare(declare); + + //EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + //XXX need to work out the eclipse side of all this state +//XXX world.addDeclare(world.resolve(EclipseWorld.fromBinding(classScope.referenceContext.binding)), +//XXX declare, false); + + + + +// binding = makeMethodBinding(classScope); +// world.addTypeMunger(new EclipseNewMethodTypeMunger(binding)); +// //??? what do we need to know +// munger = new NewMethodTypeMunger( +// EclipseWorld.makeResolvedMember(binding.introducedMethod), +// EclipseWorld.makeResolvedMember(super.binding), null); + } + + + + + + + public String toString(int tab) { + if (declare == null) return tabString(tab) + "<declare>"; + else return tabString(tab) + declare.toString(); + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/EclipseAttributeAdapter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/EclipseAttributeAdapter.java new file mode 100644 index 000000000..b7d534d14 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/EclipseAttributeAdapter.java @@ -0,0 +1,34 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.weaver.AjAttribute; +import org.eclipse.jdt.internal.compiler.IAttribute; + +public class EclipseAttributeAdapter implements IAttribute { + AjAttribute attr; + + public EclipseAttributeAdapter(AjAttribute attr) { + this.attr = attr; + } + + public char[] getNameChars() { + return attr.getNameChars(); + } + + public byte[] getAllBytes(short nameIndex) { + return attr.getAllBytes(nameIndex); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IAjDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IAjDeclaration.java new file mode 100644 index 000000000..e4e2f52f1 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IAjDeclaration.java @@ -0,0 +1,22 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; + +public interface IAjDeclaration { +// public String toString(int tab); +// void postParse(TypeDeclaration typeDec); + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IfMethodDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IfMethodDeclaration.java new file mode 100644 index 000000000..1bca70dfb --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IfMethodDeclaration.java @@ -0,0 +1,55 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.weaver.*; +import org.aspectj.weaver.patterns.IfPointcut; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; +import org.eclipse.jdt.internal.compiler.parser.Parser; + +public class IfMethodDeclaration extends MethodDeclaration { + IfPointcut ifPointcut; + + public IfMethodDeclaration(CompilationResult compilationResult, IfPointcut ifPointcut) { + super(compilationResult); + this.ifPointcut = ifPointcut; + } + + public void parseStatements( + Parser parser, + CompilationUnitDeclaration unit) { + // do nothing, we're already fully parsed + } + + public void resolveStatements(ClassScope upperScope) { + super.resolveStatements(upperScope); + if (binding != null) { + ThisJoinPointVisitor tjp = new ThisJoinPointVisitor(this); + ifPointcut.extraParameterFlags |= tjp.removeUnusedExtraArguments(); + + //XXX this is where we should remove unavailable args if we're in a cflow + + ifPointcut.testMethod = new ResolvedMember( + Member.METHOD, + EclipseWorld.fromBinding(binding.declaringClass), + this.modifiers, ResolvedTypeX.BOOLEAN, + new String(this.selector), + EclipseWorld.fromBindings(this.binding.parameters)); + } + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IfPseudoToken.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IfPseudoToken.java new file mode 100644 index 000000000..653039b96 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/IfPseudoToken.java @@ -0,0 +1,111 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.lang.reflect.Modifier; + +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.weaver.*; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.patterns.*; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.parser.*; + + +/** + * (formals*): ... if(expr) ... + * + * generates the following: + * public static final boolean ajc$if_N(formals*, [thisJoinPoints as needed]) { + * return expr; + * } + * + * Here's the complicated bit, it deals with cflow: + * (a): ... this(a) && cflow(if (a == foo)) is an error. + * The way we capture this is: + * We generate the ajc$if method with an (a) parameter, we let eclipse do the proper + * name binding. We then, as a post pass (that we need to do anyway) look for the + * used parameters. If a is used, we signal an error because a was not one of the + * cflow variables. + * XXX we'll do this part after we do cflow + * + * The IfPointcut pcd then generates itself always as a dynamic test, it has to + * get the right parameters through any named pointcut references... + */ +public class IfPseudoToken extends PseudoToken { + public Expression expr; + public MethodDeclaration testMethod; + private IfPointcut pointcut; + + public IfPseudoToken( + Parser parser, + Expression expr) { + super(parser, "if", false); + this.expr = expr; + } + + public Pointcut maybeGetParsedPointcut() { + pointcut = new IfPointcut(new ResolvedMember(Member.METHOD, TypeX.OBJECT, 0, "if_", "()V"), 0); + return pointcut; + } + + + /** + * enclosingDec is either AdviceDeclaration or PointcutDeclaration + */ + public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { +// typeDec.scope.problemReporter().signalError(sourceStart, sourceEnd, +// "if pcd is not implemented in 1.1alpha1"); + //XXX need to implement correctly + if (pointcut == null) return; + testMethod = makeMethod(enclosingDec.compilationResult, enclosingDec); + AstUtil.addMethodDeclaration(typeDec, testMethod); + } + + + //XXX static state bad + private static int counter = 0; + + //XXX todo: make sure that errors in Arguments only get displayed once + private MethodDeclaration makeMethod(CompilationResult result, MethodDeclaration enclosingDec) { + MethodDeclaration ret = new IfMethodDeclaration(result, pointcut); + ret.modifiers = AccStatic | AccFinal | AccPublic; + ret.returnType = AstUtil.makeTypeReference(TypeBinding.BooleanBinding); + ret.selector = ("ajc$if_" + counter++).toCharArray(); + ret.arguments = makeArguments(enclosingDec); + ret.statements = new Statement[] { + new ReturnStatement(expr, expr.sourceStart, expr.sourceEnd) + }; + return ret; + } + + private Argument[] makeArguments(MethodDeclaration enclosingDec) { + Argument[] baseArguments = enclosingDec.arguments; + int len = baseArguments.length; + Argument[] ret = new Argument[len]; + for (int i=0; i < len; i ++) { + Argument a = baseArguments[i]; + ret[i] = new Argument(a.name, AstUtil.makeLongPos(a.sourceStart, a.sourceEnd), + a.type, Modifier.FINAL); + } + if (!(enclosingDec instanceof AdviceDeclaration)) { + ret = AdviceDeclaration.addTjpArguments(ret); + } + + return ret; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java new file mode 100644 index 000000000..275a3bc04 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java @@ -0,0 +1,256 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.weaver.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.parser.Parser; + + +public class InterTypeConstructorDeclaration extends InterTypeDeclaration { + private MethodDeclaration preMethod; + private ExplicitConstructorCall explicitConstructorCall = null; + + public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) { + super(result, onType); + } + + public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { + if (ignoreFurtherInvestigation) + return; + parser.parseAsConstructor(this, unit); + } + + public void resolve(ClassScope upperScope) { + if (munger == null || binding == null) ignoreFurtherInvestigation = true; + if (ignoreFurtherInvestigation) return; + + explicitConstructorCall = null; + if (statements != null && statements.length > 0 && + statements[0] instanceof ExplicitConstructorCall) + { + explicitConstructorCall = (ExplicitConstructorCall) statements[0]; + statements = AstUtil.remove(0, statements); + } + + preMethod = makePreMethod(upperScope, explicitConstructorCall); + + binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters); + this.arguments = AstUtil.insert( + AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), + this.arguments); + + super.resolve(upperScope); + } + + private MethodDeclaration makePreMethod(ClassScope scope, + ExplicitConstructorCall explicitConstructorCall) + { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(scope); + + TypeX aspectTypeX = EclipseWorld.fromBinding(binding.declaringClass); + TypeX targetTypeX = EclipseWorld.fromBinding(onTypeBinding); + + ArrayBinding objectArrayBinding = scope.createArray(scope.getJavaLangObject(), 1); + + + MethodDeclaration pre = new MethodDeclaration(compilationResult); + pre.modifiers = AccPublic | AccStatic; + pre.returnType = AstUtil.makeTypeReference(objectArrayBinding); + pre.selector = NameMangler.postIntroducedConstructor(aspectTypeX, targetTypeX).toCharArray(); + + + pre.arguments = AstUtil.copyArguments(this.arguments); + + //XXX should do exceptions + + pre.scope = new MethodScope(scope, pre, true); + //??? do we need to do anything with scope??? + + pre.binding = world.makeMethodBinding( + AjcMemberMaker.preIntroducedConstructor(aspectTypeX, targetTypeX, + world.fromBindings(binding.parameters))); + + pre.bindArguments(); + pre.bindThrownExceptions(); + + + if (explicitConstructorCall == null) { + pre.statements = new Statement[] {}; + } else { + pre.statements = new Statement[] { + explicitConstructorCall + }; + } + + InterTypeScope newParent = + new InterTypeScope(scope, onTypeBinding); + pre.scope.parent = newParent; + + pre.resolveStatements(newParent); + + + + int nParams = pre.arguments.length; + MethodBinding explicitConstructor = null; + if (explicitConstructorCall != null) { + explicitConstructor = explicitConstructorCall.binding; + if (explicitConstructor.alwaysNeedsAccessMethod()) { + explicitConstructor = explicitConstructor.getAccessMethod(); + } + } + + int nExprs; + if (explicitConstructor == null) nExprs = 0; + else nExprs = explicitConstructor.parameters.length; + + + ArrayInitializer init = new ArrayInitializer(); + init.expressions = new Expression[nExprs + nParams]; + int index = 0; + for (int i=0; i < nExprs; i++) { + if (i >= explicitConstructorCall.arguments.length) { + init.expressions[index++] = new NullLiteral(0, 0); + continue; + } + + + Expression arg = explicitConstructorCall.arguments[i]; + ResolvedMember conversionMethod = + AjcMemberMaker.toObjectConversionMethod(world.fromBinding(explicitConstructorCall.binding.parameters[i])); + if (conversionMethod != null) { + arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), + new CastExpression(new NullLiteral(0, 0), + AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))), + new Expression[] {arg }); + } + init.expressions[index++] = arg; + } + + for (int i=0; i < nParams; i++) { + LocalVariableBinding binding = pre.arguments[i].binding; + Expression arg = AstUtil.makeResolvedLocalVariableReference(binding); + ResolvedMember conversionMethod = + AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type)); + if (conversionMethod != null) { + arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), + new CastExpression(new NullLiteral(0, 0), + AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))), + new Expression[] {arg }); + } + init.expressions[index++] = arg; + } + + init.binding =objectArrayBinding; + + ArrayAllocationExpression newArray = new ArrayAllocationExpression(); + newArray.initializer = init; + newArray.type = AstUtil.makeTypeReference(scope.getJavaLangObject()); + newArray.dimensions = new Expression[1]; + newArray.constant = NotAConstant; + + + + + pre.statements = new Statement[] { + new ReturnStatement(newArray, 0, 0), + }; + return pre; + } + + + + + public void build(ClassScope classScope, CrosscuttingMembers xcut) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + + binding = classScope.referenceContext.binding.resolveTypesFor(binding); + + resolveOnType(classScope); + if (ignoreFurtherInvestigation) return; + + + if (onTypeBinding.isInterface()) { + ignoreFurtherInvestigation = true; + return; + } + + if (onTypeBinding.isNestedType()) { + classScope.problemReporter().signalError(sourceStart, sourceEnd, + "can't define constructors on nested types (compiler limitation)"); + ignoreFurtherInvestigation = true; + return; + } + + ResolvedTypeX declaringTypeX = world.fromEclipse(onTypeBinding); + ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding); + + ResolvedMember bindingAsMember = world.makeResolvedMember(binding); + + ResolvedMember signature = + new ResolvedMember(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers, + ResolvedTypeX.VOID, "<init>", bindingAsMember.getParameterTypes()); + + ResolvedMember syntheticInterMember = + AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType); + + NewConstructorTypeMunger myMunger = + new NewConstructorTypeMunger(signature, syntheticInterMember, null, null); + this.munger = myMunger; + + this.selector = binding.selector = + NameMangler.postIntroducedConstructor( + EclipseWorld.fromBinding(binding.declaringClass), + declaringTypeX).toCharArray(); + + xcut.addTypeMunger(new EclipseTypeMunger(myMunger, aspectType, this)); + } + + + private AjAttribute makeAttribute(EclipseWorld world) { + if (explicitConstructorCall != null) { + MethodBinding explicitConstructor = explicitConstructorCall.binding; + if (explicitConstructor.alwaysNeedsAccessMethod()) { + explicitConstructor = explicitConstructor.getAccessMethod(); + } + + + ((NewConstructorTypeMunger)munger).setExplicitConstructor( + world.makeResolvedMember(explicitConstructor)); + } else { + ((NewConstructorTypeMunger)munger).setExplicitConstructor( + new ResolvedMember(Member.CONSTRUCTOR, + EclipseWorld.fromBinding(onTypeBinding.superclass()), + 0, ResolvedTypeX.VOID, "<init>", TypeX.NONE)); + } + return new AjAttribute.TypeMunger(munger); + } + + + public void generateCode(ClassScope classScope, ClassFile classFile) { + if (ignoreFurtherInvestigation) return; + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world))); + super.generateCode(classScope, classFile); + + preMethod.generateCode(classScope, classFile); + } + protected Shadow.Kind getShadowKindForBody() { + return Shadow.ConstructorExecution; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java new file mode 100644 index 000000000..62c840f58 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java @@ -0,0 +1,131 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.lang.reflect.Modifier; +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.weaver.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + +public abstract class InterTypeDeclaration extends MethodDeclaration implements IAjDeclaration { + //public AstNode myDeclaration; + public TypeReference onType; + protected ReferenceBinding onTypeBinding; + + protected ResolvedTypeMunger munger; + protected int declaredModifiers; + protected char[] declaredSelector; + + //protected Set superMethodsCalled; + + public InterTypeDeclaration(CompilationResult result, TypeReference onType) { + super(result); + this.onType = onType; + modifiers = AccPublic | AccStatic; + } + + public void setDeclaredModifiers(int modifiers) { + this.declaredModifiers = modifiers; + } + + public void setSelector(char[] selector) { + declaredSelector = selector; + this.selector = CharOperation.concat(selector, Integer.toHexString(sourceStart).toCharArray()); + } + + public void resolve(ClassScope upperScope) { + if (ignoreFurtherInvestigation) return; + + + ClassScope newParent = new InterTypeScope(upperScope, onTypeBinding); + //interBinding.introducedField.declaringClass); + scope.parent = newParent; + this.scope.isStatic = Modifier.isStatic(declaredModifiers); + super.resolve(newParent); + fixSuperCallsInBody(); + } + + /** + * Called from AspectDeclarations.buildInterTypeAndPerClause + */ + public abstract void build(ClassScope classScope, CrosscuttingMembers xcut); + + public void fixSuperCallsInBody() { + SuperFixerVisitor v = new SuperFixerVisitor(this, onTypeBinding); + this.traverse(v, (ClassScope)null); + HashSet set = new HashSet(); + for (Iterator i = v.superMethodsCalled.iterator(); i.hasNext(); ) { + MethodBinding b = (MethodBinding)i.next(); + set.add(EclipseWorld.makeResolvedMember(b)); + } + + munger.setSuperMethodsCalled(set); + } + + protected void resolveOnType(ClassScope classScope) { + checkSpec(); + onTypeBinding = (ReferenceBinding)onType.getTypeBinding(classScope); + if (!onTypeBinding.isValidBinding()) { + if (onTypeBinding instanceof ProblemReferenceBinding) { + classScope.problemReporter().invalidType(onType, onTypeBinding); + } else { + //XXX trouble + } + ignoreFurtherInvestigation = true; + } + } + + + protected void checkSpec() { + if (Modifier.isProtected(declaredModifiers)) { + scope.problemReporter().signalError(sourceStart, sourceEnd, + "protected inter-type declarations are not allowed"); + ignoreFurtherInvestigation = true; + } + } + + protected List makeEffectiveSignatureAttribute( + ResolvedMember sig, + Shadow.Kind kind, + boolean weaveBody) + { + List l = new ArrayList(1); + l.add(new EclipseAttributeAdapter( + new AjAttribute.EffectiveSignatureAttribute(sig, kind, weaveBody))); + return l; + } + + protected int generateInfoAttributes(ClassFile classFile) { + munger.getSignature().setPosition(sourceStart, sourceEnd); + + //System.out.println("generating effective for " + this); + List l;; + Shadow.Kind kind = getShadowKindForBody(); + if (kind != null) { + l = makeEffectiveSignatureAttribute(munger.getSignature(), kind, true); + } else { + l = new ArrayList(0); //AstUtil.getAjSyntheticAttribute(); + } + + return classFile.generateMethodInfoAttribute(binding, l); + } + + protected abstract Shadow.Kind getShadowKindForBody(); +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeFieldDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeFieldDeclaration.java new file mode 100644 index 000000000..0ed6b63c9 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeFieldDeclaration.java @@ -0,0 +1,286 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.lang.reflect.Modifier; + +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.weaver.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.parser.Parser; + +/** + * returnType encodes the type of the field + * selector encodes the name + */ +public class InterTypeFieldDeclaration extends InterTypeDeclaration { + public Expression initialization; + //public InterTypeFieldBinding interBinding; + + public InterTypeFieldDeclaration(CompilationResult result, TypeReference onType) { + super(result, onType); + } + + + public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { + //we don't have a body to parse + } + + + public void resolveOnType(ClassScope classScope) { + super.resolveOnType(classScope); + if (ignoreFurtherInvestigation) return; + if (Modifier.isStatic(declaredModifiers) && onTypeBinding.isInterface()) { + scope.problemReporter().signalError(sourceStart, sourceEnd, + "static inter-type field on interface not supported"); + ignoreFurtherInvestigation = true; + } + } + + + public void resolve(ClassScope upperScope) { + if (munger == null) ignoreFurtherInvestigation = true; + if (ignoreFurtherInvestigation) return; + + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(upperScope); + ResolvedMember sig = munger.getSignature(); + TypeX aspectType = EclipseWorld.fromBinding(upperScope.referenceContext.binding); + + if (initialization == null) { + this.statements = new Statement[] { + new ReturnStatement(null, 0, 0), + }; + } else if (!onTypeBinding.isInterface()) { + + FieldBinding interField = world.makeFieldBinding( + AjcMemberMaker.interFieldClassField(sig, aspectType)); + Reference ref = new KnownFieldReference(interField, 0); + this.statements = new Statement[] { + new Assignment(ref, initialization, initialization.sourceEnd), + }; + } else { + //XXX something is broken about this logic. Can we write to static interface fields? + MethodBinding writeMethod = world.makeMethodBinding( + AjcMemberMaker.interFieldInterfaceSetter(sig, sig.getDeclaringType().resolve(world), aspectType)); + if (Modifier.isStatic(declaredModifiers)) { + this.statements = new Statement[] { + new KnownMessageSend(writeMethod, + AstUtil.makeNameReference(writeMethod.declaringClass), + new Expression[] {initialization}), + }; + } else { + this.statements = new Statement[] { + new KnownMessageSend(writeMethod, + AstUtil.makeLocalVariableReference(arguments[0].binding), + new Expression[] {initialization}), + }; + } + } + + super.resolve(upperScope); + } + + + public void setInitialization(Expression initialization) { + this.initialization = initialization; + + } + + public void build(ClassScope classScope, CrosscuttingMembers xcut) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + resolveOnType(classScope); + + binding = classScope.referenceContext.binding.resolveTypesFor(binding); + if (ignoreFurtherInvestigation) return; + + if (!Modifier.isStatic(declaredModifiers)) { + super.binding.parameters = new TypeBinding[] { + onTypeBinding, + }; + this.arguments = new Argument[] { + AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), + }; + } + + ResolvedMember sig = + new ResolvedMember(Member.FIELD, EclipseWorld.fromBinding(onTypeBinding), + declaredModifiers, EclipseWorld.fromBinding(binding.returnType), + new String(declaredSelector), TypeX.NONE); + + NewFieldTypeMunger myMunger = new NewFieldTypeMunger(sig, null); + this.munger = myMunger; + ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding); + ResolvedMember me = + myMunger.getInitMethod(aspectType); + this.selector = binding.selector = me.getName().toCharArray(); + this.binding.returnType = TypeBinding.VoidBinding; + //??? all other pieces should already match + + xcut.addTypeMunger(new EclipseTypeMunger(myMunger, aspectType, this)); + +// interBinding = new InterTypeFieldBinding(name, type, declaredModifiers, +// declaringClass, constant, withinType); + +// //XXX handle problem bindings +// TypeBinding type = returnType.getTypeBinding(classScope); +// char[] name = selector; +// super.binding.returnType = type; +// +// if (ignoreFurtherInvestigation) return; +// +// +// ReferenceBinding withinType = classScope.referenceContext.binding; +// +// this.returnType.binding = super.binding.returnType = TypeBinding.VoidBinding; +// //this.modifiers = super.binding.modifiers = AccStatic | AccPublic; +// +// TypeX aspectTypeX = EclipseWorld.fromBinding(withinType); +// TypeX onTypeX = EclipseWorld.fromBinding(declaringClass); +// +// this.selector = +// NameMangler.interFieldInitializer(aspectTypeX, onTypeX, new String(selector)).toCharArray(); +// +// super.binding.selector = this.selector; +// Constant constant = Constant.NotAConstant; +// //XXX this is not completely correct, it will miss all constants +//// if (initialization instanceof Literal) { +//// ((Literal)initialization).computeConstant(); +//// constant = initialization.constant; +//// } + + + + + + + } + + + private AjAttribute makeAttribute() { + return new AjAttribute.TypeMunger(munger); + } + + public void generateCode(ClassScope classScope, ClassFile classFile) { + if (ignoreFurtherInvestigation) return; + + classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute())); + super.generateCode(classScope, classFile); + generateDispatchMethods(classScope, classFile); +// interBinding.reader.generateMethod(this, classScope, classFile); +// interBinding.writer.generateMethod(this, classScope, classFile); + } + + private void generateDispatchMethods(ClassScope classScope, ClassFile classFile) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + ResolvedMember sig = munger.getSignature(); + TypeX aspectType = EclipseWorld.fromBinding(classScope.referenceContext.binding); + generateDispatchMethod(world, sig, aspectType, classScope, classFile, true); + generateDispatchMethod(world, sig, aspectType, classScope, classFile, false); + } + + private void generateDispatchMethod( + EclipseWorld world, + ResolvedMember sig, + TypeX aspectType, + ClassScope classScope, + ClassFile classFile, + boolean isGetter) + { + MethodBinding binding; + if (isGetter) { + binding = world.makeMethodBinding(AjcMemberMaker.interFieldGetDispatcher(sig, aspectType)); + } else { + binding = world.makeMethodBinding(AjcMemberMaker.interFieldSetDispatcher(sig, aspectType)); + } + classFile.generateMethodInfoHeader(binding); + int methodAttributeOffset = classFile.contentsOffset; + int attributeNumber = classFile.generateMethodInfoAttribute(binding, + makeEffectiveSignatureAttribute(sig, isGetter ? Shadow.FieldGet : Shadow.FieldSet, false)); + int codeAttributeOffset = classFile.contentsOffset; + classFile.generateCodeAttributeHeader(); + CodeStream codeStream = classFile.codeStream; + codeStream.reset(this, classFile); + + FieldBinding classField = world.makeFieldBinding( + AjcMemberMaker.interFieldClassField(sig, aspectType)); + + codeStream.initializeMaxLocals(binding); + if (isGetter) { + if (onTypeBinding.isInterface()) { + MethodBinding readMethod = world.makeMethodBinding( + AjcMemberMaker.interFieldInterfaceGetter( + sig, world.resolve(sig.getDeclaringType()), aspectType)); + generateInterfaceReadBody(binding, readMethod, codeStream); + } else { + generateClassReadBody(binding, classField, codeStream); + } + } else { + if (onTypeBinding.isInterface()) { + MethodBinding writeMethod = world.makeMethodBinding( + AjcMemberMaker.interFieldInterfaceSetter( + sig, world.resolve(sig.getDeclaringType()), aspectType)); + generateInterfaceWriteBody(binding, writeMethod, codeStream); + } else { + generateClassWriteBody(binding, classField, codeStream); + } + } + AstUtil.generateReturn(binding.returnType, codeStream); + + classFile.completeCodeAttribute(codeAttributeOffset); + attributeNumber++; + classFile.completeMethodInfo(methodAttributeOffset, attributeNumber); + } + + private void generateInterfaceReadBody(MethodBinding binding, MethodBinding readMethod, CodeStream codeStream) { + codeStream.aload_0(); + codeStream.invokeinterface(readMethod); + } + + + private void generateInterfaceWriteBody(MethodBinding binding, MethodBinding writeMethod, CodeStream codeStream) { + codeStream.aload_0(); + codeStream.load(writeMethod.parameters[0], 1); + codeStream.invokeinterface(writeMethod); + } + + + + private void generateClassReadBody(MethodBinding binding, FieldBinding field, CodeStream codeStream) { + if (field.isStatic()) { + codeStream.getstatic(field); + } else { + codeStream.aload_0(); + codeStream.getfield(field); + } + } + + private void generateClassWriteBody(MethodBinding binding, FieldBinding field, CodeStream codeStream) { + if (field.isStatic()) { + codeStream.load(field.type, 0); + codeStream.putstatic(field); + } else { + codeStream.aload_0(); + codeStream.load(field.type, 1); + codeStream.putfield(field); + } + } + + protected Shadow.Kind getShadowKindForBody() { + return null; + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java new file mode 100644 index 000000000..8190809ea --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java @@ -0,0 +1,175 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.lang.reflect.Modifier; + +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.weaver.*; +import org.aspectj.weaver.Shadow.Kind; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.flow.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.parser.Parser; + + +public class InterTypeMethodDeclaration extends InterTypeDeclaration { + public InterTypeMethodDeclaration(CompilationResult result, TypeReference onType) { + super(result, onType); + } + + public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { + if (ignoreFurtherInvestigation) + return; + if (!Modifier.isAbstract(declaredModifiers)) { + parser.parse(this, unit); + } + } + + + public void analyseCode( + ClassScope currentScope, + FlowContext flowContext, + FlowInfo flowInfo) + { + if (Modifier.isAbstract(declaredModifiers)) return; + + super.analyseCode(currentScope, flowContext, flowInfo); + } + + public void resolve(ClassScope upperScope) { + if (munger == null) ignoreFurtherInvestigation = true; + if (ignoreFurtherInvestigation) return; + + if (!Modifier.isStatic(declaredModifiers)) { + this.arguments = AstUtil.insert( + AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), + this.arguments); + binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters); + } + + super.resolve(upperScope); + } + public void resolveStatements(ClassScope upperScope) { + if (!Modifier.isAbstract(declaredModifiers)) super.resolveStatements(upperScope); + } + + + + public void build(ClassScope classScope, CrosscuttingMembers xcut) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + + resolveOnType(classScope); + if (ignoreFurtherInvestigation) return; + + binding = classScope.referenceContext.binding.resolveTypesFor(binding); + ResolvedMember sig = new ResolvedMember(Member.METHOD, EclipseWorld.fromBinding(onTypeBinding), + declaredModifiers, EclipseWorld.fromBinding(binding.returnType), new String(declaredSelector), + EclipseWorld.fromBindings(binding.parameters)); + + NewMethodTypeMunger myMunger = new NewMethodTypeMunger(sig, null); + this.munger = myMunger; + ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding); + ResolvedMember me = + myMunger.getDispatchMethod(aspectType); + this.selector = binding.selector = me.getName().toCharArray(); + + xcut.addTypeMunger(new EclipseTypeMunger(myMunger, aspectType, this)); + } + + + private AjAttribute makeAttribute() { + return new AjAttribute.TypeMunger(munger); + } + + + public void generateCode(ClassScope classScope, ClassFile classFile) { + if (ignoreFurtherInvestigation) { + System.err.println("no code for " + this); + return; + } + + classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute())); + + if (!Modifier.isAbstract(declaredModifiers)) { + super.generateCode(classScope, classFile); + } + + generateDispatchMethod(classScope, classFile); + } + + public void generateDispatchMethod(ClassScope classScope, ClassFile classFile) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + + TypeX aspectType = EclipseWorld.fromBinding(classScope.referenceContext.binding); + ResolvedMember signature = munger.getSignature(); + + ResolvedMember dispatchMember = + AjcMemberMaker.interMethodDispatcher(signature, aspectType); + MethodBinding dispatchBinding = world.makeMethodBinding(dispatchMember); + MethodBinding introducedMethod = + world.makeMethodBinding(AjcMemberMaker.interMethod(signature, aspectType, onTypeBinding.isInterface())); + + classFile.generateMethodInfoHeader(dispatchBinding); + int methodAttributeOffset = classFile.contentsOffset; + int attributeNumber = classFile.generateMethodInfoAttribute(dispatchBinding, + makeEffectiveSignatureAttribute(signature, Shadow.MethodCall, false)); + int codeAttributeOffset = classFile.contentsOffset; + classFile.generateCodeAttributeHeader(); + CodeStream codeStream = classFile.codeStream; + codeStream.reset(this, classFile); + + codeStream.initializeMaxLocals(dispatchBinding); + + MethodBinding methodBinding = introducedMethod; + TypeBinding[] parameters = methodBinding.parameters; + int length = parameters.length; + int resolvedPosition; + if (methodBinding.isStatic()) + resolvedPosition = 0; + else { + codeStream.aload_0(); + resolvedPosition = 1; + } + for (int i = 0; i < length; i++) { + codeStream.load(parameters[i], resolvedPosition); + if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding)) + resolvedPosition += 2; + else + resolvedPosition++; + } + TypeBinding type; + if (methodBinding.isStatic()) + codeStream.invokestatic(methodBinding); + else { + if (methodBinding.declaringClass.isInterface()){ + codeStream.invokeinterface(methodBinding); + } else { + codeStream.invokevirtual(methodBinding); + } + } + AstUtil.generateReturn(dispatchBinding.returnType, codeStream); + + classFile.completeCodeAttribute(codeAttributeOffset); + attributeNumber++; + classFile.completeMethodInfo(methodAttributeOffset, attributeNumber); + } + + + protected Shadow.Kind getShadowKindForBody() { + return Shadow.MethodExecution; + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/KnownFieldReference.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/KnownFieldReference.java new file mode 100644 index 000000000..d2caddc25 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/KnownFieldReference.java @@ -0,0 +1,39 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.FieldReference; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class KnownFieldReference extends QualifiedNameReference { + + //XXX handle source locations + public KnownFieldReference(FieldBinding binding, long pos) { + super(new char[][] {binding.name}, 0, 0); + this.binding = this.codegenBinding = binding; + this.constant = Constant.NotAConstant; + this.receiverType = this.actualReceiverType = + binding.declaringClass; + + this.bits = FIELD; + //this.receiver = AstUtil.makeTypeReference(binding.declaringClass); + } + + public TypeBinding resolveType(BlockScope scope) { + return fieldBinding().type; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/KnownMessageSend.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/KnownMessageSend.java new file mode 100644 index 000000000..45eaa8c38 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/KnownMessageSend.java @@ -0,0 +1,57 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.util.Arrays; + +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.MessageSend; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; + +public class KnownMessageSend extends MessageSend { + + public KnownMessageSend(MethodBinding binding, Expression receiver, Expression[] arguments) { + super(); + this.binding = this.codegenBinding = binding; + this.arguments = arguments; + this.receiver = receiver; + this.selector = binding.selector; + constant = NotAConstant; + } + + public void manageSyntheticAccessIfNecessary(BlockScope currentScope) { + return; + } + + protected void resolveMethodBinding( + BlockScope scope, + TypeBinding[] argumentTypes) { + // we've already resolved this + } + + public String toStringExpression() { + return "KnownMessageSend"; + } + + public void generateCode( + BlockScope currentScope, + CodeStream codeStream, + boolean valueRequired) { + //System.out.println("about to generate: " +this + " args: " + Arrays.asList(arguments)); + super.generateCode(currentScope, codeStream, valueRequired); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java new file mode 100644 index 000000000..294258eca --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java @@ -0,0 +1,171 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.io.*; +import java.io.IOException; + +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.weaver.*; +import org.aspectj.weaver.ResolvedPointcutDefinition; +import org.aspectj.weaver.patterns.Pointcut; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; +import org.eclipse.jdt.internal.compiler.parser.Parser; + + +public class PointcutDeclaration extends MethodDeclaration implements IAjDeclaration { + public PointcutDesignator pointcutDesignator; + + public PointcutDeclaration(CompilationResult compilationResult) { + super(compilationResult); + this.returnType = TypeReference.baseTypeReference(T_void, 0); + } + +// public PointcutDeclaration(MethodDeclaration decl, Parser parser) { +// this(decl.compilationResult); +// this.sourceEnd = decl.sourceEnd; +// this.sourceStart = decl.sourceStart; +// +// this.arguments = decl.arguments; +// if (this.arguments == null) this.arguments = new Argument[0]; +// this.modifiers = decl.modifiers; +//// if ((modifiers & AccAbstract) == 0) { +//// modifiers |= AccNative; +//// } +//// modifiers |= AccSemicolonBody; //XXX hack to make me have no body +// +// this.modifiersSourceStart = decl.modifiersSourceStart; +// this.selector = decl.selector; +// if (decl.thrownExceptions != null && decl.thrownExceptions.length > 0) { +// //XXX need a better problem to report +// TypeReference e1 = decl.thrownExceptions[0]; +// parser.problemReporter().parseError(e1.sourceStart, e1.sourceEnd, +// new char[0], "throws", new String[] {":"}); +// } +// } + + private Pointcut getPointcut() { + if (pointcutDesignator == null) { + return Pointcut.makeMatchesNothing(Pointcut.RESOLVED); + } else { + return pointcutDesignator.getPointcut(); + } + } + + + public ResolvedPointcutDefinition makeResolvedPointcutDefinition() { + //System.out.println("pc: " + getPointcut()); + return new ResolvedPointcutDefinition( + EclipseWorld.fromBinding(this.binding.declaringClass), + this.modifiers, // & ~AccNative, + new String(selector), + EclipseWorld.fromBindings(this.binding.parameters), + getPointcut()); + } + + + public AjAttribute makeAttribute() { + return new AjAttribute.PointcutDeclarationAttribute(makeResolvedPointcutDefinition()); +// return new Attribute() { +// public char[] getAttributeName() { return ResolvedPointcutDefinition.AttributeName.toCharArray(); } +// public void writeTo(DataOutputStream s) throws IOException { +// makeResolvedPointcut().writeAttribute(s); +// } +// }; + } + + /** + * A pointcut declaration exists in a classfile only as an attibute on the + * class. Unlike advice and inter-type declarations, it has no corresponding + * method. + */ + public void generateCode(ClassScope classScope, ClassFile classFile) { + if (ignoreFurtherInvestigation) return ; + classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute())); + return; + } + + + +// public boolean finishResolveTypes(SourceTypeBinding sourceTypeBinding) { +// if (!super.finishResolveTypes(sourceTypeBinding)) return false; +// if (pointcutDesignator != null) { +// return pointcutDesignator.finishResolveTypes(this, this.binding, arguments.length, sourceTypeBinding); +// } else { +// return true; +// } +// } + + public String toString(int tab) { + StringBuffer buf = new StringBuffer(); + buf.append(tabString(tab)); + if (modifiers != 0) { + buf.append(modifiersString(modifiers)); + } + +// if (modifiers != AccNative) { +// buf.append(modifiersString(modifiers & ~AccNative)); +// } + + buf.append("pointcut "); + buf.append(new String(selector)); + buf.append("("); + if (arguments != null) { + for (int i = 0; i < arguments.length; i++) { + if (i > 0) buf.append(", "); + buf.append(arguments[i].toString(0)); + }; + }; + buf.append("): "); + + buf.append(getPointcut()); + + buf.append(";"); + return buf.toString(); + } + + public void parseStatements( + Parser parser, + CompilationUnitDeclaration unit) { + if (pointcutDesignator == null) { + //XXXthrow new RuntimeException("unimplemented"); + } else { + // do nothing + } + } + + public void postParse(TypeDeclaration typeDec) { + if (arguments == null) arguments = new Argument[0]; + if (pointcutDesignator == null) return; //XXX + pointcutDesignator.postParse(typeDec, this); + } + + public void resolveStatements(ClassScope upperScope) { + if (isAbstract()) this.modifiers |= AccSemicolonBody; + + if (binding == null || ignoreFurtherInvestigation) return; + + if (pointcutDesignator != null) { + pointcutDesignator.finishResolveTypes(this, this.binding, arguments.length, + upperScope.referenceContext.binding); + } + + + super.resolveStatements(upperScope); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java new file mode 100644 index 000000000..bcb0fe1ea --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java @@ -0,0 +1,88 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.io.*; +import java.util.List; + +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.weaver.*; +import org.aspectj.weaver.patterns.*; +import org.aspectj.weaver.patterns.FormalBinding; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.parser.Parser; + +public class PointcutDesignator extends AstNode { + private Pointcut pointcut; + private PseudoTokens tokens; //XXX redundant + private boolean isError = false; + + public PointcutDesignator(Parser parser, PseudoTokens tokens) { + super(); + sourceStart = tokens.sourceStart; + sourceEnd = tokens.sourceEnd; + this.tokens = tokens; + + Pointcut pc = tokens.parsePointcut(parser); + if (pc.toString().equals("")) { //??? is this a good signal + isError = true; + } + pointcut = pc; + } + + public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { + tokens.postParse(typeDec, enclosingDec); + } + + + + public String toString(int tab) { + if (pointcut == null) return "<pcd>"; + return pointcut.toString(); + } + + public boolean finishResolveTypes(final AbstractMethodDeclaration dec, MethodBinding method, final int baseArgumentCount, SourceTypeBinding sourceTypeBinding) { + //System.err.println("resolving: " + this); + //Thread.currentThread().dumpStack(); + //XXX why do we need this test + if (pointcut.state == Pointcut.RESOLVED) return true; + + TypeBinding[] parameters = method.parameters; + Argument[] arguments = dec.arguments; + + FormalBinding[] bindings = new FormalBinding[baseArgumentCount]; + for (int i = 0, len = baseArgumentCount; i < len; i++) { + Argument arg = arguments[i]; + String name = new String(arg.name); + TypeX type = EclipseWorld.fromBinding(parameters[i]); + bindings[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd, "unknown"); + } + + EclipseScope scope = new EclipseScope(bindings, dec.scope); + + pointcut = pointcut.resolve(scope); + return true; + } + + public Pointcut getPointcut() { + return pointcut; + } + + public boolean isError() { + return isError; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/Proceed.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/Proceed.java new file mode 100644 index 000000000..541184931 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/Proceed.java @@ -0,0 +1,123 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.weaver.AdviceKind; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.MessageSend; +import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; + + +public class Proceed extends MessageSend { + public Proceed(MessageSend parent) { + super(); + + this.receiver = parent.receiver; + this.selector = parent.selector; + this.arguments = parent.arguments; + this.binding = parent.binding; + this.codegenBinding = parent.codegenBinding; + + this.nameSourcePosition = parent.nameSourcePosition; + this.receiverType = parent.receiverType; + this.qualifyingType = qualifyingType; + + this.sourceStart = parent.sourceStart; + this.sourceEnd = parent.sourceEnd; + } + + public TypeBinding resolveType(BlockScope scope) { + // find out if I'm really in an around body or not + //??? there is a small performance issue here + AdviceDeclaration aroundDecl = findEnclosingAround(scope); + + if (aroundDecl == null) { + return super.resolveType(scope); + } + + + + constant = NotAConstant; + binding = codegenBinding = aroundDecl.proceedMethodBinding; + + this.qualifyingType = this.receiverType = binding.declaringClass; + + int baseArgCount = 0; + if (arguments != null) { + baseArgCount = arguments.length; + Expression[] newArguments = new Expression[baseArgCount + 1]; + System.arraycopy(arguments, 0, newArguments, 0, baseArgCount); + arguments = newArguments; + } else { + arguments = new Expression[1]; + } + + arguments[baseArgCount] = AstUtil.makeLocalVariableReference(aroundDecl.extraArgument.binding); + + int declaredParameterCount = aroundDecl.getDeclaredParameterCount(); + if (baseArgCount < declaredParameterCount) { + scope.problemReporter().signalError(this.sourceStart, this.sourceEnd, + "too few arguments to proceed, expected " + declaredParameterCount); + aroundDecl.ignoreFurtherInvestigation = true; + return null; //binding.returnType; + } + + if (baseArgCount > declaredParameterCount) { + scope.problemReporter().signalError(this.sourceStart, this.sourceEnd, + "too many arguments to proceed, expected " + declaredParameterCount); + aroundDecl.ignoreFurtherInvestigation = true; + return null; //binding.returnType; + } + + + for (int i=0, len=arguments.length; i < len; i++) { + Expression arg = arguments[i]; + TypeBinding argType = arg.resolveType(scope); + if (argType != null) { + TypeBinding paramType = binding.parameters[i]; + if (!scope.areTypesCompatible(argType, paramType)) { + scope.problemReporter().typeMismatchError(argType, paramType, arg); + } + arg.implicitWidening(binding.parameters[i], argType); + } + } + + + return binding.returnType; + } + + private AdviceDeclaration findEnclosingAround(Scope scope) { + if (scope == null) return null; + + if (scope instanceof MethodScope) { + MethodScope methodScope = (MethodScope)scope; + ReferenceContext context = methodScope.referenceContext; + if (context instanceof AdviceDeclaration) { + AdviceDeclaration adviceDecl = (AdviceDeclaration)context; + if (adviceDecl.kind == AdviceKind.Around) { + return adviceDecl; + } else { + return null; + } + } + } + + return findEnclosingAround(scope.parent); + } + + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoToken.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoToken.java new file mode 100644 index 000000000..6414c8879 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoToken.java @@ -0,0 +1,85 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.weaver.patterns.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.AstNode; +import org.eclipse.jdt.internal.compiler.parser.Parser; + +/** + */ +public class PseudoToken extends AstNode implements IToken { + public String value; + public boolean isIdentifier; + public String literalKind = null; + public Parser parser; + /** + * Constructor for PointcutDesignatorToken. + */ + public PseudoToken(Parser parser, String value, boolean isIdentifier) { + this.parser = parser; + this.value = value; + this.isIdentifier = isIdentifier; + } + + public String toString(int tab) { + return "<" + value + "@" + getStart() + ":" + getEnd() + ">"; + } + /** + * @see org.aspectj.weaver.patterns.IToken#getString() + */ + public String getString() { + return value; + } + + /** + * @see org.aspectj.weaver.patterns.IToken#isIdentifier() + */ + public boolean isIdentifier() { + return isIdentifier; + } + + /** + * returns null if this isn't a literal + */ + public String getLiteralKind() { + return literalKind; + } + + public Pointcut maybeGetParsedPointcut() { + return null; + } + + + public int getStart() { + return sourceStart; + } + + /** + * + */ + public int getEnd() { + return sourceEnd; + } + + public String getFileName() { + return "unknown"; + } + + public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { + // nothing to do typically + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoTokens.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoTokens.java new file mode 100644 index 000000000..be578dfe5 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoTokens.java @@ -0,0 +1,147 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.io.*; +import java.util.*; + + +import org.aspectj.weaver.*; +import org.aspectj.weaver.patterns.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.AstNode; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.parser.Parser; +import org.eclipse.jdt.internal.compiler.problem.*; + + +public class PseudoTokens extends AstNode { + BasicTokenSource tokenSource; + PseudoToken[] tokens; //XXX this is redundant with the field above + String endToken; + + + public PseudoTokens(PseudoToken[] tokens, ISourceContext sourceContext) { + super(); + this.tokens = tokens; + this.tokenSource = new BasicTokenSource(tokens, sourceContext); + endToken = tokens[tokens.length-1].getString(); + sourceStart = tokens[0].sourceStart; + sourceEnd = tokens[tokens.length-2].sourceEnd; + } + + public Pointcut parsePointcut(Parser parser) { + PatternParser patternParser = new PatternParser(tokenSource); + try { + Pointcut ret = patternParser.parsePointcut(); + checkEof(parser); + return ret; + } catch (ParserException pe) { + reportError(parser, pe); + return Pointcut.makeMatchesNothing(Pointcut.SYMBOLIC); + } + } + + private void checkEof(Parser parser) { + IToken last = tokenSource.next(); + if (tokenSource.next() != IToken.EOF) { + parser.problemReporter().parseError(last.getStart(), last.getEnd(), + last.getString().toCharArray(), + last.getString(), + new String[] {endToken}); + } + } + + + private void reportError(Parser parser, ParserException pe) { + IHasPosition tok = pe.getLocation(); + int start, end; + if (tok == IToken.EOF) { + start = sourceEnd+1; + end = sourceEnd+1; + } else { + start = tok.getStart(); + end = tok.getEnd(); + } + String found = "<unknown>"; + if (tok instanceof IToken) { + found = ((IToken)tok).getString(); + } + + parser.problemReporter().parseError(start, end, + found.toCharArray(), + found, + new String[] {pe.getMessage()}); + } + + + public TypePattern maybeParseDominatesPattern(Parser parser) { + PatternParser patternParser = new PatternParser(tokenSource); + try { + if (patternParser.maybeEatIdentifier("dominates")) { + // there is no eof check here + return patternParser.parseTypePattern(); + } else { + return null; + } + } catch (ParserException pe) { + reportError(parser, pe); + return null; + } + } + + + public PerClause parsePerClause(Parser parser) { + PatternParser patternParser = new PatternParser(tokenSource); + try { + PerClause ret = patternParser.maybeParsePerClause(); + checkEof(parser); + if (ret == null) return new PerSingleton(); + else return ret; + } catch (ParserException pe) { + reportError(parser, pe); + return new PerSingleton(); + } + + } + + +// public TypePattern parseTypePattern(Parser parser) { +// } +// + public Declare parseDeclare(Parser parser) { + PatternParser patternParser = new PatternParser(tokenSource); + try { + Declare ret = patternParser.parseDeclare(); + checkEof(parser); + return ret; + } catch (ParserException pe) { + reportError(parser, pe); + return null; + } + } + + + public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { + for (int i=0, len=tokens.length; i < len; i++) { + tokens[i].postParse(typeDec, enclosingDec); + } + } + + + public String toString(int tab) { + return tokenSource.toString(); + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/SuperFixerVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/SuperFixerVisitor.java new file mode 100644 index 000000000..c1747778a --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/SuperFixerVisitor.java @@ -0,0 +1,68 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.util.*; +import java.util.Arrays; + +import org.aspectj.weaver.*; +import org.aspectj.weaver.ShadowMunger; +import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; + +/** + * Takes a method that already has the three extra parameters + * thisJoinPointStaticPart, thisJoinPoint and thisEnclosingJoinPointStaticPart + */ + +public class SuperFixerVisitor extends AbstractSyntaxTreeVisitorAdapter { + Set superMethodsCalled = new HashSet(); + AbstractMethodDeclaration method; + ReferenceBinding targetClass; + + SuperFixerVisitor(AbstractMethodDeclaration method, ReferenceBinding targetClass) { + this.method = method; + this.targetClass = targetClass; + } + + + //XXX does this walk into inners + public void endVisit(MessageSend call, BlockScope scope) { + //System.out.println("endVisit: " + call); + // an error has already occurred + if (call.codegenBinding == null) return; + + if (!call.isSuperAccess() || call.binding.isStatic()) return; + + call.receiver = new ThisReference(); + + MethodBinding superBinding = call.codegenBinding; + + char[] accessName = AstUtil.makeAjcMangledName( + ResolvedTypeMunger.SUPER_DISPATCH_NAME.toCharArray(), targetClass, superBinding.selector + ); + + //??? do we want these to be unique + MethodBinding superAccessBinding = + new MethodBinding(AstNode.AccPublic, accessName, + superBinding.returnType, superBinding.parameters, superBinding.thrownExceptions, + targetClass); + + call.codegenBinding = superAccessBinding; + + superMethodsCalled.add(superBinding); + + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ThisJoinPointVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ThisJoinPointVisitor.java new file mode 100644 index 000000000..989d9123d --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ThisJoinPointVisitor.java @@ -0,0 +1,224 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.ast; + +import java.util.Arrays; + +import org.aspectj.weaver.*; +import org.aspectj.weaver.ShadowMunger; +import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.lookup.*; + +/** + * Takes a method that already has the three extra parameters + * thisJoinPointStaticPart, thisJoinPoint and thisEnclosingJoinPointStaticPart + */ + +public class ThisJoinPointVisitor extends AbstractSyntaxTreeVisitorAdapter { + boolean needsDynamic = false; + boolean needsStatic = false; + boolean needsStaticEnclosing = false; + boolean hasEffectivelyStaticRef = false; + + LocalVariableBinding thisJoinPointDec; + LocalVariableBinding thisJoinPointStaticPartDec; + LocalVariableBinding thisEnclosingJoinPointStaticPartDec; + + LocalVariableBinding thisJoinPointDecLocal; + LocalVariableBinding thisJoinPointStaticPartDecLocal; + LocalVariableBinding thisEnclosingJoinPointStaticPartDecLocal; + + boolean replaceEffectivelyStaticRefs = false; + + AbstractMethodDeclaration method; + + ThisJoinPointVisitor(AbstractMethodDeclaration method) { + this.method = method; + int index = method.arguments.length - 3; + + thisJoinPointStaticPartDecLocal = method.scope.locals[index]; + thisJoinPointStaticPartDec = method.arguments[index++].binding; + thisJoinPointDecLocal = method.scope.locals[index]; + thisJoinPointDec = method.arguments[index++].binding; + thisEnclosingJoinPointStaticPartDecLocal = method.scope.locals[index]; + thisEnclosingJoinPointStaticPartDec = method.arguments[index++].binding; + } + + public void computeJoinPointParams() { + // walk my body to see what is needed + method.traverse(this, (ClassScope) null); + + //??? add support for option to disable this optimization + //System.err.println("check: "+ hasEffectivelyStaticRef + ", " + needsDynamic); + if (hasEffectivelyStaticRef && !needsDynamic) { + // replace effectively static refs with thisJoinPointStaticPart + replaceEffectivelyStaticRefs = true; + needsStatic = true; + method.traverse(this, (ClassScope) null); + } + } + + boolean isRef(NameReference ref, Binding binding) { + return ref.binding == binding; + } + + boolean isRef(Expression expr, Binding binding) { + //System.err.println("isRef: " + expr + ", " + binding); + return expr != null + && expr instanceof NameReference + && isRef((NameReference) expr, binding); + } + + public void endVisit(SingleNameReference ref, BlockScope scope) { + if (isRef(ref, thisJoinPointDec)) + needsDynamic = true; + else if (isRef(ref, thisJoinPointStaticPartDec)) + needsStatic = true; + else if (isRef(ref, thisEnclosingJoinPointStaticPartDec)) + needsStaticEnclosing = true; + } + + // public void checkAndFix(ASTObject body) { + // this.process(body); + // if (needsFakeStatic && !needsDynamic) { + // if (!this.getCompiler().getOptions().noMetaJoinPointOptimization) { + // makeFakeStatics = true; + // needsStatic = true; + // this.process(body); + // } else { + // needsDynamic = true; + // } + // } + // } + + boolean canTreatAsStatic(String id) { + return id.equals("toString") + || id.equals("toShortString") + || id.equals("toLongString") + || id.equals("getKind") + || id.equals("getSignature") + || id.equals("getSourceLocation") + || id.equals("getStaticPart"); + } + + // boolean canTreatAsStatic(VarExpr varExpr) { + // ASTObject parent = varExpr.getParent(); + // if (parent instanceof CallExpr) { + // Method calledMethod = ((CallExpr)parent).getMethod(); + // return canTreatAsStatic(calledMethod); + // + // //??? should add a case here to catch + // //??? tjp.getEnclosingExecutionJoinPoint().STATIC_METHOD() + // } else if (parent instanceof BinopExpr) { + // BinopExpr binop = (BinopExpr)parent; + // if (binop.getType().isEquivalent(this.getTypeManager().getStringType())) { + // return true; + // } else { + // return false; + // } + // } else { + // return false; + // } + // } + + boolean inBlockThatCantRun = false; + + public boolean visit(MessageSend call, BlockScope scope) { + Expression receiver = call.receiver; + if (isRef(receiver, thisJoinPointDec)) { + if (canTreatAsStatic(new String(call.selector))) { + if (replaceEffectivelyStaticRefs) { + replaceEffectivelyStaticRef(call); + } else { + //System.err.println("has static reg"); + hasEffectivelyStaticRef = true; + if (call.arguments != null) { + int argumentsLength = call.arguments.length; + for (int i = 0; i < argumentsLength; i++) + call.arguments[i].traverse(this, scope); + } + return false; + } + } + } + + return super.visit(call, scope); + } + + private void replaceEffectivelyStaticRef(MessageSend call) { + //System.err.println("replace static ref"); + NameReference receiver = (NameReference) call.receiver; + receiver.binding = thisJoinPointStaticPartDecLocal; //thisJoinPointStaticPartDec; + receiver.codegenBinding = thisJoinPointStaticPartDecLocal; + + call.binding.declaringClass = + (ReferenceBinding) thisJoinPointStaticPartDec.type; + } + + public int removeUnusedExtraArguments() { + int extraArgumentFlags = 0; + + this.computeJoinPointParams(); + MethodBinding binding = method.binding; + + + int index = binding.parameters.length - 3; + if (needsStaticEnclosing) { + extraArgumentFlags |= Advice.ThisEnclosingJoinPointStaticPart; + } else { + removeParameter(index+2); + } + + if (needsDynamic) { + extraArgumentFlags |= Advice.ThisJoinPoint; + } else { + removeParameter(index+1); + } + + if (needsStatic) { + extraArgumentFlags |= Advice.ThisJoinPointStaticPart; + } else { + removeParameter(index+0); + } + + return extraArgumentFlags; + } + + private void removeParameter(int indexToRemove) { + TypeBinding[] parameters = method.binding.parameters; + method.scope.locals = removeLocalBinding(indexToRemove, method.scope.locals); + method.binding.parameters = removeParameter(indexToRemove, method.binding.parameters); + } + + + private static TypeBinding[] removeParameter(int index, TypeBinding[] bindings) { + int len = bindings.length; + TypeBinding[] ret = new TypeBinding[len-1]; + System.arraycopy(bindings, 0, ret, 0, index); + System.arraycopy(bindings, index+1, ret, index, len-index-1); + return ret; + } + + private static LocalVariableBinding[] removeLocalBinding(int index, LocalVariableBinding[] bindings) { + int len = bindings.length; + //??? for performance we should do this in-place + LocalVariableBinding[] ret = new LocalVariableBinding[len-1]; + System.arraycopy(bindings, 0, ret, 0, index); + System.arraycopy(bindings, index+1, ret, index, len-index-1); + return ret; + } + + +} 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 new file mode 100644 index 000000000..e09f859fc --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -0,0 +1,201 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.ast.*; +import org.aspectj.bridge.MessageUtil; +import org.aspectj.weaver.*; +import org.aspectj.weaver.patterns.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.impl.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; + +public class AjLookupEnvironment extends LookupEnvironment { + public EclipseWorld world = null; + + public AjLookupEnvironment( + ITypeRequestor typeRequestor, + CompilerOptions options, + ProblemReporter problemReporter, + INameEnvironment nameEnvironment) { + super(typeRequestor, options, problemReporter, nameEnvironment); + } + + //XXX figure out if we can do this through super or not + //XXX otherwise duplicates some of super's code + public void completeTypeBindings() { + stepCompleted = BUILD_TYPE_HIERARCHY; + + for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + units[i].scope.checkAndSetImports(); + } + stepCompleted = CHECK_AND_SET_IMPORTS; + + for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + units[i].scope.connectTypeHierarchy(); + } + stepCompleted = CONNECT_TYPE_HIERARCHY; + + // collect inter-type declarations as well + for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + units[i].scope.buildFieldsAndMethods(); + } + + // need to build inter-type declarations for all AspectDeclarations at this point + for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + SourceTypeBinding[] b = units[i].scope.topLevelTypes; + for (int j = 0; j < b.length; j++) { + buildInterTypeAndPerClause(b[j].scope); + } + } + //??? do we need a new stepCompleted + + // now do weaving + Collection typeMungers = world.getTypeMungers(); + Collection declareParents = world.getDeclareParents(); + for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + weaveInterTypeDeclarations(units[i].scope, typeMungers, declareParents); + units[i] = null; // release unnecessary reference to the parsed unit + } + + stepCompleted = BUILD_FIELDS_AND_METHODS; + lastCompletedUnitIndex = lastUnitIndex; + } + + private void buildInterTypeAndPerClause(ClassScope s) { + TypeDeclaration dec = s.referenceContext; + if (dec instanceof AspectDeclaration) { + ((AspectDeclaration)dec).buildInterTypeAndPerClause(s); + } + + SourceTypeBinding sourceType = s.referenceContext.binding; + + ReferenceBinding[] memberTypes = sourceType.memberTypes; + for (int i = 0, length = memberTypes.length; i < length; i++) { + buildInterTypeAndPerClause(((SourceTypeBinding) memberTypes[i]).scope); + } + } + + + private void weaveInterTypeDeclarations(CompilationUnitScope unit, Collection typeMungers, Collection declareParents) { + for (int i = 0, length = unit.topLevelTypes.length; i < length; i++) + weaveInterTypeDeclarations(unit.topLevelTypes[i].scope, typeMungers, declareParents); + + //System.err.println("done with inter types"); + } + + private void weaveInterTypeDeclarations(ClassScope scope, Collection typeMungers, Collection declareParents) { + //System.err.println("weaving: " + scope); + SourceTypeBinding sourceType = scope.referenceContext.binding; + ResolvedTypeX onType = world.fromEclipse(sourceType); + for (Iterator i = declareParents.iterator(); i.hasNext();) { + doDeclareParents((DeclareParents)i.next(), scope); + } + + for (Iterator i = typeMungers.iterator(); i.hasNext();) { + EclipseTypeMunger munger = (EclipseTypeMunger) i.next(); + //System.out.println("weaving: " + munger); + //if (munger.match(scope)) + if (munger.matches(onType)) { + onType.addInterTypeMunger(munger); + } + } + + for (Iterator i = onType.getInterTypeMungers().iterator(); i.hasNext();) { + EclipseTypeMunger munger = (EclipseTypeMunger) i.next(); + munger.munge(scope); + } + + + + ReferenceBinding[] memberTypes = sourceType.memberTypes; + for (int i = 0, length = memberTypes.length; i < length; i++) { + weaveInterTypeDeclarations(((SourceTypeBinding) memberTypes[i]).scope, typeMungers, declareParents); + } + } + + private void doDeclareParents(DeclareParents declareParents, ClassScope scope) { + if (declareParents.match(world.fromEclipse(scope.referenceContext.binding))) { + TypePatternList l = declareParents.getParents(); + for (int i=0, len=l.size(); i < len; i++) { + addParent(declareParents, scope, l.get(i)); + } + } + } + + private void addParent(DeclareParents declareParents, ClassScope scope, TypePattern typePattern) { + SourceTypeBinding sourceType = scope.referenceContext.binding; + if (!typePattern.assertExactType(world.getMessageHandler())) return; + TypeX iType = typePattern.getExactType(); +// if (iType == null) { +// throw new RuntimeException("yikes: " + typePattern); +// } + //if (iType == ResolvedTypeX.MISSING || iType == null) return; + ReferenceBinding b = (ReferenceBinding)world.makeTypeBinding(iType); //" + + if (b.isClass()) { + if (sourceType.isInterface()) { + world.getMessageHandler().handleMessage(MessageUtil.error( + "interface can not extend a class", declareParents.getSourceLocation() + )); + // how to handle xcutting errors??? + } + + if (sourceType == b || sourceType.isSuperclassOf(b)) { + world.getMessageHandler().handleMessage(MessageUtil.error( + "class can not extend itself", declareParents.getSourceLocation() + )); + return; + } + sourceType.superclass = b; + } else { + //??? it's not considered an error to extend yourself, nothing happens + if (sourceType.equals(b)) { + return; + } + + if (sourceType.isInterface() && b.implementsInterface(sourceType, true)) { + world.getMessageHandler().handleMessage(MessageUtil.error( + "interface can not extend itself", declareParents.getSourceLocation() + )); + return; + } + if (sourceType == b || b.isSuperclassOf(sourceType)) return; + ReferenceBinding[] oldI = sourceType.superInterfaces; + ReferenceBinding[] newI; + if (oldI == null) { + newI = new ReferenceBinding[1]; + newI[0] = b; + } else { + int n = oldI.length; + newI = new ReferenceBinding[n+1]; + System.arraycopy(oldI, 0, newI, 0, n); + newI[n] = b; + } + sourceType.superInterfaces = newI; + } + + } + + private TypeReference makeReference(ExactTypePattern e) { + return new SingleTypeReference(e.getType().getName().toCharArray(), + AstUtil.makeLongPos(e.getStart(), e.getEnd())); + } + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjTypeConstants.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjTypeConstants.java new file mode 100644 index 000000000..fdb53c2a2 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjTypeConstants.java @@ -0,0 +1,68 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.Scope; + +public class AjTypeConstants { + + public static final char[] ORG = "org".toCharArray(); + public static final char[] ASPECTJ = "aspectj".toCharArray(); + public static final char[] RUNTIME = "runtime".toCharArray(); + public static final char[] LANG = "lang".toCharArray(); + public static final char[] INTERNAL = "internal".toCharArray(); + + // Constant compound names + public static final char[][] ORG_ASPECTJ_LANG_JOINPOINT = + new char[][] {ORG, ASPECTJ, LANG, "JoinPoint".toCharArray()}; + + public static final char[][] ORG_ASPECTJ_LANG_JOINPOINT_STATICPART = + new char[][] {ORG, ASPECTJ, LANG, "JoinPoint".toCharArray(), "StaticPart".toCharArray()}; + + public static final char[][] ORG_ASPECTJ_RUNTIME_INTERNAL_AROUNDCLOSURE = + new char[][] {ORG, ASPECTJ, RUNTIME, INTERNAL, "AroundClosure".toCharArray()}; + + public static final char[][] ORG_ASPECTJ_RUNTIME_INTERNAL_CONVERSIONS = + new char[][] {ORG, ASPECTJ, RUNTIME, INTERNAL, "Conversions".toCharArray()}; + + public static TypeReference getJoinPointType() { + return new QualifiedTypeReference(ORG_ASPECTJ_LANG_JOINPOINT, new long[10]); + } + + public static TypeReference getJoinPointStaticPartType() { + return new QualifiedTypeReference(ORG_ASPECTJ_LANG_JOINPOINT_STATICPART, new long[10]); + } + + public static TypeReference getAroundClosureType() { + return new QualifiedTypeReference(ORG_ASPECTJ_RUNTIME_INTERNAL_AROUNDCLOSURE, new long[10]); + } + + public static ReferenceBinding getConversionsType(Scope scope) { + return (ReferenceBinding)scope.getType(ORG_ASPECTJ_RUNTIME_INTERNAL_CONVERSIONS); + } + + public static MethodBinding getConversionMethodToObject(Scope scope, TypeBinding fromType) { + String name = new String(fromType.sourceName()) + "Object"; + return getConversionsType(scope).getMethods(name.toCharArray())[0]; + } + + public static MethodBinding getConversionMethodFromObject(Scope scope, TypeBinding toType) { + String name = new String(toType.sourceName()) + "Value"; + return getConversionsType(scope).getMethods(name.toCharArray())[0]; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseAdvice.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseAdvice.java new file mode 100644 index 000000000..41cab4c62 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseAdvice.java @@ -0,0 +1,46 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import org.aspectj.weaver.*; +import org.aspectj.weaver.Advice; +import org.aspectj.weaver.patterns.Pointcut; + + +public class EclipseAdvice extends Advice { + public EclipseAdvice( + AdviceKind kind, + Pointcut pointcut, + Member signature, + int extraParameterFlags, + int start, int end, ISourceContext context) { + + super(kind, pointcut, signature, extraParameterFlags, start, end, context); + } + + + + public void implementOn(Shadow shadow) { + throw new RuntimeException("unimplemented"); + } + + public void specializeOn(Shadow shadow) { + throw new RuntimeException("unimplemented"); + } + + public int compareTo(Object other) { + throw new RuntimeException("unimplemented"); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseObjectType.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseObjectType.java new file mode 100644 index 000000000..c483f6094 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseObjectType.java @@ -0,0 +1,123 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.ast.*; +import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration; +import org.aspectj.weaver.*; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class EclipseObjectType extends ResolvedTypeX.Name { + private ReferenceBinding binding; + + private ResolvedMember[] declaredPointcuts = null; + private ResolvedMember[] declaredMethods = null; + private ResolvedMember[] declaredFields = null; + + + public EclipseObjectType(String signature, EclipseWorld world, ReferenceBinding binding) { + super(signature, world); + this.binding = binding; + } + + private EclipseWorld eclipseWorld() { + return (EclipseWorld)world; + } + + + public boolean isAspect() { + if (!(binding instanceof SourceTypeBinding)) return false; + //XXX assume SourceBinding throughout + return ((SourceTypeBinding)binding).scope.referenceContext instanceof AspectDeclaration; + + } + + public ResolvedTypeX getSuperclass() { + //XXX what about java.lang.Object + return eclipseWorld().fromEclipse(binding.superclass()); + } + + public ResolvedTypeX[] getDeclaredInterfaces() { + return eclipseWorld().fromEclipse(binding.superInterfaces()); + } + + public ResolvedMember[] getDeclaredFields() { + if (declaredFields == null) fillDeclaredMembers(); + return declaredFields; + } + + public ResolvedMember[] getDeclaredMethods() { + if (declaredMethods == null) fillDeclaredMembers(); + return declaredMethods; + } + + public ResolvedMember[] getDeclaredPointcuts() { + if (declaredPointcuts == null) fillDeclaredMembers(); + return declaredPointcuts; + } + + private void fillDeclaredMembers() { + List declaredPointcuts = new ArrayList(); + List declaredMethods = new ArrayList(); + List declaredFields = new ArrayList(); + + MethodBinding[] methods = binding.methods(); + for (int i=0, len=methods.length; i < len; i++) { + MethodBinding m = methods[i]; + AbstractMethodDeclaration amd = m.sourceMethod(); + if (amd == null) continue; //??? + if (amd instanceof PointcutDeclaration) { + PointcutDeclaration d = (PointcutDeclaration)amd; + declaredPointcuts.add(d.makeResolvedPointcutDefinition()); + } else { + //XXX this doesn't handle advice quite right + declaredMethods.add(eclipseWorld().makeResolvedMember(m)); + } + } + + FieldBinding[] fields = binding.fields(); + for (int i=0, len=fields.length; i < len; i++) { + FieldBinding f = fields[i]; + declaredFields.add(eclipseWorld().makeResolvedMember(f)); + } + + this.declaredPointcuts = (ResolvedMember[]) + declaredPointcuts.toArray(new ResolvedMember[declaredPointcuts.size()]); + this.declaredMethods = (ResolvedMember[]) + declaredMethods.toArray(new ResolvedMember[declaredMethods.size()]); + this.declaredFields = (ResolvedMember[]) + declaredFields.toArray(new ResolvedMember[declaredFields.size()]); + } + + + public int getModifiers() { + // only return the real Java modifiers, not the extra eclipse ones + return binding.modifiers & CompilerModifiers.AccJustFlag; + } + + ReferenceBinding getBinding() { + return binding; + } + + public String toString() { + return "EclipseObjectType(" + getClassName() + ")"; + } + public CrosscuttingMembers collectCrosscuttingMembers() { + return crosscuttingMembers; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseScope.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseScope.java new file mode 100644 index 000000000..b77d5e99e --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseScope.java @@ -0,0 +1,254 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.util.*; + +import org.aspectj.weaver.*; +import org.aspectj.weaver.patterns.*; +import org.aspectj.bridge.*; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + +public class EclipseScope implements IScope { + private Scope scope; + private EclipseWorld world; + private ResolvedTypeX enclosingType; + private FormalBinding[] bindings; + + private String[] importedPrefixes = null; + private String[] importedNames = null; + + + public EclipseScope(FormalBinding[] bindings, Scope scope) { + this.bindings = bindings; + + this.scope = scope; + this.world = EclipseWorld.fromScopeLookupEnvironment(scope); + + this.enclosingType = world.fromEclipse(scope.enclosingSourceType()); + } + + + public TypeX lookupType(String name, IHasPosition location) { + computeImports(); + +// System.out.println("lookup: " + name + " in " + +// Arrays.asList(importedPrefixes)); + + ResolvedTypeX ret = null; + String dotName = "." + name; + for (int i=0; i<importedNames.length; i++) { + String importedName = importedNames[i]; + //??? can this be right + if (importedName.endsWith(name) && + ((importedName.length() == name.length()) || + (importedName.endsWith(dotName)))) + { + ResolvedTypeX found = resolveVisible(importedName); + if (found == ResolvedTypeX.MISSING) continue; + if (ret != null) { + message(IMessage.ERROR, location, + "ambiguous type reference, both " + ret.getName() + " and " + importedName); + return ResolvedTypeX.MISSING; + } else { + ret = found; + } + } + } + + if (ret != null) return ret; + + //XXX need to handle ambiguous references here + for (int i=0; i<importedPrefixes.length; i++) { + String importedPrefix = importedPrefixes[i]; + ResolvedTypeX tryType = resolveVisible(importedPrefix + name); + if (tryType != ResolvedTypeX.MISSING) { + return tryType; + } + } + + return resolveVisible(name); + } + + + private ResolvedTypeX resolveVisible(String name) { + ResolvedTypeX found = world.resolve(TypeX.forName(name), true); + if (found == ResolvedTypeX.MISSING) return found; + if (ResolvedTypeX.isVisible(found.getModifiers(), found, enclosingType)) return found; + return ResolvedTypeX.MISSING; + } + + +// public TypeX lookupType(String name, IHasPosition location) { +// char[][] namePieces = CharOperation.splitOn('.', name.toCharArray()); +// TypeBinding binding; +// if (namePieces.length == 1) { +// binding = scope.getType(namePieces[0]); +// } else { +// binding = scope.getType(namePieces); +// } +// +// +// if (!binding.isValidBinding()) { +// //XXX do we do this always or sometimes +// System.err.println("error: " + binding); +// scope.problemReporter().invalidType(EclipseWorld.astForLocation(location), binding); +// return ResolvedTypeX.MISSING; +// } +// //??? do we want this too +//// if (AstNode.isTypeUseDeprecated(binding, scope)) +//// scope.problemReporter().deprecatedType(binding, EclipseWorld.astForLocation(location)); +// +// return EclipseWorld.fromBinding(binding); +// } + + + + private void computeImports() { + if (importedNames != null) return; + + List importedNamesList = new ArrayList(); + List importedPrefixesList = new ArrayList(); + + + Scope currentScope = scope; + //add any enclosing types to this list + while (!(currentScope instanceof CompilationUnitScope)) { + if (currentScope == null) { + throw new RuntimeException("unimplemented"); + } + if (currentScope instanceof ClassScope) { + addClassAndParentsToPrefixes(((ClassScope)currentScope).referenceType().binding, importedPrefixesList); + } + currentScope = currentScope.parent; + } + + CompilationUnitScope cuScope = (CompilationUnitScope)currentScope; + + String packageName = + new String(CharOperation.concatWith(cuScope.currentPackageName, '.')); + if (packageName.length() > 1) { + importedPrefixesList.add(packageName + "."); + } + + + ImportBinding[] imports = cuScope.imports; + for (int i = 0; i < imports.length; i++) { + ImportBinding importBinding = imports[i]; + String importName = + new String(CharOperation.concatWith(importBinding.compoundName, '.')); + + //XXX wrong behavior for java.util.Map.* + if (importBinding.onDemand) { + importedPrefixesList.add(importName + "."); + } else { + importedNamesList.add(importName); + } + } + + TypeBinding[] topTypes = cuScope.topLevelTypes; + for (int i = 0; i < topTypes.length; i++) { + importedNamesList.add(EclipseWorld.fromBinding(topTypes[i]).getName()); + } + + importedNames = + (String[])importedNamesList.toArray(new String[importedNamesList.size()]); + + importedPrefixes = + (String[])importedPrefixesList.toArray(new String[importedPrefixesList.size()]); + } + + private void addClassAndParentsToPrefixes( + ReferenceBinding binding, + List importedPrefixesList) + { + if (binding == null) return; + importedPrefixesList.add(EclipseWorld.fromBinding(binding).getName()+"$"); + + addClassAndParentsToPrefixes(binding.superclass(), importedPrefixesList); + ReferenceBinding[] superinterfaces = binding.superInterfaces(); + if (superinterfaces != null) { + for (int i = 0; i < superinterfaces.length; i++) { + addClassAndParentsToPrefixes(superinterfaces[i], importedPrefixesList); + } + } + } + + + public String[] getImportedNames() { + computeImports(); + return importedNames; + } + + public String[] getImportedPrefixes() { + computeImports(); + return importedPrefixes; + } + + + //XXX add good errors when would bind to extra parameters + public FormalBinding lookupFormal(String name) { + for (int i = 0, len = bindings.length; i < len; i++) { + if (bindings[i].getName().equals(name)) return bindings[i]; + } + return null; + } + + + public FormalBinding getFormal(int i) { + return bindings[i]; + } + + public int getFormalCount() { + return bindings.length; + } + + public ISourceLocation makeSourceLocation(IHasPosition location) { + return new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(), + location.getStart(), location.getEnd()); + } + + public IMessageHandler getMessageHandler() { + return world.getMessageHandler(); + } + + + public void message( + IMessage.Kind kind, + IHasPosition location1, + IHasPosition location2, + String message) { + message(kind, location1, message); + message(kind, location2, message); + } + + public void message( + IMessage.Kind kind, + IHasPosition location, + String message) { + //System.out.println("message: " + message + " loc: " + makeSourceLocation(location)); + getMessageHandler() + .handleMessage(new Message(message, kind, null, makeSourceLocation(location))); + + } + public World getWorld() { + return world; + } + + public ResolvedTypeX getEnclosingType() { + return enclosingType; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseShadow.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseShadow.java new file mode 100644 index 000000000..5f362ccc3 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseShadow.java @@ -0,0 +1,132 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration; +import org.aspectj.bridge.SourceLocation; +import org.aspectj.weaver.*; +import org.aspectj.weaver.ast.Var; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.AstNode; +import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; + +public class EclipseShadow extends Shadow { + EclipseWorld world; + AstNode astNode; + //XXXReferenceContext context; + AbstractMethodDeclaration enclosingMethod; + + public EclipseShadow(EclipseWorld world, Kind kind, Member signature, AstNode astNode, + ReferenceContext context) + { + super(kind, signature); + this.world = world; + this.astNode = astNode; + //XXX can this fail in practice? + this.enclosingMethod = (AbstractMethodDeclaration)context; + } + + public World getIWorld() { + return world; + } + + public boolean hasThis() { + return !enclosingMethod.isStatic(); //XXX what about pre-initialization + } + + public TypeX getThisType() { + return world.fromBinding(enclosingMethod.binding.declaringClass); + } + + public TypeX getEnclosingType() { + return getThisType(); //??? why is this different from the above + } + + public SourceLocation getSourceLocation() { + //XXX need to fill this in ASAP + return null; + } + + public Member getEnclosingCodeSignature() { + return world.makeResolvedMember(enclosingMethod.binding); + } + + // -- all below here are only used for implementing, not in matching + // -- we should probably pull out a super-interface to capture this in type system + + public Var getThisVar() { + throw new RuntimeException("unimplemented"); + } + + public Var getTargetVar() { + throw new RuntimeException("unimplemented"); + } + + public Var getArgVar(int i) { + throw new RuntimeException("unimplemented"); + } + + public Var getThisJoinPointVar() { + throw new RuntimeException("unimplemented"); + } + + public Var getThisJoinPointStaticPartVar() { + throw new RuntimeException("unimplemented"); + } + + public Var getThisEnclosingJoinPointStaticPartVar() { + throw new RuntimeException("unimplemented"); + } + + // --- factory methods + + public static EclipseShadow makeShadow(EclipseWorld world, AstNode astNode, + ReferenceContext context) + { + //XXX make sure we're getting the correct declaring type at call-site + if (astNode instanceof AllocationExpression) { + AllocationExpression e = (AllocationExpression)astNode; + return new EclipseShadow(world, Shadow.ConstructorCall, + world.makeResolvedMember(e.binding), astNode, context); + } else if (astNode instanceof MessageSend) { + MessageSend e = (MessageSend)astNode; + return new EclipseShadow(world, Shadow.MethodCall, + world.makeResolvedMember(e.binding), astNode, context); + } else if (astNode instanceof ExplicitConstructorCall) { + //??? these need to be ignored, they don't have shadows + return null; +// ExplicitConstructorCall e = (ExplicitConstructorCall)astNode; +// return new EclipseShadow(world, Shadow.MethodCall, +// world.makeResolvedMember(e.binding), astNode, context); + } else if (astNode instanceof AbstractMethodDeclaration) { + AbstractMethodDeclaration e = (AbstractMethodDeclaration)astNode; + Shadow.Kind kind; + if (e instanceof AdviceDeclaration) { + kind = Shadow.AdviceExecution; + } else if (e instanceof MethodDeclaration) { + kind = Shadow.MethodExecution; + } else if (e instanceof ConstructorDeclaration) { + kind = Shadow.ConstructorExecution; + } else { + throw new RuntimeException("unimplemented: " + e); + } + return new EclipseShadow(world, kind, + world.makeResolvedMember(e.binding), astNode, context); + } else { + throw new RuntimeException("unimplemented: " + astNode); + } + } + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java new file mode 100644 index 000000000..57f96197c --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java @@ -0,0 +1,65 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.io.File; + +import org.aspectj.bridge.ISourceLocation; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.problem.ProblemHandler; + +public class EclipseSourceLocation implements ISourceLocation { + CompilationResult result; + int startPos, endPos; + + public EclipseSourceLocation(CompilationResult result, int startPos, int endPos) { + super(); + this.result = result; + this.startPos = startPos; + this.endPos = endPos; + } + + public File getSourceFile() { + return new File(new String(result.fileName)); + } + + public int getLine() { + return ProblemHandler.searchLineNumber(result.lineSeparatorPositions, startPos); + } + + public int getColumn() { + return 0; //XXX need better search above to get both + } + + public int getEndLine() { + return getLine(); //XXX no real need to do better + } + + + /** @return String {file:}line{:column} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + + if (getSourceFile() != ISourceLocation.NO_FILE) { + sb.append(getSourceFile().getPath()); + sb.append(":"); + } + sb.append("" + getLine()); + if (getColumn() != 0) { + sb.append(":" + getColumn()); + } + return sb.toString(); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java new file mode 100644 index 000000000..2610a56c0 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java @@ -0,0 +1,141 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.lang.reflect.Modifier; + +import org.aspectj.bridge.*; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.weaver.*; +import org.aspectj.weaver.ConcreteTypeMunger; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; + + +public class EclipseTypeMunger extends ConcreteTypeMunger { + protected ReferenceBinding targetBinding = null; + private AbstractMethodDeclaration sourceMethod; + + public EclipseTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType, + AbstractMethodDeclaration sourceMethod) + { + super(munger, aspectType); + this.sourceMethod = sourceMethod; + } + + public String toString() { + return "(EclipseTypeMunger " + getMunger() + ")"; + } + + private boolean match(ClassScope scope) { + if (targetBinding == null) { + TypeX targetTypeX = munger.getSignature().getDeclaringType(); + targetBinding = + (ReferenceBinding)EclipseWorld.fromScopeLookupEnvironment(scope).makeTypeBinding(targetTypeX); + } + //??? assumes instance uniqueness for ReferenceBindings + return targetBinding == scope.referenceContext.binding; + + } + + /** + * Modifies signatures of a TypeBinding through its ClassScope, + * i.e. adds Method|FieldBindings, plays with inheritance, ... + */ + public boolean munge(ClassScope classScope) { + if (!match(classScope)) return false; + + if (munger.getKind() == ResolvedTypeMunger.Field) { + mungeNewField(classScope, (NewFieldTypeMunger)munger); + } else if (munger.getKind() == ResolvedTypeMunger.Method) { + mungeNewMethod(classScope, (NewMethodTypeMunger)munger); + } else if (munger.getKind() == ResolvedTypeMunger.Constructor) { + mungeNewConstructor(classScope, (NewConstructorTypeMunger)munger); + } else { + throw new RuntimeException("unimplemented"); + } + return true; + } + + + private void mungeNewMethod(ClassScope classScope, NewMethodTypeMunger munger) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + +// if (shouldTreatAsPublic()) { +// MethodBinding binding = world.makeMethodBinding(munger.getSignature()); +// findOrCreateInterTypeMemberFinder(classScope).addInterTypeMethod(binding); +// //classScope.referenceContext.binding.addMethod(binding); +// } else { + InterTypeMethodBinding binding = + new InterTypeMethodBinding(world, munger.getSignature(), aspectType, sourceMethod); + findOrCreateInterTypeMemberFinder(classScope).addInterTypeMethod(binding); +// } + + } + private void mungeNewConstructor(ClassScope classScope, NewConstructorTypeMunger munger) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + + if (shouldTreatAsPublic()) { + MethodBinding binding = world.makeMethodBinding(munger.getSignature()); + findOrCreateInterTypeMemberFinder(classScope).addInterTypeMethod(binding); + //classScope.referenceContext.binding.addMethod(binding); + } else { + InterTypeMethodBinding binding = + new InterTypeMethodBinding(world, munger.getSignature(), aspectType, sourceMethod); + findOrCreateInterTypeMemberFinder(classScope).addInterTypeMethod(binding); + } + + } + + private void mungeNewField(ClassScope classScope, NewFieldTypeMunger munger) { + EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope); + + if (shouldTreatAsPublic() && !targetBinding.isInterface()) { + FieldBinding binding = world.makeFieldBinding(munger.getSignature()); + findOrCreateInterTypeMemberFinder(classScope).addInterTypeField(binding); + //classScope.referenceContext.binding.addField(binding); + } else { + InterTypeFieldBinding binding = + new InterTypeFieldBinding(world, munger.getSignature(), aspectType, sourceMethod); + findOrCreateInterTypeMemberFinder(classScope).addInterTypeField(binding); + } + } + + + private boolean shouldTreatAsPublic() { + //??? this is where we could fairly easily choose to treat package-protected + //??? introductions like public ones when the target type and the aspect + //??? are in the same package + return Modifier.isPublic(munger.getSignature().getModifiers()); + } + + + private InterTypeMemberFinder findOrCreateInterTypeMemberFinder(ClassScope classScope) { + InterTypeMemberFinder finder = + (InterTypeMemberFinder)classScope.referenceContext.binding.memberFinder; + if (finder == null) { + finder = new InterTypeMemberFinder(); + classScope.referenceContext.binding.memberFinder = finder; + finder.sourceTypeBinding = classScope.referenceContext.binding; + } + return finder; + } + + public ISourceLocation getSourceLocation() { + return new EclipseSourceLocation(sourceMethod.compilationResult, + sourceMethod.sourceStart, sourceMethod.sourceEnd); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseWorld.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseWorld.java new file mode 100644 index 000000000..f7e74ddc2 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseWorld.java @@ -0,0 +1,263 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.ast.AstUtil; +import org.aspectj.ajdt.internal.core.builder.*; +import org.aspectj.ajdt.internal.core.builder.AjBuildManager; +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.weaver.*; +import org.aspectj.weaver.patterns.*; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.impl.*; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + +public class EclipseWorld extends World { + public static boolean DEBUG = false; + + public AjBuildManager buildManager; + private LookupEnvironment lookupEnvironment; + + private Map addedTypeBindings = new HashMap(); + + public static EclipseWorld forLookupEnvironment(LookupEnvironment env) { + AjLookupEnvironment aenv = (AjLookupEnvironment)env; + return aenv.world; + } + + public static EclipseWorld fromScopeLookupEnvironment(Scope scope) { + return forLookupEnvironment(AstUtil.getCompilationUnitScope(scope).environment); + } + + + public EclipseWorld(LookupEnvironment lookupEnvironment, IMessageHandler handler) { + this.lookupEnvironment = lookupEnvironment; + setMessageHandler(handler); + } + + public Advice concreteAdvice(AdviceKind kind, Pointcut p, Member m, int extraMods, + int start, int end, ISourceContext context) + { + return new EclipseAdvice(kind, p, m, extraMods, start, end, context); + } + + public ConcreteTypeMunger concreteTypeMunger( + ResolvedTypeMunger munger, ResolvedTypeX aspectType) + { + return null; + //throw new RuntimeException("unimplemented"); + } + + protected ResolvedTypeX resolveObjectType(TypeX ty) { + String n = ty.getName(); + //n = n.replace('$', '.'); + char[][] name = CharOperation.splitOn('.', n.toCharArray()); //ty.getName().toCharArray()); + ReferenceBinding ret = lookupEnvironment.getType(name); + //System.out.println("name: " + ty.getName() + ", " + ret); + if (ret == null || ret instanceof ProblemReferenceBinding) return ResolvedTypeX.MISSING; + return new EclipseObjectType(ty.getSignature(), this, ret); + } + + + public ResolvedTypeX fromEclipse(ReferenceBinding binding) { + if (binding == null) return ResolvedTypeX.MISSING; + //??? this seems terribly inefficient + //System.out.println("resolving: " + binding + ", name = " + getName(binding)); + ResolvedTypeX ret = resolve(fromBinding(binding)); + //System.out.println(" got: " + ret); + return ret; + } + + public ResolvedTypeX[] fromEclipse(ReferenceBinding[] bindings) { + if (bindings == null) { + return ResolvedTypeX.NONE; + } + int len = bindings.length; + ResolvedTypeX[] ret = new ResolvedTypeX[len]; + for (int i=0; i < len; i++) { + ret[i] = fromEclipse(bindings[i]); + } + return ret; + } + + + private static String getName(TypeBinding binding) { + String packageName = new String(binding.qualifiedPackageName()); + String className = new String(binding.qualifiedSourceName()).replace('.', '$'); + if (packageName.length() > 0) { + className = packageName + "." + className; + } + //XXX doesn't handle arrays correctly (or primitives?) + return new String(className); + } + + + + //??? going back and forth between strings and bindings is a waste of cycles + public static TypeX fromBinding(TypeBinding binding) { +// if (binding instanceof ReferenceBinding) { +// return fromEclipse( (ReferenceBinding)binding); +// } else { + + if (binding instanceof HelperInterfaceBinding) { + return ((HelperInterfaceBinding)binding).getTypeX(); + } + if (binding.qualifiedSourceName() == null) return ResolvedTypeX.MISSING; + return TypeX.forName(getName(binding)); +// } + } + + public static TypeX[] fromBindings(TypeBinding[] bindings) { + int len = bindings.length; + TypeX[] ret = new TypeX[len]; + for (int i=0; i<len; i++) { + ret[i] = fromBinding(bindings[i]); + } + return ret; + } + + public static AstNode astForLocation(IHasPosition location) { + return new EmptyStatement(location.getStart(), location.getEnd()); + } + + public Collection getTypeMungers() { + return crosscuttingMembersSet.getTypeMungers(); + } + + public static ResolvedMember makeResolvedMember(MethodBinding binding) { + return new ResolvedMember( + Member.METHOD, + fromBinding(binding.declaringClass), + binding.modifiers, + fromBinding(binding.returnType), + new String(binding.selector), + fromBindings(binding.parameters)); + //XXX need to add checked exceptions + } + + public static ResolvedMember makeResolvedMember(FieldBinding binding) { + return new ResolvedMember( + Member.FIELD, + fromBinding(binding.declaringClass), + binding.modifiers, + fromBinding(binding.type), + new String(binding.name), + TypeX.NONE); + } + + public TypeBinding makeTypeBinding(TypeX typeX) { + //System.out.println("in: " + typeX.getSignature() + " have: " + addedTypeBindings); + TypeBinding ret = (TypeBinding)addedTypeBindings.get(typeX); + if (ret != null) return ret; + + if (typeX.isPrimitive()) { + if (typeX == ResolvedTypeX.BOOLEAN) return BaseTypes.BooleanBinding; + if (typeX == ResolvedTypeX.BYTE) return BaseTypes.ByteBinding; + if (typeX == ResolvedTypeX.CHAR) return BaseTypes.CharBinding; + if (typeX == ResolvedTypeX.DOUBLE) return BaseTypes.DoubleBinding; + if (typeX == ResolvedTypeX.FLOAT) return BaseTypes.FloatBinding; + if (typeX == ResolvedTypeX.INT) return BaseTypes.IntBinding; + if (typeX == ResolvedTypeX.LONG) return BaseTypes.LongBinding; + if (typeX == ResolvedTypeX.SHORT) return BaseTypes.ShortBinding; + if (typeX == ResolvedTypeX.VOID) return BaseTypes.VoidBinding; + throw new RuntimeException("weird primitive type " + typeX); + } else if (typeX.isArray()) { + int dim = 0; + while (typeX.isArray()) { + dim++; + typeX = typeX.getComponentType(); + } + return new ArrayBinding(makeTypeBinding(typeX), dim); + } else { + ResolvedTypeX rt = typeX.resolve(this); + //System.out.println("typex: " + typeX + ", " + rt); + if (rt == ResolvedTypeX.MISSING) { + throw new RuntimeException("shouldn't be missing: " + typeX); + } + return ((EclipseObjectType)rt).getBinding(); + } + } + + public TypeBinding[] makeTypeBindings(TypeX[] types) { + int len = types.length; + TypeBinding[] ret = new TypeBinding[len]; + + for (int i = 0; i < len; i++) { + ret[i] = makeTypeBinding(types[i]); + } + return ret; + } + + + public FieldBinding makeFieldBinding(ResolvedMember member) { + return new FieldBinding(member.getName().toCharArray(), + makeTypeBinding(member.getReturnType()), + member.getModifiers(), + (ReferenceBinding)makeTypeBinding(member.getDeclaringType()), + Constant.NotAConstant); + } + + + public MethodBinding makeMethodBinding(ResolvedMember member) { + if (member.getExceptions() != null && member.getExceptions().length > 0) { + throw new RuntimeException("unimplemented"); + } + return new MethodBinding(member.getModifiers(), + member.getName().toCharArray(), + makeTypeBinding(member.getReturnType()), + makeTypeBindings(member.getParameterTypes()), + new ReferenceBinding[0], + (ReferenceBinding)makeTypeBinding(member.getDeclaringType())); + } + + public MethodBinding makeMethodBindingForCall(Member member) { + return new MethodBinding(member.getCallsiteModifiers(), + member.getName().toCharArray(), + makeTypeBinding(member.getReturnType()), + makeTypeBindings(member.getParameterTypes()), + new ReferenceBinding[0], + (ReferenceBinding)makeTypeBinding(member.getDeclaringType())); + } + + public void finishedCompilationUnit(CompilationUnitDeclaration unit) { + if (buildManager.doGenerateModel()) { + AsmBuilder.build(unit, buildManager.getStructureModel()); + } + } + + + public void addTypeBinding(TypeBinding binding) { + addedTypeBindings.put(fromBinding(binding), binding); + } + + public Shadow makeShadow( + AstNode location, + ReferenceContext context) + { + return EclipseShadow.makeShadow(this, location, context); + } + + public Shadow makeShadow( + ReferenceContext context) + { + return EclipseShadow.makeShadow(this, (AstNode)context, context); + } + + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/HelperInterfaceBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/HelperInterfaceBinding.java new file mode 100644 index 000000000..132a9b294 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/HelperInterfaceBinding.java @@ -0,0 +1,99 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + + package org.aspectj.ajdt.internal.compiler.lookup; + +import java.util.*; + +import org.aspectj.weaver.*; +import org.aspectj.weaver.TypeX; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class HelperInterfaceBinding extends SourceTypeBinding { + private TypeX typeX; + SourceTypeBinding enclosingType; + List methods = new ArrayList(); + + public HelperInterfaceBinding(SourceTypeBinding enclosingType, TypeX typeX) { + super(); + this.fPackage = enclosingType.fPackage; + //this.fileName = scope.referenceCompilationUnit().getFileName(); + this.modifiers = AccPublic | AccInterface; + this.sourceName = enclosingType.scope.referenceContext.name; + this.enclosingType = enclosingType; + this.typeX = typeX; + + this.scope = enclosingType.scope; + } + + public HelperInterfaceBinding( + char[][] compoundName, + PackageBinding fPackage, + ClassScope scope) { + super(compoundName, fPackage, scope); + } + + public char[] getFileName() { + return enclosingType.getFileName(); + } + + public TypeX getTypeX() { + return typeX; + } + + public void addMethod(EclipseWorld world , ResolvedMember member) { + MethodBinding binding = world.makeMethodBinding(member); + this.methods.add(binding); + } + + public FieldBinding[] fields() { return new FieldBinding[0]; } + + public MethodBinding[] methods() { return new MethodBinding[0]; } + + + public char[] constantPoolName() { + String sig = typeX.getSignature(); + return sig.substring(1, sig.length()-1).toCharArray(); + } + + public void generateClass(CompilationResult result, ClassFile enclosingClassFile) { + ClassFile classFile = new ClassFile(this, enclosingClassFile, false); + classFile.addFieldInfos(); + + classFile.setForMethodInfos(); + for (Iterator i = methods.iterator(); i.hasNext(); ) { + MethodBinding b = (MethodBinding)i.next(); + generateMethod(classFile, b); + } + + classFile.addAttributes(); + + result.record(this.constantPoolName(), classFile); + } + + + private void generateMethod(ClassFile classFile, MethodBinding binding) { + classFile.generateMethodInfoHeader(binding); + int methodAttributeOffset = classFile.contentsOffset; + int attributeNumber = classFile.generateMethodInfoAttribute(binding); + classFile.completeMethodInfo(methodAttributeOffset, attributeNumber); + } + + + + public ReferenceBinding[] superInterfaces() { + return new ReferenceBinding[0]; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeFieldBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeFieldBinding.java new file mode 100644 index 000000000..db30f03ff --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeFieldBinding.java @@ -0,0 +1,113 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.lang.reflect.Modifier; + +import org.aspectj.ajdt.internal.compiler.ast.AstUtil; +import org.aspectj.weaver.*; +import org.aspectj.weaver.NameMangler; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + +public class InterTypeFieldBinding extends FieldBinding { + public ReferenceBinding targetType; + public SyntheticAccessMethodBinding reader; + public SyntheticAccessMethodBinding writer; + public AbstractMethodDeclaration sourceMethod; + + public InterTypeFieldBinding(EclipseWorld world, ResolvedMember signature, TypeX withinType, + AbstractMethodDeclaration sourceMethod) + { + super(world.makeFieldBinding(signature), null); + this.sourceMethod = sourceMethod; + + targetType = (ReferenceBinding)world.makeTypeBinding(signature.getDeclaringType()); + this.declaringClass = (ReferenceBinding)world.makeTypeBinding(withinType); + + reader = new SimpleSyntheticAccessMethodBinding(world.makeMethodBinding( + AjcMemberMaker.interFieldGetDispatcher(signature, withinType) + )); + + writer = new SimpleSyntheticAccessMethodBinding(world.makeMethodBinding( + AjcMemberMaker.interFieldSetDispatcher(signature, withinType) + )); + } + + public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { + if (isPublic()) return true; + + SourceTypeBinding invocationType = scope.invocationType(); + //System.out.println("receiver: " + receiverType + ", " + invocationType); + + if (invocationType == declaringClass) return true; + + + // if (invocationType.isPrivileged) { + // System.out.println("privileged access to: " + this); + // return true; + // } + + if (isProtected()) { + throw new RuntimeException("unimplemented"); + } + + //XXX make sure this walks correctly + if (isPrivate()) { + // answer true if the receiverType is the declaringClass + // AND the invocationType and the declaringClass have a common enclosingType + if (receiverType != declaringClass) return false; + + if (invocationType != declaringClass) { + ReferenceBinding outerInvocationType = invocationType; + ReferenceBinding temp = outerInvocationType.enclosingType(); + while (temp != null) { + outerInvocationType = temp; + temp = temp.enclosingType(); + } + + ReferenceBinding outerDeclaringClass = declaringClass; + temp = outerDeclaringClass.enclosingType(); + while (temp != null) { + outerDeclaringClass = temp; + temp = temp.enclosingType(); + } + if (outerInvocationType != outerDeclaringClass) return false; + } + return true; + } + + // isDefault() + if (invocationType.fPackage == declaringClass.fPackage) return true; + return false; + } + + + public SyntheticAccessMethodBinding getAccessMethod(boolean isReadAccess) { + if (isReadAccess) return reader; + else return writer; + } + + public boolean alwaysNeedsAccessMethod(boolean isReadAccess) { return true; } + + + + public ReferenceBinding getTargetType() { + return targetType; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java new file mode 100644 index 000000000..acc5cb9cf --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java @@ -0,0 +1,401 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.util.*; + +import org.aspectj.weaver.*; +import org.aspectj.weaver.ResolvedTypeX; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + +public class InterTypeMemberFinder implements IMemberFinder { + private List interTypeFields = new ArrayList(); + private List interTypeMethods = new ArrayList(); + + public SourceTypeBinding sourceTypeBinding; + + public FieldBinding getField( + SourceTypeBinding sourceTypeBinding, + char[] fieldName, + InvocationSite site, + Scope scope) + { + FieldBinding retField = sourceTypeBinding.getFieldBase(fieldName); + if (interTypeFields.isEmpty()) return retField; + int fieldLength = fieldName.length; + + for (int i=0, len=interTypeFields.size(); i < len; i++) { + FieldBinding field = (FieldBinding)interTypeFields.get(i); + if (field.name.length == fieldLength && CharOperation.prefixEquals(field.name, fieldName)) { + retField = resolveConflicts(sourceTypeBinding, retField, field, site, scope); + } + } + + return retField; + } + + private FieldBinding resolveConflicts( + SourceTypeBinding sourceTypeBinding, + FieldBinding retField, + FieldBinding field, + InvocationSite site, + Scope scope) + { + if (retField == null) return field; + if (!field.canBeSeenBy(sourceTypeBinding, site, scope)) return retField; + if (!retField.canBeSeenBy(sourceTypeBinding, site, scope)) return field; + //XXX need dominates check on aspects + return new ProblemFieldBinding(retField.declaringClass, retField.name, ProblemReporter.Ambiguous); + } + + +// private void reportConflicts(SourceTypeBinding sourceTypeBinding, +// MethodBinding m1, MethodBinding m2) +// { +// if (m1 == m2) { +// System.err.println("odd that we're ecomparing the same: " + m1); +// return; +// } +// +// if (!m1.areParametersEqual(m2)) return; + +// if (m1 instanceof InterTypeMethodBinding) { +// if (m2 instanceof InterTypeMethodBinding) { +// reportConflictsBoth(sourceTypeBinding, +// (InterTypeMethodBinding)m1, +// (InterTypeMethodBinding)m2); +// } else { +// reportConflictsOne(sourceTypeBinding, +// (InterTypeMethodBinding)m1, +// m2); +// } +// } else if (m2 instanceof InterTypeMethodBinding) { +// reportConflictsOne(sourceTypeBinding, +// (InterTypeMethodBinding)m2, +// m1); +// } else { +// reportConflictsNone(sourceTypeBinding, +// m2, +// m1); +// } +// } + + +// private void reportConflicts( +// SourceTypeBinding sourceTypeBinding, +// MethodBinding m1, +// MethodBinding m2) +// { +// //System.err.println("compare: " + m1 + " with " + m2); +// +// if (m1 == m2) { +// System.err.println("odd that we're ecomparing the same: " + m1); +// return; +// } +// +// if (!m1.areParametersEqual(m2)) return; +// +// //System.err.println("t1: " + getTargetType(m1) + ", " + getTargetType(m2)); +// +// if (getTargetType(m1) != getTargetType(m2)) return; +// +// if (m1.declaringClass == m2.declaringClass) { +// duplicateMethodBinding(m1, m2); +// return; +// } +// +// +// if (m1.isPublic() || m2.isPublic()) { +// duplicateMethodBinding(m1, m2); +// return; +// } +// +// // handle the wierd case where the aspect is a subtype of the target +// if (m2.isProtected()) { +// if (m2.declaringClass.isSuperclassOf(m1.declaringClass)) { +// duplicateMethodBinding(m1, m2); +// } +// // don't return because we also want to do the package test +// } +// +// if (!m1.isPrivate() || !m2.isPrivate()) { +// // at least package visible +// if (m1.declaringClass.getPackage() == m2.declaringClass.getPackage()) { +// duplicateMethodBinding(m1, m2); +// } +// return; +// } +// +// //XXX think about inner types some day +// } +//// + private boolean isVisible(MethodBinding m1, ReferenceBinding s) { + if (m1.declaringClass == s) return true; + + + if (m1.isPublic()) return true; + + //don't need to handle protected + //if (m1.isProtected()) { + + + if (!m1.isPrivate()) { + // at least package visible + return (m1.declaringClass.getPackage() == s.getPackage()); + } + + return false; + } + +// +// private void duplicateMethodBinding(MethodBinding m1, MethodBinding m2) { +// ReferenceBinding t1 = m1.declaringClass; +// ReferenceBinding t2 = m2.declaringClass; +// +// +// +// +// +// +// if (!(t1 instanceof SourceTypeBinding) || !(t2 instanceof SourceTypeBinding)) { +// throw new RuntimeException("unimplemented"); +// } +// +// SourceTypeBinding s1 = (SourceTypeBinding)t1; +// SourceTypeBinding s2 = (SourceTypeBinding)t2; +// +// if (m1.sourceMethod() != null) { +// s1.scope.problemReporter().duplicateMethodInType(s2, m1.sourceMethod()); +// } +// if (m2.sourceMethod() != null) { +// s2.scope.problemReporter().duplicateMethodInType(s1, m2.sourceMethod()); +// } +// } + +// private void reportConflictsNone( +// SourceTypeBinding sourceTypeBinding, +// MethodBinding m2, +// MethodBinding m1) +// { +// throw new RuntimeException("not possible"); +// } + + + +// ReferenceBinding t1 = getDeclaringClass(m1); +// //.declaringClass; +// ReferenceBinding t2 = getDeclaringClass(m2); +// //.declaringClass; +// +// if (t1 == t2) { +// AbstractMethodDeclaration methodDecl = m2.sourceMethod(); // cannot be retrieved after binding is lost +// System.err.println("duplicate: " + t1 + ", " + t2); +// sourceTypeBinding.scope.problemReporter().duplicateMethodInType(sourceTypeBinding, methodDecl); +// methodDecl.binding = null; +// //methods[m] = null; //XXX duplicate problem reports +// return; +// } +// +// if (!(t1 instanceof SourceTypeBinding) || !(t2 instanceof SourceTypeBinding)) { +// throw new RuntimeException("unimplemented"); +// } +// +// SourceTypeBinding s1 = (SourceTypeBinding)t1; +// SourceTypeBinding s2 = (SourceTypeBinding)t2; +// +// +// if (m1.canBeSeenBy(s1, null, s2.scope) || m2.canBeSeenBy(s2, null, s1.scope)) { +// s1.scope.problemReporter().duplicateMethodInType(s2, m1.sourceMethod()); +// s2.scope.problemReporter().duplicateMethodInType(s1, m2.sourceMethod()); +// } +// } + + private ReferenceBinding getTargetType(MethodBinding m2) { + if (m2 instanceof InterTypeMethodBinding) { + return ((InterTypeMethodBinding)m2).getTargetType(); + } + + return m2.declaringClass; + } + + + + //XXX conflicts + public MethodBinding[] getMethods( + SourceTypeBinding sourceTypeBinding, + char[] selector) { +// System.err.println("getMethods: " + new String(sourceTypeBinding.signature()) + +// ", " + new String(selector)); + + MethodBinding[] orig = sourceTypeBinding.getMethodsBase(selector); + if (interTypeMethods.isEmpty()) return orig; + + List ret = new ArrayList(Arrays.asList(orig)); +// System.err.println("declared method: " + ret + " inters = " + interTypeMethods); + + for (int i=0, len=interTypeMethods.size(); i < len; i++) { + MethodBinding method = (MethodBinding)interTypeMethods.get(i); + + if (CharOperation.equals(selector, method.selector)) { + ret.add(method); + } + } + + if (ret.isEmpty()) return SourceTypeBinding.NoMethods; + +// System.err.println("method: " + ret); + + // check for conflicts +// int len = ret.size(); +// if (len > 1) { +// for (int i=0; i <len; i++) { +// MethodBinding m1 = (MethodBinding)ret.get(i); +// for (int j=i+1; j < len; j++) { +// MethodBinding m2 = (MethodBinding)ret.get(j); +// //reportConflicts(sourceTypeBinding, m1, m2); +// } +// } +// } + + + //System.err.println("got methods: " + ret + " on " + sourceTypeBinding); + + return (MethodBinding[])ret.toArray(new MethodBinding[ret.size()]); + } + + public MethodBinding getExactMethod( + SourceTypeBinding sourceTypeBinding, + char[] selector, + TypeBinding[] argumentTypes) + { + MethodBinding ret = sourceTypeBinding.getExactMethodBase(selector, argumentTypes); + if (ret != null) return ret; + + for (int i=0, len=interTypeMethods.size(); i < len; i++) { + MethodBinding im = + (MethodBinding)interTypeMethods.get(i); + if (matches(im, selector, argumentTypes)) { + return im; + } + } + return null; + } +// if (isVisible(im, sourceTypeBinding)) { +// if (ret == null) { +// ret = im; +// } else { +// ret = resolveOverride(ret, im); +// } +// } +// } +// } +// return ret; +// } + +// private MethodBinding resolveOverride(MethodBinding m1, MethodBinding m2) { +// ReferenceBinding t1 = getTargetType(m1); +// ReferenceBinding t2 = getTargetType(m2); +// if (t1 == t2) { +// //XXX also need a test for completely matching sigs +// if (m1.isAbstract()) return m2; +// else if (m2.isAbstract()) return m1; +// +// +// if (m1 instanceof InterTypeMethodBinding) { +// //XXX need to handle dominates here +// EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(sourceTypeBinding.scope); +// int cmp = compareAspectPrecedence(world.fromEclipse(m1.declaringClass), +// world.fromEclipse(m2.declaringClass)); +// if (cmp < 0) return m2; +// else if (cmp > 0) return m1; +// } +// +// duplicateMethodBinding(m1, m2); +// return null; +// } +// if (t1.isSuperclassOf(t2)) { +// return m2; +// } +// if (t2.isSuperclassOf(t1)) { +// return m1; +// } +// +// duplicateMethodBinding(m1, m2); +// return null; +// } + + +// private int compareAspectPrecedence(ResolvedTypeX a1, ResolvedTypeX a2) { +// World world = a1.getWorld(); +// int ret = world.compareByDominates(a1, a2); +// if (ret == 0) { +// if (a1.isAssignableFrom(a2)) return -1; +// if (a2.isAssignableFrom(a1)) return +1; +// } +// return ret; +// } + + + // + private boolean matches(MethodBinding m1, MethodBinding m2) { + return matches(m1, m2.selector, m2.parameters); + // && + // (isVisible(m1, m2.declaringClass) || isVisible(m2, m1.declaringClass)); + } + + private boolean matches(MethodBinding method, char[] selector, TypeBinding[] argumentTypes) { + if (!CharOperation.equals(selector, method.selector)) return false; + int argCount = argumentTypes.length; + if (method.parameters.length != argCount) return false; + + TypeBinding[] toMatch = method.parameters; + for (int p = 0; p < argCount; p++) { + if (toMatch[p] != argumentTypes[p]) return false; + } + return true; + } + + + + + public void addInterTypeField(FieldBinding binding) { + interTypeFields.add(binding); + } + + public void addInterTypeMethod(MethodBinding binding) { + // check for conflicts with existing methods, should really check type as well... + //System.err.println("adding: " + binding + " to " + sourceTypeBinding); + if (isVisible(binding, sourceTypeBinding)) { + MethodBinding[] baseMethods = sourceTypeBinding.methods; + for (int i=0, len=baseMethods.length; i < len; i++) { + MethodBinding b = baseMethods[i]; + if (matches(binding, b)) { + // this always means we should remove the existing method + if (b.sourceMethod() != null) { + b.sourceMethod().binding = null; + } + sourceTypeBinding.removeMethod(i); + //System.err.println(" left: " + Arrays.asList(sourceTypeBinding.methods)); + break; + } + } + } + + interTypeMethods.add(binding); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMethodBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMethodBinding.java new file mode 100644 index 000000000..1a0d8066c --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMethodBinding.java @@ -0,0 +1,147 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import org.aspectj.weaver.*; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class InterTypeMethodBinding extends MethodBinding { + //private ReferenceBinding withinType; + private ReferenceBinding targetType; + private MethodBinding syntheticMethod; + + //public MethodBinding introducedMethod; + + public AbstractMethodDeclaration sourceMethod; + + public InterTypeMethodBinding(EclipseWorld world, ResolvedMember signature, TypeX withinType, + AbstractMethodDeclaration sourceMethod) + { + super(world.makeMethodBinding(signature), null); + this.sourceMethod = sourceMethod; + + targetType = (ReferenceBinding)world.makeTypeBinding(signature.getDeclaringType()); + this.declaringClass = (ReferenceBinding)world.makeTypeBinding(withinType); + + if (signature.getKind() == Member.METHOD) { + syntheticMethod = + world.makeMethodBinding(AjcMemberMaker.interMethodDispatcher(signature, withinType)); + } else { + syntheticMethod = world.makeMethodBinding( + AjcMemberMaker.interConstructor(world.resolve(signature.getDeclaringType()), + signature, withinType)); + } + + + } + +// +// this.declaringClass = +// +// +// +// char[] dispatch2Name; +// if (Modifier.isPublic(modifiers)) { +// dispatch2Name = name; +// } else if (Modifier.isPrivate(modifiers)) { +// dispatch2Name = +// AstUtil.makeAjcMangledName("dispatch2".toCharArray(), withinType, selector); +// } else { +// // package visible +// //??? optimize both in same package +// dispatch2Name = +// AstUtil.makeAjcMangledName("dispatch2".toCharArray(), +// withinType.qualifiedPackageName(), selector); +// } +// +// introducedMethod = +// new MethodBinding(AstUtil.makePublic(modifiers), dispatch2Name, +// type, args, exceptions, declaringClass); +// +// this.dispatchMethod = +// new DispatchMethodBinding(introducedMethod, withinType, mangledParams); +// } + + + //XXX this is identical to InterTypeFieldBinding + public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { + if (isPublic()) return true; + + SourceTypeBinding invocationType = scope.invocationType(); + //System.out.println("receiver: " + receiverType + ", " + invocationType); + + if (invocationType == declaringClass) return true; + + + // if (invocationType.isPrivileged) { + // System.out.println("privileged access to: " + this); + // return true; + // } + + if (isProtected()) { + throw new RuntimeException("unimplemented"); + } + + //XXX make sure this walks correctly + if (isPrivate()) { + // answer true if the receiverType is the declaringClass + // AND the invocationType and the declaringClass have a common enclosingType + //if (receiverType != declaringClass) return false; + + if (invocationType != declaringClass) { + ReferenceBinding outerInvocationType = invocationType; + ReferenceBinding temp = outerInvocationType.enclosingType(); + while (temp != null) { + outerInvocationType = temp; + temp = temp.enclosingType(); + } + + ReferenceBinding outerDeclaringClass = declaringClass; + temp = outerDeclaringClass.enclosingType(); + while (temp != null) { + outerDeclaringClass = temp; + temp = temp.enclosingType(); + } + + //System.err.println("outer dec: " + + if (outerInvocationType != outerDeclaringClass) return false; + } + return true; + } + + // isDefault() + if (invocationType.fPackage == declaringClass.fPackage) return true; + return false; + } + + + public MethodBinding getAccessMethod() { + return syntheticMethod; + } + + public boolean alwaysNeedsAccessMethod() { return true; } + + public AbstractMethodDeclaration sourceMethod() { + return sourceMethod; + } + + public ReferenceBinding getTargetType() { + return targetType; + } + + public String toString() { + return "InterTypeMethodBinding(" + super.toString() + ", " + getTargetType() +")"; + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeScope.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeScope.java new file mode 100644 index 000000000..05bddbd58 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeScope.java @@ -0,0 +1,51 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class InterTypeScope extends ClassScope { + + public InterTypeScope(Scope parent, TypeBinding onType) { + super(parent, null); + if (onType instanceof SourceTypeBinding) { + referenceContext = new TypeDeclaration(null); + referenceContext.binding = ((SourceTypeBinding)onType); + } else { + throw new RuntimeException("unimplemented"); + } + //System.out.println("encolsingSource: " + this.enclosingSourceType()); + } + + public FieldBinding findField( + TypeBinding receiverType, + char[] fieldName, + InvocationSite invocationSite) + { + //System.out.println("find: " + new String(fieldName)); + return super.findField(receiverType, fieldName, invocationSite); + } + + public SourceTypeBinding invocationType() { + return parent.enclosingSourceType(); + } + + public int addDepth() { + return 0; + } + + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PointcutBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PointcutBinding.java new file mode 100644 index 000000000..c63086c40 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PointcutBinding.java @@ -0,0 +1,36 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import org.eclipse.jdt.internal.compiler.lookup.*; + +/** + */ +public class PointcutBinding extends Binding { + + /** + * @see org.eclipse.jdt.internal.compiler.lookup.Binding#bindingType() + */ + public int bindingType() { + return 0; + } + + /** + * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName() + */ + public char[] readableName() { + return null; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PrivilegedFieldBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PrivilegedFieldBinding.java new file mode 100644 index 000000000..bd5ac958a --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PrivilegedFieldBinding.java @@ -0,0 +1,68 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.lang.reflect.Modifier; + +import org.aspectj.ajdt.internal.compiler.ast.*; +import org.aspectj.ajdt.internal.compiler.ast.AstUtil; +import org.aspectj.weaver.*; +import org.aspectj.weaver.NameMangler; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + +public class PrivilegedFieldBinding extends FieldBinding { + public SimpleSyntheticAccessMethodBinding reader; + public SimpleSyntheticAccessMethodBinding writer; + + + public FieldBinding baseField; + + public PrivilegedFieldBinding(AspectDeclaration inAspect, FieldBinding baseField) { + super(baseField, baseField.declaringClass); + + this.reader = new SimpleSyntheticAccessMethodBinding( + inAspect.world.makeMethodBinding( + AjcMemberMaker.privilegedAccessMethodForFieldGet( + inAspect.typeX, inAspect.world.makeResolvedMember(baseField) + ))); + this.writer = new SimpleSyntheticAccessMethodBinding(inAspect.world.makeMethodBinding( + AjcMemberMaker.privilegedAccessMethodForFieldSet( + inAspect.typeX, inAspect.world.makeResolvedMember(baseField) + ))); + } + + + public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { + return true; + + } + + + public SyntheticAccessMethodBinding getAccessMethod(boolean isReadAccess) { + if (isReadAccess) return reader; + else return writer; + } + + public boolean alwaysNeedsAccessMethod(boolean isReadAccess) { return true; } + + + +// public ReferenceBinding getTargetType() { +// return introducedField.declaringClass; +// } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PrivilegedHandler.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PrivilegedHandler.java new file mode 100644 index 000000000..dfa8af816 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PrivilegedHandler.java @@ -0,0 +1,63 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration; +import org.aspectj.weaver.*; +import org.eclipse.jdt.internal.compiler.lookup.*; + + + +public class PrivilegedHandler implements IPrivilegedHandler { + private AspectDeclaration inAspect; + private Map accessors = new HashMap(); + + public PrivilegedHandler(AspectDeclaration inAspect) { + this.inAspect = inAspect; + } + + public FieldBinding getPrivilegedAccessField(FieldBinding baseField) { + ResolvedMember key = inAspect.world.makeResolvedMember(baseField); + if (accessors.containsKey(key)) return (FieldBinding)accessors.get(key); + FieldBinding ret = new PrivilegedFieldBinding(inAspect, baseField); + accessors.put(key, ret); + return ret; + } + + public MethodBinding getPrivilegedAccessMethod(MethodBinding baseMethod) { + ResolvedMember key = inAspect.world.makeResolvedMember(baseMethod); + if (accessors.containsKey(key)) return (MethodBinding)accessors.get(key); + MethodBinding ret = inAspect.world.makeMethodBinding( + AjcMemberMaker.privilegedAccessMethodForMethod(inAspect.typeX, key) + ); + + //new PrivilegedMethodBinding(inAspect, baseMethod); + accessors.put(key, ret); + return ret; + } + + public ResolvedMember[] getMembers() { + Collection m = accessors.keySet(); + int len = m.size(); + ResolvedMember[] ret = new ResolvedMember[len]; + int index = 0; + for (Iterator i = m.iterator(); i.hasNext(); ) { + ret[index++] = (ResolvedMember)i.next(); + } + return ret; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/SimpleSyntheticAccessMethodBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/SimpleSyntheticAccessMethodBinding.java new file mode 100644 index 000000000..8f238a428 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/SimpleSyntheticAccessMethodBinding.java @@ -0,0 +1,27 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.lookup; + +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class SimpleSyntheticAccessMethodBinding extends SyntheticAccessMethodBinding { + public SimpleSyntheticAccessMethodBinding(MethodBinding method) { + super(method); + this.declaringClass = method.declaringClass; +// this.selector = method.selector; +// this.modifiers = method.modifiers; +// this.parameters = method.parameters; +// this.returnType = method.returnType; + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/AjParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/AjParser.java new file mode 100644 index 000000000..40d65731e --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/AjParser.java @@ -0,0 +1,2251 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.parser; + +import java.lang.reflect.Modifier; +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.ast.*; +import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext; +import org.aspectj.weaver.*; +import org.aspectj.weaver.AdviceKind; +import org.aspectj.weaver.patterns.Declare; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.parser.*; +import org.eclipse.jdt.internal.compiler.problem.*; +import org.eclipse.jdt.internal.compiler.util.CharOperation; +import org.eclipse.jdt.internal.core.util.CharArrayOps; + + + +public class AjParser extends Parser { + //===DATA===DATA===DATA===DATA===DATA===DATA===// + public final static byte rhs[] = {0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,1,1,1,1,1,1,1,1,1, + 1,1,1,1,3,1,1,1,3,4,0,1,2,1,1, + 1,1,1,1,1,1,1,5,1,2,1,2,2,2,1, + 1,2,2,2,4,1,1,1,1,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,4,3,5,0,2,1,3,1,2,0,2, + 1,3,5,4,1,1,2,5,4,2,6,3,3,4,3, + 1,0,1,3,1,1,1,1,2,4,6,2,2,3,5, + 7,0,4,1,3,3,1,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,4,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,3,3,2,2,1,3,1,3,1,2,1, + 1,1,3,0,3,1,1,1,1,1,1,1,4,1,3, + 3,7,0,0,0,0,0,2,1,1,1,2,2,4,4, + 5,4,4,2,1,2,3,3,3,1,3,3,1,3,1, + 4,0,2,1,2,2,4,1,1,2,5,5,7,7,7, + 7,2,2,3,2,2,3,1,2,1,2,1,1,2,2, + 1,1,1,1,1,3,3,4,1,3,4,0,1,2,1, + 1,1,1,2,3,4,0,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,3,3,2,1,1,1,1,1,1,1,5,7,7,6, + 2,3,3,4,1,2,2,1,2,3,2,5,5,7,9, + 9,1,1,1,1,3,3,5,2,3,2,3,3,3,5, + 1,3,4,1,2,5,2,1,1,1,1,1,1,3,1, + 1,3,3,3,3,3,1,1,5,6,8,7,2,0,2, + 0,1,3,4,4,1,2,3,2,1,1,2,2,3,3, + 4,6,6,4,4,1,1,1,1,2,2,0,1,1,3, + 3,1,3,3,1,3,3,1,5,5,4,1,3,3,3, + 1,3,3,1,3,3,3,1,3,3,3,3,3,1,3, + 3,1,3,1,3,1,3,1,3,1,3,1,5,1,1, + 3,3,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,0,1,0,1,0,1,0,1,0,1, + 0,1,0,2,0,1,0,1,0,1,0,1,0,1,0, + 1,0,1,0,2,0,0,1,0,1,0,1,0,1,0, + 1 + }; + + + public static char asbStatic[] = null; + public static char asrStatic[] = null; + public static char symbol_indexStatic[] = null; + + public final static String name[] = { null, + "++", + "--", + "==", + "<=", + ">=", + "!=", + "<<", + ">>", + ">>>", + "+=", + "-=", + "*=", + "/=", + "&=", + "|=", + "^=", + "%=", + "<<=", + ">>=", + ">>>=", + "||", + "&&", + "+", + "-", + "!", + "%", + "^", + "&", + "*", + "|", + "~", + "/", + ">", + "<", + "(", + ")", + "{", + "}", + "[", + "]", + ";", + "?", + ":", + ",", + ".", + "=", + "", + "$empty", + "Identifier", + "abstract", + "assert", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "continue", + "default", + "do", + "double", + "else", + "extends", + "false", + "final", + "finally", + "float", + "for", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "void", + "volatile", + "while", + "aspect", + "pointcut", + "around", + "before", + "after", + "declare", + "privileged", + "IntegerLiteral", + "LongLiteral", + "FloatingPointLiteral", + "DoubleLiteral", + "CharacterLiteral", + "StringLiteral", + UNEXPECTED_EOF, + "Invalid Character", + "Goal", + "MethodBody", + "ConstructorBody", + "StaticInitializer", + "Initializer", + "Headers", + "BlockStatements", + "MethodPushModifiersHeader", + "CatchHeader", + "FieldDeclaration", + "ImportDeclaration", + "PackageDeclaration", + "TypeDeclaration", + "GenericMethodDeclaration", + "ClassBodyDeclaration", + "Expression", + "JavaIdentifier", + "AjSimpleName", + "JavaIdentifierNoAround", + "AjSimpleNameNoAround", + "Type", + "PrimitiveType", + "ReferenceType", + "ClassOrInterfaceType", + "ArrayType", + "Name", + "Dims", + "ClassType", + "NameOrAj", + "AjName", + "SimpleName", + "Header", + "ClassHeader", + "InterfaceHeader", + "MethodHeader", + "ConstructorHeader", + "FormalParameter", + "ImportDeclarations", + "TypeDeclarations", + "PackageDeclarationName", + "SingleTypeImportDeclarationNam" + + "e", + "TypeImportOnDemandDeclarationN" + + "ame", + "Modifiers", + "Modifier", + "InterfaceMemberDeclaration", + "AspectHeader", + "AspectBody", + "AspectHeaderName", + "AspectHeaderRestStart", + "PseudoTokens", + "AspectBodyDeclarations", + "AspectBodyDeclaration", + "PointcutHeader", + "MethodHeaderParameters", + "AroundHeader", + "AroundHeaderName", + "BasicAdviceHeader", + "BasicAdviceHeaderName", + "OnType", + "InterTypeMethodHeader", + "InterTypeMethodHeaderName", + "InterTypeConstructorHeader", + "InterTypeConstructorHeaderName", + "VariableInitializer", + "DeclareHeader", + "PseudoToken", + "ClassBody", + "ClassHeaderName", + "InterfaceTypeList", + "InterfaceType", + "ClassBodyDeclarations", + "Block", + "VariableDeclarators", + "VariableDeclarator", + "VariableDeclaratorId", + "ArrayInitializer", + "MethodHeaderName", + "MethodPushModifiersHeaderName", + "ClassTypeList", + "ConstructorHeaderName", + "FormalParameterList", + "ClassTypeElt", + "StaticOnly", + "ExplicitConstructorInvocation", + "Primary", + "InterfaceBody", + "InterfaceHeaderName", + "InterfaceMemberDeclarations", + "VariableInitializers", + "BlockStatement", + "Statement", + "LocalVariableDeclaration", + "StatementWithoutTrailingSubsta" + + "tement", + "StatementNoShortIf", + "StatementExpression", + "PostIncrementExpression", + "PostDecrementExpression", + "MethodInvocation", + "ClassInstanceCreationExpressio" + + "n", + "SwitchBlock", + "SwitchBlockStatements", + "SwitchLabels", + "SwitchBlockStatement", + "SwitchLabel", + "ConstantExpression", + "StatementExpressionList", + "OnlySynchronized", + "Catches", + "Finally", + "CatchClause", + "PushLPAREN", + "PushRPAREN", + "PrimaryNoNewArray", + "FieldAccess", + "ArrayAccess", + "ClassInstanceCreationExpressio" + + "nName", + "ArgumentList", + "DimWithOrWithOutExprs", + "DimWithOrWithOutExpr", + "DimsLoop", + "OneDimLoop", + "PostfixExpression", + "UnaryExpression", + "UnaryExpressionNotPlusMinus", + "MultiplicativeExpression", + "AdditiveExpression", + "ShiftExpression", + "RelationalExpression", + "EqualityExpression", + "AndExpression", + "ExclusiveOrExpression", + "InclusiveOrExpression", + "ConditionalAndExpression", + "ConditionalOrExpression", + "ConditionalExpression", + "AssignmentExpression", + "LeftHandSide", + "AssignmentOperator" + }; + + public static short check_tableStatic[] = null; + public static char lhsStatic[] = null; + public static char actionStatic[] = lhsStatic; + + protected void initData() { + rhsInst = rhs; + asb = asbStatic; + asr = asrStatic; + symbol_index = symbol_indexStatic; + nameInst = name; + check_table = check_tableStatic; + lhs = lhsStatic; + action = actionStatic; + } + + static { + try{ + initAjTables(AjParser.class); + } catch(java.io.IOException ex){ + throw new ExceptionInInitializerError(ex.getMessage()); + } + } + + public final static void initAjTables(Class parserClass) + throws java.io.IOException { + + final String prefix = FILEPREFIX; + int i = 0; + lhsStatic = readTable(parserClass, prefix + (++i) + ".rsc"); //$NON-NLS-1$ + char[] chars = readTable(parserClass, prefix + (++i) + ".rsc"); //$NON-NLS-1$ + check_tableStatic = new short[chars.length]; + for (int c = chars.length; c-- > 0;) { + check_tableStatic[c] = (short) (chars[c] - 32768); + } + asbStatic = readTable(parserClass, prefix + (++i) + ".rsc"); //$NON-NLS-1$ + asrStatic = readTable(parserClass, prefix + (++i) + ".rsc"); //$NON-NLS-1$ + symbol_indexStatic = readTable(parserClass, prefix + (++i) + ".rsc"); //$NON-NLS-1$ + actionStatic = lhsStatic; + } + + + public void initializeScanner(){ + this.scanner = new AjScanner(false, false, this.problemReporter.options.getNonExternalizedStringLiteralSeverity() != ProblemSeverities.Ignore , this.assertMode); + } + + + +//*************New display debugging method + private static final boolean AJ_DEBUG = false; + + void println(Object o) { + if (AJ_DEBUG) System.out.println(o); + } + + private void printStack(Object[] s, int p) { + List list = Arrays.asList(s); + System.out.println(" " + list.subList(0, p+1)); + } + + private void printStack(int[] s, int p) { + StringBuffer buf = new StringBuffer("["); + for (int i=0; i<p+1; i++) { + if (i > 0) buf.append(", "); + buf.append(Integer.toString(s[i])); + } + buf.append("]"); + System.out.println(" " + buf); + } + + private void printStack(long[] s, int p) { + StringBuffer buf = new StringBuffer("["); + for (int i=0; i<p+1; i++) { + if (i > 0) buf.append(", "); + buf.append(Long.toString(s[i])); + } + buf.append("]"); + System.out.println(" " + buf); + } + + private void printStack(char[][] s, int p) { + StringBuffer buf = new StringBuffer("["); + for (int i=0; i<p+1; i++) { + if (i > 0) buf.append(", "); + buf.append(new String(s[i])); + } + buf.append("]"); + System.out.println(" " + buf); + } + + public void display() { + if (!AJ_DEBUG) return; + System.out.print("astStack: "); + printStack(astStack, astPtr); + System.out.print("astLengthStack: "); + printStack(astLengthStack, astLengthPtr); + + System.out.print("expressionStack: "); + printStack(expressionStack, expressionPtr); + System.out.print("expressionLengthStack: "); + printStack(expressionLengthStack, expressionLengthPtr); + + System.out.print("identifierStack: "); + printStack(identifierStack, identifierPtr); + System.out.print("identifierLengthStack: "); + printStack(identifierLengthStack, identifierLengthPtr); + System.out.print("identifierPositionStack: "); + printStack(identifierPositionStack, identifierPtr); + + + System.out.print("intStack:"); + printStack(intStack, intPtr); + System.out.println(); + } + + + +//************** Overriding behavior for standard Java rules + protected void consumeMethodInvocationName() { + super.consumeMethodInvocationName(); + + MessageSend m = (MessageSend)expressionStack[expressionPtr]; + if (CharArrayOps.equals(m.selector, "proceed".toCharArray())) { + expressionStack[expressionPtr] = new Proceed(m); + } + } + + protected void consumeToken(int type) { + currentTokenStart = scanner.startPosition; + super.consumeToken(type); + switch (type) { + case TokenNameaspect : // pseudo keyword + case TokenNameprivileged : // pseudo keyword + case TokenNamepointcut : // pseudo keyword + case TokenNamebefore : // pseudo keyword + case TokenNameafter : // pseudo keyword + case TokenNamearound : // pseudo keyword + case TokenNamedeclare : // pseudo keyword + pushIdentifier(); + scanner.commentPtr = -1; + break; + } + } + + +//************New AspectJ rules + protected void consumeAspectDeclaration() { + // AspectDeclaration ::= AspectHeader AspectBody + consumeClassDeclaration(); + //??? post parsing step here + } + + protected void consumeAspectHeader() { + // AspectHeader ::= AspectHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt AspectHeaderRest + consumeClassHeader(); + } + + protected void consumeAspectHeaderName(boolean isPrivileged) { + // (isPrivileged == false) -> AspectHeaderName ::= Modifiersopt 'aspect' 'Identifier' + // (isPrivileged == true) -> AspectHeaderName ::= Modifiersopt 'privileged' Modifiersopt 'aspect' 'Identifier' + AspectDeclaration aspectDecl = + new AspectDeclaration(this.compilationUnit.compilationResult); + + println("aspect header name: "); + this.display(); + + //highlight the name of the type + long pos = identifierPositionStack[identifierPtr]; + aspectDecl.sourceEnd = (int) pos; + aspectDecl.sourceStart = (int) (pos >>> 32); + aspectDecl.name = identifierStack[identifierPtr--]; + identifierLengthPtr--; + + // pop the aspect pseudo-token + eatIdentifier(); + + + // handle modifiers, only without privileged for now + if (isPrivileged) { + pos = eatIdentifier(); // eat the privileged + int end = (int) pos; + int start = (int) (pos >>> 32); + aspectDecl.isPrivileged = true; + //problemReporter().signalError(start, end, "privileged is unimplemented in 1.1alpha1"); + } + aspectDecl.modifiersSourceStart = intStack[intPtr--]; + aspectDecl.modifiers = intStack[intPtr--]; + if (aspectDecl.modifiersSourceStart >= 0) { + aspectDecl.declarationSourceStart = aspectDecl.modifiersSourceStart; + } + + println("modifiers: " + aspectDecl.modifiers); + + aspectDecl.bodyStart = aspectDecl.sourceEnd + 1; + pushOnAstStack(aspectDecl); + + listLength = 0; // will be updated when reading super-interfaces + // recovery + if (currentElement != null) { + lastCheckPoint = aspectDecl.bodyStart; + currentElement = currentElement.add(aspectDecl, 0); + lastIgnoredToken = -1; + } + + this.display(); + } + + private long eatIdentifier() { + long pos = identifierPositionStack[identifierPtr]; + identifierPtr--; + identifierLengthPtr--; + return pos; + } + + protected void consumeAspectHeaderRest() { + //--[dominates TypePattern] [persingleton() | percflow(PCD) | perthis(PCD) | pertarget(PCD)] + //AspectHeaderRest ::= AspectHeaderRestStart PseudoTokens + concatNodeLists(); + this.display(); + PseudoTokens pseudoTokens = popPseudoTokens("{"); + println("pseudo: " + pseudoTokens); + + AspectDeclaration aspectDecl = (AspectDeclaration) astStack[astPtr]; + + aspectDecl.dominatesPattern = pseudoTokens.maybeParseDominatesPattern(this); + aspectDecl.perClause = pseudoTokens.parsePerClause(this); + // XXX handle dominates + } + + + protected void consumePointcutDeclaration() { + consumePointcutDesignatorOnDeclaration(); + } + + protected void consumeEmptyPointcutDeclaration() { + //??? set pcd to non-null + } + + protected void consumePointcutHeader() { + //PointcutDeclaration ::= Modifiersopt 'pointcut' JavaIdentifier '(' + + PointcutDeclaration ret = new PointcutDeclaration(compilationUnit.compilationResult); + + //the name + long pos = identifierPositionStack[identifierPtr]; + int sourceEnd = (int) pos; + ret.sourceStart = (int) (pos >>> 32); + ret.selector = identifierStack[identifierPtr--]; + identifierLengthPtr--; + + // pop the 'pointcut' keyword + eatIdentifier(); + + // modifiers + ret.declarationSourceStart = intStack[intPtr--]; + ret.modifiers = intStack[intPtr--]; + + pushOnAstStack(ret); + } + + + + protected void consumeAroundDeclaration() { + // AroundDeclaration ::= AroundHeader MethodBody + consumeMethodDeclaration(true); + } + + protected void consumeAroundHeader() { + consumePointcutDesignatorOnAdvice(); + } + + protected void consumeAroundHeaderName() { + // AroundHeaderName ::= Modifiersopt Type 'around' '(' + + AdviceDeclaration adviceDecl = + new AdviceDeclaration(compilationUnit.compilationResult, AdviceKind.Around); + + // skip the name of the advice + long pos = eatIdentifier(); + adviceDecl.sourceStart = (int) (pos >>> 32); + + TypeReference returnType = getTypeReference(intStack[intPtr--]); + + //modifiers + adviceDecl.declarationSourceStart = intStack[intPtr--]; + adviceDecl.modifiers = intStack[intPtr--]; + + adviceDecl.returnType = returnType; + + //XXX get some locations right + + pushOnAstStack(adviceDecl); + } + + protected void consumePointcutDesignatorOnAdvice() { + PointcutDesignator des = popPointcutDesignator("{"); + AdviceDeclaration adviceDecl = (AdviceDeclaration)astStack[astPtr]; + adviceDecl.pointcutDesignator = des; + adviceDecl.sourceEnd = des.sourceEnd; + adviceDecl.bodyStart = des.sourceEnd+1; + } + + protected void consumePointcutDesignatorOnDeclaration() { + PointcutDesignator des = popPointcutDesignator(";"); + PointcutDeclaration adviceDecl = (PointcutDeclaration)astStack[astPtr]; + adviceDecl.pointcutDesignator = des; + adviceDecl.sourceEnd = des.sourceEnd; + adviceDecl.bodyStart = des.sourceEnd+1; + } + + + protected void consumeBasicAdviceDeclaration() { + // BasicAdviceDeclaration ::= BasicAdviceHeader MethodBody + consumeMethodDeclaration(true); + } + + protected void consumeBasicAdviceHeader() { + // BasicAdviceHeader ::= BasicAdviceHeaderName MethodHeaderParameters ExtraParamopt MethodHeaderThrowsClauseopt ':' PseudoTokens + consumePointcutDesignatorOnAdvice(); + } + + + protected void consumeBasicAdviceHeaderName(boolean isAfter) { + // BasicAdviceHeaderName ::= 'before'|'after '(' + + AdviceDeclaration adviceDecl = + new AdviceDeclaration(compilationUnit.compilationResult, isAfter ? AdviceKind.After : AdviceKind.Before); + + // skip the name of the advice + long pos = eatIdentifier(); + adviceDecl.sourceStart = (int) (pos >>> 32); + + //modifiers + adviceDecl.declarationSourceStart = intStack[intPtr--]; + adviceDecl.modifiers = intStack[intPtr--]; + + + //??? get more locations right + + pushOnAstStack(adviceDecl); + } + + protected void consumeExtraParameterWithFormal() { + Argument arg = (Argument)astStack[astPtr--]; + astLengthPtr--; + + ((AdviceDeclaration)astStack[astPtr]).extraArgument = arg; + + consumeExtraParameterNoFormal(); + } + + + protected void consumeExtraParameterNoFormal() { + + + long pos = identifierPositionStack[identifierPtr]; + int end = (int) pos; + int start = (int) (pos >>> 32); + char[] name = identifierStack[identifierPtr--]; + identifierLengthPtr--; + + //System.out.println("extra parameter: " + new String(name)); + + AdviceDeclaration adviceDecl = (AdviceDeclaration)astStack[astPtr]; + if (adviceDecl.kind != AdviceKind.After) { + //XXX error, extra param makes no sense here + } + + if (CharOperation.equals(name, "throwing".toCharArray())) { + adviceDecl.kind = AdviceKind.AfterThrowing; + } else if (CharOperation.equals(name, "returning".toCharArray())) { + adviceDecl.kind = AdviceKind.AfterReturning; + } else { + //XXX illegal name here + } + } + + protected void consumeClassBodyDeclarationInAspect() { } + + + protected void consumeDeclareDeclaration() { + concatNodeLists(); + PseudoTokens tokens = popPseudoTokens(";"); + Declare declare = tokens.parseDeclare(this); + println("parsed declare: " + declare); + display(); + pushOnAstStack(new DeclareDeclaration(this.compilationUnit.compilationResult, declare)); + } + + + + + protected void consumeDeclareHeader() { + consumePseudoTokenIdentifier(); // name + consumePseudoTokenIdentifier(); // declare + swapAstStack(); + consumePseudoTokens(); + + consumePseudoToken(":", 0, false); + consumePseudoTokens(); + + println(">>>>>>>>>>>>>>>>>>>>>>>declare header"); + display(); + } + + + protected void consumeInterTypeFieldDeclaration() { + // InterTypeFieldDeclaration ::= Modifiersopt Type OnType '.' JavaIdentifier InterTypeFieldBody ';' + println("about to consume field"); + this.display(); + // FieldDeclaration field = new FieldDeclaration(); + + Expression initialization = null; + if (expressionPtr >= 0) { + expressionLengthPtr--; + initialization = expressionStack[expressionPtr--]; + } + + long pos = identifierPositionStack[identifierPtr]; + int end = (int) pos; + int start = (int) (pos >>> 32); + char[] name = identifierStack[identifierPtr--]; + identifierLengthPtr--; + + // field.name = name; + // field.sourceStart = start; + // field.sourceEnd = end; + + TypeReference onType = getTypeReference(0); + TypeReference returnType = getTypeReference(0); + // field.type = returnType; + + this.display(); + + int dontKnowWhatThisIs = intStack[intPtr--]; + + int decSourceStart = intStack[intPtr--]; + int modifiers = intStack[intPtr--]; + + InterTypeFieldDeclaration dec = + new InterTypeFieldDeclaration( + this.compilationUnit.compilationResult, + onType); + + dec.returnType = returnType; + dec.sourceStart = start; + dec.sourceEnd = end; + dec.setSelector(name); + dec.declarationSourceStart = decSourceStart; + dec.setDeclaredModifiers(modifiers); + dec.setInitialization(initialization); + + pushOnAstStack(dec); + println("consumed field: " + dec); + this.display(); + } + + protected void consumeInterTypeMethodDeclaration(boolean isNotAbstract) { + consumeMethodDeclaration(isNotAbstract); + } + + protected void consumeInterTypeMethodHeader() { + consumeMethodHeader(); + } + + protected void consumeInterTypeConstructorDeclaration() { + consumeMethodDeclaration(true); + } + + protected void consumeInterTypeConstructorHeader() { + consumeMethodHeader(); + } + + protected void consumeInterTypeMethodHeaderName() { + //InterTypeMethodHeaderName ::= Modifiersopt Type OnType '.' JavaIdentifier '(' + this.display(); + InterTypeMethodDeclaration md = + new InterTypeMethodDeclaration( + this.compilationUnit.compilationResult, + null); + + //identifier + char[] name = identifierStack[identifierPtr]; + long selectorSource = identifierPositionStack[identifierPtr--]; + identifierLengthPtr--; + + //onType + md.onType = getTypeReference(0); + + //type + md.returnType = getTypeReference(intStack[intPtr--]); + + //modifiers + md.declarationSourceStart = intStack[intPtr--]; + md.setDeclaredModifiers(intStack[intPtr--]); + + //highlight starts at selector start + md.sourceStart = (int) (selectorSource >>> 32); + pushOnAstStack(md); + md.sourceEnd = lParenPos; + md.bodyStart = lParenPos + 1; + md.setSelector(name); + listLength = 0; + // initialize listLength before reading parameters/throws + + // recovery + if (currentElement != null) { + if (currentElement instanceof RecoveredType + //|| md.modifiers != 0 + || (scanner.getLineNumber(md.returnType.sourceStart) + == scanner.getLineNumber(md.sourceStart))) { + lastCheckPoint = md.bodyStart; + currentElement = currentElement.add(md, 0); + lastIgnoredToken = -1; + } else { + lastCheckPoint = md.sourceStart; + restartRecovery = true; + } + } + } + + protected void consumeInterTypeConstructorHeaderName() { + //InterTypeConstructorHeaderName ::= Modifiersopt Name '.' 'new' '(' + this.display(); + InterTypeConstructorDeclaration md = + new InterTypeConstructorDeclaration( + this.compilationUnit.compilationResult, + null); + + //identifier +// md.selector = identifierStack[identifierPtr]; +// long selectorSource = identifierPositionStack[identifierPtr--]; +//// identifierLengthPtr--; + + //onType + md.onType = getTypeReference(0); + + println("got onType: " + md.onType); + this.display(); + + intPtr--; // pop new info + //type + md.returnType = TypeReference.baseTypeReference(T_void, 0); //getTypeReference(intStack[intPtr--]); + + //modifiers + md.declarationSourceStart = intStack[intPtr--]; + md.setDeclaredModifiers(intStack[intPtr--]); + //md.modifiers = intStack[intPtr--]; + + //highlight starts at selector start + //md.sourceStart = (int) (selectorSource >>> 32); + md.sourceStart = md.onType.sourceStart; + pushOnAstStack(md); + md.sourceEnd = lParenPos; + md.bodyStart = lParenPos + 1; + listLength = 0; + // initialize listLength before reading parameters/throws + + md.setSelector( + (new String(CharOperation.concatWith(md.onType.getTypeName(), '_')) + "_new"). + toCharArray()); + + + // recovery + if (currentElement != null) { + if (currentElement instanceof RecoveredType + //|| md.modifiers != 0 + //|| (scanner.getLineNumber(md.returnType.sourceStart) + // == scanner.getLineNumber(md.sourceStart)) + ) { + //lastCheckPoint = md.bodyStart; + currentElement = currentElement.add(md, 0); + lastIgnoredToken = -1; + } else { + lastCheckPoint = md.sourceStart; + restartRecovery = true; + } + } + } + + + + +//********************************************************* + + + protected void consumePseudoToken(String value) { + consumePseudoToken(value, 0, false); + } + + protected void consumePseudoToken( + String value, + int popFromIntStack, + boolean isIdentifier) { + intPtr -= popFromIntStack; + + int start = currentTokenStart; + int end = start + value.length() - 1; + PseudoToken tok = new PseudoToken(this, value, isIdentifier); + tok.sourceStart = start; + tok.sourceEnd = end; + pushOnAstStack(tok); + } + + protected void consumePseudoTokenIdentifier() { + long pos = identifierPositionStack[identifierPtr]; + int end = (int) pos; + int start = (int) (pos >>> 32); + char[] name = identifierStack[identifierPtr--]; + identifierLengthPtr--; + + PseudoToken tok = new PseudoToken(this, new String(name), true); + tok.sourceStart = start; + tok.sourceEnd = end; + pushOnAstStack(tok); + } + + protected void consumePseudoTokenIf() { + //this.display(); + Expression expr = (Expression) expressionStack[expressionPtr--]; + expressionLengthPtr--; + println("expr: " + expr); + + int start = intStack[intPtr--]; + PseudoToken tok = new IfPseudoToken(this, expr); + tok.sourceStart = start; + tok.sourceEnd = this.rParenPos; + pushOnAstStack(tok); + } + + protected void consumePseudoTokenLiteral() { + Literal literal = (Literal) expressionStack[expressionPtr--]; + expressionLengthPtr--; + //System.out.println("literal: " + new String(literal.source())); + + PseudoToken tok = + new PseudoToken(this, new String(literal.source()), false); + tok.literalKind = "string"; + tok.sourceStart = literal.sourceStart; + tok.sourceEnd = literal.sourceEnd; + pushOnAstStack(tok); + } + + protected void consumePseudoTokenModifier() { + //int modifier = modifiers; + consumePseudoToken(Modifier.toString(modifiers), 0, true); + modifiers = AccDefault; + } + + protected void consumePseudoTokenPrimitiveType() { + TypeReference type = getTypeReference(0); + + PseudoToken tok = new PseudoToken(this, type.toString(), true); + tok.sourceStart = type.sourceStart; + tok.sourceEnd = type.sourceEnd; + pushOnAstStack(tok); + } + + protected void consumePseudoTokens() { + optimizedConcatNodeLists(); + } + +// Helpers + + protected PointcutDesignator popPointcutDesignator(String terminator) { + PseudoTokens tokens = popPseudoTokens(terminator); + return new PointcutDesignator(this, tokens); + } + + protected PseudoTokens popPseudoTokens(String terminator) { + consumePseudoToken(terminator); + consumePseudoTokens(); + //System.out.println("next token is: " + new String(scanner.getCurrentTokenSource())); + + int length = astLengthStack[astLengthPtr--]; + astPtr -= length; + + //arguments + PseudoToken[] tokens = new PseudoToken[length]; + System.arraycopy(astStack, astPtr + 1, tokens, 0, length); + //md.bodyStart = rParenPos+1; + listLength = 0; // reset listLength after having read all parameters + + return new PseudoTokens(tokens, makeSourceContext(this.compilationUnit.compilationResult())); + } + + private ISourceContext makeSourceContext(CompilationResult compilationResult) { + return new EclipseSourceContext(compilationResult); + } + + + private void swapAstStack() { + AstNode top = astStack[astPtr]; + AstNode next = astStack[astPtr-1]; + astStack[astPtr] = next; + astStack[astPtr-1] = top; + } + + + + // This method is part of an automatic generation : do NOT edit-modify + // This method is part of an automatic generation : do NOT edit-modify +protected void consumeRule(int act) { + switch ( act ) { + case 33 : // System.out.println("Type ::= PrimitiveType"); + consumePrimitiveType(); + break ; + + case 47 : // System.out.println("ReferenceType ::= ClassOrInterfaceType"); + consumeReferenceType(); + break ; + + case 65 : // System.out.println("AjQualifiedName ::= AjName DOT SimpleName"); + consumeQualifiedName(); + break ; + + case 69 : // System.out.println("QualifiedName ::= Name DOT JavaIdentifier"); + consumeQualifiedName(); + break ; + + case 70 : // System.out.println("CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt"); + consumeCompilationUnit(); + break ; + + case 71 : // System.out.println("EnterCompilationUnit ::="); + consumeEnterCompilationUnit(); + break ; + + case 83 : // System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN LBRACE"); + consumeCatchHeader(); + break ; + + case 85 : // System.out.println("ImportDeclarations ::= ImportDeclarations ImportDeclaration"); + consumeImportDeclarations(); + break ; + + case 87 : // System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); + consumeTypeDeclarations(); + break ; + + case 88 : // System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); + consumePackageDeclaration(); + break ; + + case 89 : // System.out.println("PackageDeclarationName ::= package Name"); + consumePackageDeclarationName(); + break ; + + case 92 : // System.out.println("SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName SEMICOLON"); + consumeSingleTypeImportDeclaration(); + break ; + + case 93 : // System.out.println("SingleTypeImportDeclarationName ::= import Name"); + consumeSingleTypeImportDeclarationName(); + break ; + + case 94 : // System.out.println("TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName SEMICOLON"); + consumeTypeImportOnDemandDeclaration(); + break ; + + case 95 : // System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT MULTIPLY"); + consumeTypeImportOnDemandDeclarationName(); + break ; + + case 98 : // System.out.println("TypeDeclaration ::= SEMICOLON"); + consumeEmptyTypeDeclaration(); + break ; + + case 124 : // System.out.println("AspectDeclaration ::= AspectHeader AspectBody"); + consumeAspectDeclaration(); + break ; + + case 125 : // System.out.println("AspectHeader ::= AspectHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt..."); + consumeAspectHeader(); + break ; + + case 126 : // System.out.println("AspectHeaderName ::= Modifiersopt aspect Identifier"); + consumeAspectHeaderName(false); + break ; + + case 127 : // System.out.println("AspectHeaderName ::= Modifiersopt privileged Modifiersopt aspect Identifier"); + consumeAspectHeaderName(true); + break ; + + case 129 : // System.out.println("AspectHeaderRest ::= AspectHeaderRestStart PseudoTokens"); + consumeAspectHeaderRest(); + break ; + + case 130 : // System.out.println("AspectHeaderRestStart ::= Identifier"); + consumePseudoTokenIdentifier(); + break ; + + case 133 : // System.out.println("AspectBodyDeclarations ::= AspectBodyDeclarations AspectBodyDeclaration"); + consumeClassBodyDeclarations(); + break ; + + case 134 : // System.out.println("AspectBodyDeclarationsopt ::="); + consumeEmptyClassBodyDeclarationsopt(); + break ; + + case 135 : // System.out.println("AspectBodyDeclarationsopt ::= NestedType AspectBodyDeclarations"); + consumeClassBodyDeclarationsopt(); + break ; + + case 136 : // System.out.println("AspectBodyDeclaration ::= ClassBodyDeclaration"); + consumeClassBodyDeclarationInAspect(); + break ; + + case 137 : // System.out.println("PointcutDeclaration ::= PointcutHeader MethodHeaderParameters SEMICOLON"); + consumeEmptyPointcutDeclaration(); + break ; + + case 138 : // System.out.println("PointcutDeclaration ::= PointcutHeader MethodHeaderParameters COLON PseudoTokens..."); + consumePointcutDeclaration(); + break ; + + case 139 : // System.out.println("PointcutHeader ::= Modifiersopt pointcut JavaIdentifier LPAREN"); + consumePointcutHeader(); + break ; + + case 142 : // System.out.println("AroundDeclaration ::= AroundHeader MethodBody"); + consumeAroundDeclaration(); + break ; + + case 143 : // System.out.println("AroundHeader ::= AroundHeaderName MethodHeaderParameters..."); + consumeAroundHeader(); + break ; + + case 144 : // System.out.println("AroundHeaderName ::= Modifiersopt Type around LPAREN"); + consumeAroundHeaderName(); + break ; + + case 145 : // System.out.println("BasicAdviceDeclaration ::= BasicAdviceHeader MethodBody"); + consumeBasicAdviceDeclaration(); + break ; + + case 146 : // System.out.println("BasicAdviceHeader ::= BasicAdviceHeaderName MethodHeaderParameters ExtraParamopt..."); + consumeBasicAdviceHeader(); + break ; + + case 147 : // System.out.println("BasicAdviceHeaderName ::= Modifiersopt before LPAREN"); + consumeBasicAdviceHeaderName(false); + break ; + + case 148 : // System.out.println("BasicAdviceHeaderName ::= Modifiersopt after LPAREN"); + consumeBasicAdviceHeaderName(true); + break ; + + case 149 : // System.out.println("ExtraParamopt ::= Identifier LPAREN FormalParameter RPAREN"); + consumeExtraParameterWithFormal(); + break ; + + case 150 : // System.out.println("ExtraParamopt ::= Identifier LPAREN RPAREN"); + consumeExtraParameterNoFormal(); + break ; + + case 151 : // System.out.println("ExtraParamopt ::= Identifier"); + consumeExtraParameterNoFormal(); + break ; + + case 154 : // System.out.println("OnType ::= OnType DOT JavaIdentifier"); + consumeQualifiedName(); + break ; + + case 159 : // System.out.println("InterTypeMethodDeclaration ::= InterTypeMethodHeader MethodBody"); + // set to true to consume a method with a body + consumeInterTypeMethodDeclaration(true); + break ; + + case 160 : // System.out.println("InterTypeMethodHeader ::= InterTypeMethodHeaderName MethodHeaderParameters..."); + consumeInterTypeMethodHeader(); + break ; + + case 161 : // System.out.println("InterTypeMethodHeaderName ::= Modifiersopt Type OnType DOT JavaIdentifier LPAREN"); + consumeInterTypeMethodHeaderName(); + break ; + + case 162 : // System.out.println("AbstractInterTypeMethodDeclaration ::= InterTypeMethodHeader SEMICOLON"); + // set to false to consume a method without body + consumeInterTypeMethodDeclaration(false); + break ; + + case 163 : // System.out.println("InterTypeConstructorDeclaration ::= InterTypeConstructorHeader ConstructorBody"); + // set to true to consume a method with a body + consumeInterTypeConstructorDeclaration(); + break ; + + case 164 : // System.out.println("InterTypeConstructorHeader ::= InterTypeConstructorHeaderName..."); + consumeInterTypeConstructorHeader(); + break ; + + case 165 : // System.out.println("InterTypeConstructorHeaderName ::= Modifiersopt Name DOT new LPAREN"); + consumeInterTypeConstructorHeaderName(); + break ; + + case 166 : // System.out.println("InterTypeFieldDeclaration ::= Modifiersopt Type OnType DOT JavaIdentifier..."); + consumeInterTypeFieldDeclaration(); + break ; + + case 170 : // System.out.println("DeclareDeclaration ::= DeclareHeader PseudoTokens SEMICOLON"); + consumeDeclareDeclaration(); + break ; + + case 171 : // System.out.println("DeclareHeader ::= declare Identifier COLON"); + consumeDeclareHeader(); + break ; + + case 173 : // System.out.println("PseudoTokens ::= PseudoTokens PseudoToken"); + consumePseudoTokens(); + break ; + + case 174 : // System.out.println("PseudoToken ::= JavaIdentifier"); + consumePseudoTokenIdentifier(); + break ; + + case 175 : // System.out.println("PseudoToken ::= LPAREN"); + consumePseudoToken("("); + break ; + + case 176 : // System.out.println("PseudoToken ::= RPAREN"); + consumePseudoToken(")"); + break ; + + case 177 : // System.out.println("PseudoToken ::= DOT"); + consumePseudoToken("."); + break ; + + case 178 : // System.out.println("PseudoToken ::= MULTIPLY"); + consumePseudoToken("*"); + break ; + + case 179 : // System.out.println("PseudoToken ::= PLUS"); + consumePseudoToken("+"); + break ; + + case 180 : // System.out.println("PseudoToken ::= AND_AND"); + consumePseudoToken("&&"); + break ; + + case 181 : // System.out.println("PseudoToken ::= OR_OR"); + consumePseudoToken("||"); + break ; + + case 182 : // System.out.println("PseudoToken ::= NOT"); + consumePseudoToken("!"); + break ; + + case 183 : // System.out.println("PseudoToken ::= COLON"); + consumePseudoToken(":"); + break ; + + case 184 : // System.out.println("PseudoToken ::= COMMA"); + consumePseudoToken(","); + break ; + + case 185 : // System.out.println("PseudoToken ::= LBRACKET"); + consumePseudoToken("["); + break ; + + case 186 : // System.out.println("PseudoToken ::= RBRACKET"); + consumePseudoToken("]"); + break ; + + case 187 : // System.out.println("PseudoToken ::= PrimitiveType"); + consumePseudoTokenPrimitiveType(); + break ; + + case 188 : // System.out.println("PseudoToken ::= Modifier"); + consumePseudoTokenModifier(); + break ; + + case 189 : // System.out.println("PseudoToken ::= Literal"); + consumePseudoTokenLiteral(); + break ; + + case 190 : // System.out.println("PseudoToken ::= this"); + consumePseudoToken("this", 1, true); + break ; + + case 191 : // System.out.println("PseudoToken ::= super"); + consumePseudoToken("super", 1, true); + break ; + + case 192 : // System.out.println("PseudoToken ::= if LPAREN Expression RPAREN"); + consumePseudoTokenIf(); + break ; + + case 193 : // System.out.println("PseudoToken ::= assert"); + consumePseudoToken("assert", 1, true); + break ; + + case 194 : // System.out.println("PseudoToken ::= import"); + consumePseudoToken("import", 1, true); + break ; + + case 195 : // System.out.println("PseudoToken ::= package"); + consumePseudoToken("package", 1, true); + break ; + + case 196 : // System.out.println("PseudoToken ::= throw"); + consumePseudoToken("throw", 1, true); + break ; + + case 197 : // System.out.println("PseudoToken ::= new"); + consumePseudoToken("new", 1, true); + break ; + + case 198 : // System.out.println("PseudoToken ::= do"); + consumePseudoToken("do", 1, true); + break ; + + case 199 : // System.out.println("PseudoToken ::= for"); + consumePseudoToken("for", 1, true); + break ; + + case 200 : // System.out.println("PseudoToken ::= switch"); + consumePseudoToken("switch", 1, true); + break ; + + case 201 : // System.out.println("PseudoToken ::= try"); + consumePseudoToken("try", 1, true); + break ; + + case 202 : // System.out.println("PseudoToken ::= while"); + consumePseudoToken("while", 1, true); + break ; + + case 203 : // System.out.println("PseudoToken ::= break"); + consumePseudoToken("break", 1, true); + break ; + + case 204 : // System.out.println("PseudoToken ::= continue"); + consumePseudoToken("continue", 1, true); + break ; + + case 205 : // System.out.println("PseudoToken ::= return"); + consumePseudoToken("return", 1, true); + break ; + + case 206 : // System.out.println("PseudoToken ::= case"); + consumePseudoToken("case", 1, true); + break ; + + case 207 : // System.out.println("PseudoToken ::= catch"); + consumePseudoToken("catch", 0, true); + break ; + + case 208 : // System.out.println("PseudoToken ::= instanceof"); + consumePseudoToken("instanceof", 0, true); + break ; + + case 209 : // System.out.println("PseudoToken ::= else"); + consumePseudoToken("else", 0, true); + break ; + + case 210 : // System.out.println("PseudoToken ::= extends"); + consumePseudoToken("extends", 0, true); + break ; + + case 211 : // System.out.println("PseudoToken ::= finally"); + consumePseudoToken("finally", 0, true); + break ; + + case 212 : // System.out.println("PseudoToken ::= implements"); + consumePseudoToken("implements", 0, true); + break ; + + case 213 : // System.out.println("PseudoToken ::= throws"); + consumePseudoToken("throws", 0, true); + break ; + + case 214 : // System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); + consumeClassDeclaration(); + break ; + + case 215 : // System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt"); + consumeClassHeader(); + break ; + + case 216 : // System.out.println("ClassHeaderName ::= Modifiersopt class JavaIdentifier"); + consumeClassHeaderName(); + break ; + + case 217 : // System.out.println("ClassHeaderExtends ::= extends ClassType"); + consumeClassHeaderExtends(); + break ; + + case 218 : // System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); + consumeClassHeaderImplements(); + break ; + + case 220 : // System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA InterfaceType"); + consumeInterfaceTypeList(); + break ; + + case 221 : // System.out.println("InterfaceType ::= ClassOrInterfaceType"); + consumeInterfaceType(); + break ; + + case 224 : // System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration"); + consumeClassBodyDeclarations(); + break ; + + case 228 : // System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block"); + consumeClassBodyDeclaration(); + break ; + + case 229 : // System.out.println("Diet ::="); + consumeDiet(); + break ; + + case 230 : // System.out.println("Initializer ::= Diet NestedMethod Block"); + consumeClassBodyDeclaration(); + break ; + + case 237 : // System.out.println("ClassMemberDeclaration ::= SEMICOLON"); + consumeEmptyClassMemberDeclaration(); + break ; + + case 238 : // System.out.println("FieldDeclaration ::= Modifiersopt Type VariableDeclarators SEMICOLON"); + consumeFieldDeclaration(); + break ; + + case 240 : // System.out.println("VariableDeclarators ::= VariableDeclarators COMMA VariableDeclarator"); + consumeVariableDeclarators(); + break ; + + case 243 : // System.out.println("EnterVariable ::="); + consumeEnterVariable(); + break ; + + case 244 : // System.out.println("ExitVariableWithInitialization ::="); + consumeExitVariableWithInitialization(); + break ; + + case 245 : // System.out.println("ExitVariableWithoutInitialization ::="); + consumeExitVariableWithoutInitialization(); + break ; + + case 246 : // System.out.println("ForceNoDiet ::="); + consumeForceNoDiet(); + break ; + + case 247 : // System.out.println("RestoreDiet ::="); + consumeRestoreDiet(); + break ; + + case 252 : // System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); + // set to true to consume a method with a body + consumeMethodDeclaration(true); + break ; + + case 253 : // System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); + // set to false to consume a method without body + consumeMethodDeclaration(false); + break ; + + case 254 : // System.out.println("MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims"); + consumeMethodHeader(); + break ; + + case 255 : // System.out.println("MethodPushModifiersHeader ::= MethodPushModifiersHeaderName MethodHeaderParameters"); + consumeMethodHeader(); + break ; + + case 256 : // System.out.println("MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers..."); + consumeMethodPushModifiersHeaderName(); + break ; + + case 257 : // System.out.println("MethodPushModifiersHeaderName ::= Type PushModifiers JavaIdentifierNoAround LPAREN"); + consumeMethodPushModifiersHeaderName(); + break ; + + case 258 : // System.out.println("MethodHeaderName ::= Modifiersopt Type JavaIdentifierNoAround LPAREN"); + consumeMethodHeaderName(); + break ; + + case 259 : // System.out.println("MethodHeaderParameters ::= FormalParameterListopt RPAREN"); + consumeMethodHeaderParameters(); + break ; + + case 260 : // System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); + consumeMethodHeaderExtendedDims(); + break ; + + case 261 : // System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); + consumeMethodHeaderThrowsClause(); + break ; + + case 262 : // System.out.println("ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters..."); + consumeConstructorHeader(); + break ; + + case 263 : // System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); + consumeConstructorHeaderName(); + break ; + + case 264 : // System.out.println("ConstructorHeaderName ::= Modifiersopt aspect LPAREN"); + consumeConstructorHeaderName(); + break ; + + case 266 : // System.out.println("FormalParameterList ::= FormalParameterList COMMA FormalParameter"); + consumeFormalParameterList(); + break ; + + case 267 : // System.out.println("FormalParameter ::= Modifiersopt Type VariableDeclaratorId"); + // the boolean is used to know if the modifiers should be reset + consumeFormalParameter(); + break ; + + case 269 : // System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); + consumeClassTypeList(); + break ; + + case 270 : // System.out.println("ClassTypeElt ::= ClassType"); + consumeClassTypeElt(); + break ; + + case 271 : // System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt RBRACE"); + consumeMethodBody(); + break ; + + case 272 : // System.out.println("NestedMethod ::="); + consumeNestedMethod(); + break ; + + case 273 : // System.out.println("StaticInitializer ::= StaticOnly Block"); + consumeStaticInitializer(); + break ; + + case 274 : // System.out.println("StaticOnly ::= static"); + consumeStaticOnly(); + break ; + + case 275 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader ConstructorBody"); + consumeConstructorDeclaration() ; + break ; + + case 276 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); + consumeInvalidConstructorDeclaration() ; + break ; + + case 277 : // System.out.println("ConstructorBody ::= NestedMethod LBRACE ConstructorBlockStatementsopt RBRACE"); + consumeConstructorBody(); + break ; + + case 280 : // System.out.println("ConstructorBlockStatementsopt ::= ExplicitConstructorInvocation BlockStatements"); + consumeConstructorBlockStatements(); + break ; + + case 281 : // System.out.println("ExplicitConstructorInvocation ::= this LPAREN ArgumentListopt RPAREN SEMICOLON"); + consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This); + break ; + + case 282 : // System.out.println("ExplicitConstructorInvocation ::= super LPAREN ArgumentListopt RPAREN SEMICOLON"); + consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super); + break ; + + case 283 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT super LPAREN ArgumentListopt RPAREN"); + consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super); + break ; + + case 284 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN ArgumentListopt RPAREN..."); + consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super); + break ; + + case 285 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT this LPAREN ArgumentListopt RPAREN..."); + consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This); + break ; + + case 286 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN ArgumentListopt RPAREN..."); + consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This); + break ; + + case 287 : // System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); + consumeInterfaceDeclaration(); + break ; + + case 288 : // System.out.println("InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt"); + consumeInterfaceHeader(); + break ; + + case 289 : // System.out.println("InterfaceHeaderName ::= Modifiersopt interface JavaIdentifier"); + consumeInterfaceHeaderName(); + break ; + + case 291 : // System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); + consumeInterfaceHeaderExtends(); + break ; + + case 294 : // System.out.println("InterfaceMemberDeclarations ::= InterfaceMemberDeclarations..."); + consumeInterfaceMemberDeclarations(); + break ; + + case 295 : // System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); + consumeEmptyInterfaceMemberDeclaration(); + break ; + + case 298 : // System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration"); + ignoreMethodBody(); + break ; + + case 299 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody"); + ignoreInvalidConstructorDeclaration(true); + break ; + + case 300 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader SEMICOLON"); + ignoreInvalidConstructorDeclaration(false); + break ; + + case 306 : // System.out.println("ArrayInitializer ::= LBRACE ,opt RBRACE"); + consumeEmptyArrayInitializer(); + break ; + + case 307 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers RBRACE"); + consumeArrayInitializer(); + break ; + + case 308 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers COMMA RBRACE"); + consumeArrayInitializer(); + break ; + + case 310 : // System.out.println("VariableInitializers ::= VariableInitializers COMMA VariableInitializer"); + consumeVariableInitializers(); + break ; + + case 311 : // System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); + consumeBlock(); + break ; + + case 312 : // System.out.println("OpenBlock ::="); + consumeOpenBlock() ; + break ; + + case 314 : // System.out.println("BlockStatements ::= BlockStatements BlockStatement"); + consumeBlockStatements() ; + break ; + + case 318 : // System.out.println("BlockStatement ::= InvalidInterfaceDeclaration"); + ignoreInterfaceDeclaration(); + break ; + + case 319 : // System.out.println("LocalVariableDeclarationStatement ::= LocalVariableDeclaration SEMICOLON"); + consumeLocalVariableDeclarationStatement(); + break ; + + case 320 : // System.out.println("LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators"); + consumeLocalVariableDeclaration(); + break ; + + case 321 : // System.out.println("LocalVariableDeclaration ::= Modifiers Type PushModifiers VariableDeclarators"); + consumeLocalVariableDeclaration(); + break ; + + case 322 : // System.out.println("PushModifiers ::="); + consumePushModifiers(); + break ; + + case 346 : // System.out.println("EmptyStatement ::= SEMICOLON"); + consumeEmptyStatement(); + break ; + + case 347 : // System.out.println("LabeledStatement ::= JavaIdentifier COLON Statement"); + consumeStatementLabel() ; + break ; + + case 348 : // System.out.println("LabeledStatementNoShortIf ::= JavaIdentifier COLON StatementNoShortIf"); + consumeStatementLabel() ; + break ; + + case 349 : // System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); + consumeExpressionStatement(); + break ; + + case 357 : // System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN Statement"); + consumeStatementIfNoElse(); + break ; + + case 358 : // System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN StatementNoShortIf else..."); + consumeStatementIfWithElse(); + break ; + + case 359 : // System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression RPAREN StatementNoShortIf..."); + consumeStatementIfWithElse(); + break ; + + case 360 : // System.out.println("SwitchStatement ::= switch OpenBlock LPAREN Expression RPAREN SwitchBlock"); + consumeStatementSwitch() ; + break ; + + case 361 : // System.out.println("SwitchBlock ::= LBRACE RBRACE"); + consumeEmptySwitchBlock() ; + break ; + + case 364 : // System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements SwitchLabels RBRACE"); + consumeSwitchBlock() ; + break ; + + case 366 : // System.out.println("SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement"); + consumeSwitchBlockStatements() ; + break ; + + case 367 : // System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); + consumeSwitchBlockStatement() ; + break ; + + case 369 : // System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); + consumeSwitchLabels() ; + break ; + + case 370 : // System.out.println("SwitchLabel ::= case ConstantExpression COLON"); + consumeCaseLabel(); + break ; + + case 371 : // System.out.println("SwitchLabel ::= default COLON"); + consumeDefaultLabel(); + break ; + + case 372 : // System.out.println("WhileStatement ::= while LPAREN Expression RPAREN Statement"); + consumeStatementWhile() ; + break ; + + case 373 : // System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression RPAREN StatementNoShortIf"); + consumeStatementWhile() ; + break ; + + case 374 : // System.out.println("DoStatement ::= do Statement while LPAREN Expression RPAREN SEMICOLON"); + consumeStatementDo() ; + break ; + + case 375 : // System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON Expressionopt SEMICOLON..."); + consumeStatementFor() ; + break ; + + case 376 : // System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt SEMICOLON Expressionopt SEMICOLON"); + consumeStatementFor() ; + break ; + + case 377 : // System.out.println("ForInit ::= StatementExpressionList"); + consumeForInit() ; + break ; + + case 381 : // System.out.println("StatementExpressionList ::= StatementExpressionList COMMA StatementExpression"); + consumeStatementExpressionList() ; + break ; + + case 382 : // System.out.println("AssertStatement ::= assert Expression SEMICOLON"); + consumeSimpleAssertStatement() ; + break ; + + case 383 : // System.out.println("AssertStatement ::= assert Expression COLON Expression SEMICOLON"); + consumeAssertStatement() ; + break ; + + case 384 : // System.out.println("BreakStatement ::= break SEMICOLON"); + consumeStatementBreak() ; + break ; + + case 385 : // System.out.println("BreakStatement ::= break Identifier SEMICOLON"); + consumeStatementBreakWithLabel() ; + break ; + + case 386 : // System.out.println("ContinueStatement ::= continue SEMICOLON"); + consumeStatementContinue() ; + break ; + + case 387 : // System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); + consumeStatementContinueWithLabel() ; + break ; + + case 388 : // System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); + consumeStatementReturn() ; + break ; + + case 389 : // System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); + consumeStatementThrow(); + + break ; + + case 390 : // System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN Expression RPAREN Block"); + consumeStatementSynchronized(); + break ; + + case 391 : // System.out.println("OnlySynchronized ::= synchronized"); + consumeOnlySynchronized(); + break ; + + case 392 : // System.out.println("TryStatement ::= try Block Catches"); + consumeStatementTry(false); + break ; + + case 393 : // System.out.println("TryStatement ::= try Block Catchesopt Finally"); + consumeStatementTry(true); + break ; + + case 395 : // System.out.println("Catches ::= Catches CatchClause"); + consumeCatches(); + break ; + + case 396 : // System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN Block"); + consumeStatementCatch() ; + break ; + + case 398 : // System.out.println("PushLPAREN ::= LPAREN"); + consumeLeftParen(); + break ; + + case 399 : // System.out.println("PushRPAREN ::= RPAREN"); + consumeRightParen(); + break ; + + case 403 : // System.out.println("PrimaryNoNewArray ::= this"); + consumePrimaryNoNewArrayThis(); + break ; + + case 404 : // System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN"); + consumePrimaryNoNewArray(); + break ; + + case 407 : // System.out.println("PrimaryNoNewArray ::= Name DOT this"); + consumePrimaryNoNewArrayNameThis(); + break ; + + case 408 : // System.out.println("PrimaryNoNewArray ::= Name DOT super"); + consumePrimaryNoNewArrayNameSuper(); + break ; + + case 409 : // System.out.println("PrimaryNoNewArray ::= Name DOT class"); + consumePrimaryNoNewArrayName(); + break ; + + case 410 : // System.out.println("PrimaryNoNewArray ::= ArrayType DOT class"); + consumePrimaryNoNewArrayArrayType(); + break ; + + case 411 : // System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); + consumePrimaryNoNewArrayPrimitiveType(); + break ; + + case 414 : // System.out.println("AllocationHeader ::= new ClassType LPAREN ArgumentListopt RPAREN"); + consumeAllocationHeader(); + break ; + + case 415 : // System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN ArgumentListopt RPAREN..."); + consumeClassInstanceCreationExpression(); + break ; + + case 416 : // System.out.println("ClassInstanceCreationExpression ::= Primary DOT new SimpleName LPAREN..."); + consumeClassInstanceCreationExpressionQualified() ; + break ; + + case 417 : // System.out.println("ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName new..."); + consumeClassInstanceCreationExpressionQualified() ; + break ; + + case 418 : // System.out.println("ClassInstanceCreationExpressionName ::= Name DOT"); + consumeClassInstanceCreationExpressionName() ; + break ; + + case 419 : // System.out.println("ClassBodyopt ::="); + consumeClassBodyopt(); + break ; + + case 421 : // System.out.println("EnterAnonymousClassBody ::="); + consumeEnterAnonymousClassBody(); + break ; + + case 423 : // System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); + consumeArgumentList(); + break ; + + case 424 : // System.out.println("ArrayCreationExpression ::= new PrimitiveType DimWithOrWithOutExprs..."); + consumeArrayCreationExpression(); + break ; + + case 425 : // System.out.println("ArrayCreationExpression ::= new ClassOrInterfaceType DimWithOrWithOutExprs..."); + consumeArrayCreationExpression(); + break ; + + case 427 : // System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr"); + consumeDimWithOrWithOutExprs(); + break ; + + case 429 : // System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET"); + consumeDimWithOrWithOutExpr(); + break ; + + case 430 : // System.out.println("Dims ::= DimsLoop"); + consumeDims(); + break ; + + case 433 : // System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); + consumeOneDimLoop(); + break ; + + case 434 : // System.out.println("FieldAccess ::= Primary DOT JavaIdentifier"); + consumeFieldAccess(false); + break ; + + case 435 : // System.out.println("FieldAccess ::= super DOT JavaIdentifier"); + consumeFieldAccess(true); + break ; + + case 436 : // System.out.println("MethodInvocation ::= NameOrAj LPAREN ArgumentListopt RPAREN"); + consumeMethodInvocationName(); + break ; + + case 437 : // System.out.println("MethodInvocation ::= Primary DOT JavaIdentifier LPAREN ArgumentListopt RPAREN"); + consumeMethodInvocationPrimary(); + break ; + + case 438 : // System.out.println("MethodInvocation ::= super DOT JavaIdentifier LPAREN ArgumentListopt RPAREN"); + consumeMethodInvocationSuper(); + break ; + + case 439 : // System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); + consumeArrayAccess(true); + break ; + + case 440 : // System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression RBRACKET"); + consumeArrayAccess(false); + break ; + + case 442 : // System.out.println("PostfixExpression ::= NameOrAj"); + consumePostfixExpression(); + break ; + + case 445 : // System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); + consumeUnaryExpression(OperatorExpression.PLUS,true); + break ; + + case 446 : // System.out.println("PostDecrementExpression ::= PostfixExpression MINUS_MINUS"); + consumeUnaryExpression(OperatorExpression.MINUS,true); + break ; + + case 447 : // System.out.println("PushPosition ::="); + consumePushPosition(); + break ; + + case 450 : // System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); + consumeUnaryExpression(OperatorExpression.PLUS); + break ; + + case 451 : // System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); + consumeUnaryExpression(OperatorExpression.MINUS); + break ; + + case 453 : // System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition UnaryExpression"); + consumeUnaryExpression(OperatorExpression.PLUS,false); + break ; + + case 454 : // System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition UnaryExpression"); + consumeUnaryExpression(OperatorExpression.MINUS,false); + break ; + + case 456 : // System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition UnaryExpression"); + consumeUnaryExpression(OperatorExpression.TWIDDLE); + break ; + + case 457 : // System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition UnaryExpression"); + consumeUnaryExpression(OperatorExpression.NOT); + break ; + + case 459 : // System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN UnaryExpression"); + consumeCastExpression(); + break ; + + case 460 : // System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN UnaryExpressionNotPlusMinus"); + consumeCastExpression(); + break ; + + case 461 : // System.out.println("CastExpression ::= PushLPAREN Expression PushRPAREN UnaryExpressionNotPlusMinus"); + consumeCastExpressionLL1(); + break ; + + case 463 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression MULTIPLY UnaryExpression"); + consumeBinaryExpression(OperatorExpression.MULTIPLY); + break ; + + case 464 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression DIVIDE UnaryExpression"); + consumeBinaryExpression(OperatorExpression.DIVIDE); + break ; + + case 465 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression REMAINDER UnaryExpression"); + consumeBinaryExpression(OperatorExpression.REMAINDER); + break ; + + case 467 : // System.out.println("AdditiveExpression ::= AdditiveExpression PLUS MultiplicativeExpression"); + consumeBinaryExpression(OperatorExpression.PLUS); + break ; + + case 468 : // System.out.println("AdditiveExpression ::= AdditiveExpression MINUS MultiplicativeExpression"); + consumeBinaryExpression(OperatorExpression.MINUS); + break ; + + case 470 : // System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT AdditiveExpression"); + consumeBinaryExpression(OperatorExpression.LEFT_SHIFT); + break ; + + case 471 : // System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT AdditiveExpression"); + consumeBinaryExpression(OperatorExpression.RIGHT_SHIFT); + break ; + + case 472 : // System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT AdditiveExpression"); + consumeBinaryExpression(OperatorExpression.UNSIGNED_RIGHT_SHIFT); + break ; + + case 474 : // System.out.println("RelationalExpression ::= RelationalExpression LESS ShiftExpression"); + consumeBinaryExpression(OperatorExpression.LESS); + break ; + + case 475 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER ShiftExpression"); + consumeBinaryExpression(OperatorExpression.GREATER); + break ; + + case 476 : // System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL ShiftExpression"); + consumeBinaryExpression(OperatorExpression.LESS_EQUAL); + break ; + + case 477 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER_EQUAL ShiftExpression"); + consumeBinaryExpression(OperatorExpression.GREATER_EQUAL); + break ; + + case 478 : // System.out.println("RelationalExpression ::= RelationalExpression instanceof ReferenceType"); + consumeInstanceOfExpression(OperatorExpression.INSTANCEOF); + break ; + + case 480 : // System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL RelationalExpression"); + consumeEqualityExpression(OperatorExpression.EQUAL_EQUAL); + break ; + + case 481 : // System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL RelationalExpression"); + consumeEqualityExpression(OperatorExpression.NOT_EQUAL); + break ; + + case 483 : // System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); + consumeBinaryExpression(OperatorExpression.AND); + break ; + + case 485 : // System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR AndExpression"); + consumeBinaryExpression(OperatorExpression.XOR); + break ; + + case 487 : // System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR ExclusiveOrExpression"); + consumeBinaryExpression(OperatorExpression.OR); + break ; + + case 489 : // System.out.println("ConditionalAndExpression ::= ConditionalAndExpression AND_AND InclusiveOrExpression"); + consumeBinaryExpression(OperatorExpression.AND_AND); + break ; + + case 491 : // System.out.println("ConditionalOrExpression ::= ConditionalOrExpression OR_OR ConditionalAndExpression"); + consumeBinaryExpression(OperatorExpression.OR_OR); + break ; + + case 493 : // System.out.println("ConditionalExpression ::= ConditionalOrExpression QUESTION Expression COLON..."); + consumeConditionalExpression(OperatorExpression.QUESTIONCOLON) ; + break ; + + case 496 : // System.out.println("Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression"); + consumeAssignment(); + break ; + + case 498 : // System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); + ignoreExpressionAssignment(); + break ; + + case 499 : // System.out.println("LeftHandSide ::= NameOrAj"); + consumeLeftHandSide(); + break ; + + case 502 : // System.out.println("AssignmentOperator ::= EQUAL"); + consumeAssignmentOperator(EQUAL); + break ; + + case 503 : // System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); + consumeAssignmentOperator(MULTIPLY); + break ; + + case 504 : // System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); + consumeAssignmentOperator(DIVIDE); + break ; + + case 505 : // System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); + consumeAssignmentOperator(REMAINDER); + break ; + + case 506 : // System.out.println("AssignmentOperator ::= PLUS_EQUAL"); + consumeAssignmentOperator(PLUS); + break ; + + case 507 : // System.out.println("AssignmentOperator ::= MINUS_EQUAL"); + consumeAssignmentOperator(MINUS); + break ; + + case 508 : // System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); + consumeAssignmentOperator(LEFT_SHIFT); + break ; + + case 509 : // System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); + consumeAssignmentOperator(RIGHT_SHIFT); + break ; + + case 510 : // System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); + consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT); + break ; + + case 511 : // System.out.println("AssignmentOperator ::= AND_EQUAL"); + consumeAssignmentOperator(AND); + break ; + + case 512 : // System.out.println("AssignmentOperator ::= XOR_EQUAL"); + consumeAssignmentOperator(XOR); + break ; + + case 513 : // System.out.println("AssignmentOperator ::= OR_EQUAL"); + consumeAssignmentOperator(OR); + break ; + + case 520 : // System.out.println("Expressionopt ::="); + consumeEmptyExpression(); + break ; + + case 524 : // System.out.println("ImportDeclarationsopt ::="); + consumeEmptyImportDeclarationsopt(); + break ; + + case 525 : // System.out.println("ImportDeclarationsopt ::= ImportDeclarations"); + consumeImportDeclarationsopt(); + break ; + + case 526 : // System.out.println("TypeDeclarationsopt ::="); + consumeEmptyTypeDeclarationsopt(); + break ; + + case 527 : // System.out.println("TypeDeclarationsopt ::= TypeDeclarations"); + consumeTypeDeclarationsopt(); + break ; + + case 528 : // System.out.println("ClassBodyDeclarationsopt ::="); + consumeEmptyClassBodyDeclarationsopt(); + break ; + + case 529 : // System.out.println("ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations"); + consumeClassBodyDeclarationsopt(); + break ; + + case 530 : // System.out.println("Modifiersopt ::="); + consumeDefaultModifiers(); + break ; + + case 531 : // System.out.println("Modifiersopt ::= Modifiers"); + consumeModifiers(); + break ; + + case 532 : // System.out.println("BlockStatementsopt ::="); + consumeEmptyBlockStatementsopt(); + break ; + + case 534 : // System.out.println("Dimsopt ::="); + consumeEmptyDimsopt(); + break ; + + case 536 : // System.out.println("ArgumentListopt ::="); + consumeEmptyArgumentListopt(); + break ; + + case 540 : // System.out.println("FormalParameterListopt ::="); + consumeFormalParameterListopt(); + break ; + + case 544 : // System.out.println("InterfaceMemberDeclarationsopt ::="); + consumeEmptyInterfaceMemberDeclarationsopt(); + break ; + + case 545 : // System.out.println("InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations"); + consumeInterfaceMemberDeclarationsopt(); + break ; + + case 546 : // System.out.println("NestedType ::="); + consumeNestedType(); + break ; + + case 547 : // System.out.println("ForInitopt ::="); + consumeEmptyForInitopt(); + break ; + + case 549 : // System.out.println("ForUpdateopt ::="); + consumeEmptyForUpdateopt(); + break ; + + case 553 : // System.out.println("Catchesopt ::="); + consumeEmptyCatchesopt(); + break ; + + case 555 : // System.out.println("ArrayInitializeropt ::="); + consumeEmptyArrayInitializeropt(); + break ; + + } +} +protected void consumeSimpleAssertStatement() { + super.consumeSimpleAssertStatement(); +} + public AjParser( + ProblemReporter problemReporter, + boolean optimizeStringLiterals, + boolean assertMode) { + super(problemReporter, optimizeStringLiterals, assertMode); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/AjScanner.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/AjScanner.java new file mode 100644 index 000000000..879a409bb --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/AjScanner.java @@ -0,0 +1,74 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + + +package org.aspectj.ajdt.internal.compiler.parser; + +import org.aspectj.ajdt.compiler.IAjTerminalSymbols; +import org.eclipse.jdt.core.compiler.*; +import org.eclipse.jdt.internal.compiler.parser.Scanner; +import org.eclipse.jdt.internal.compiler.util.CharOperation; + + +public class AjScanner extends Scanner implements IScanner { + public AjScanner( + boolean tokenizeComments, + boolean tokenizeWhiteSpace, + boolean checkNonExternalizedStringLiterals) { + super( + tokenizeComments, + tokenizeWhiteSpace, + checkNonExternalizedStringLiterals); + } + + public AjScanner( + boolean tokenizeComments, + boolean tokenizeWhiteSpace, + boolean checkNonExternalizedStringLiterals, + boolean assertMode) { + super( + tokenizeComments, + tokenizeWhiteSpace, + checkNonExternalizedStringLiterals, + assertMode); + } + + + private static final char[] aspectV = "aspect".toCharArray(); + private static final char[] pointcutV = "pointcut".toCharArray(); + private static final char[] privilegedV = "privileged".toCharArray(); + private static final char[] beforeV = "before".toCharArray(); + private static final char[] afterV = "after".toCharArray(); + private static final char[] aroundV = "around".toCharArray(); + private static final char[] declareV = "declare".toCharArray(); + + + + public int scanIdentifierOrKeyword() throws InvalidInputException { + int kind = super.scanIdentifierOrKeyword(); + if (kind != IAjTerminalSymbols.TokenNameIdentifier) return kind; + + char[] contents = getCurrentIdentifierSource(); + + //XXX performance here is less than optimal, but code simplicity is pretty damn good + if (CharOperation.equals(aspectV, contents)) return IAjTerminalSymbols.TokenNameaspect; + else if (CharOperation.equals(pointcutV, contents)) return IAjTerminalSymbols.TokenNamepointcut; + else if (CharOperation.equals(privilegedV, contents)) return IAjTerminalSymbols.TokenNameprivileged; + else if (CharOperation.equals(beforeV, contents)) return IAjTerminalSymbols.TokenNamebefore; + else if (CharOperation.equals(afterV, contents)) return IAjTerminalSymbols.TokenNameafter; + else if (CharOperation.equals(aroundV, contents)) return IAjTerminalSymbols.TokenNamearound; + else if (CharOperation.equals(declareV, contents)) return IAjTerminalSymbols.TokenNamedeclare; + + return kind; + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser1.rsc b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser1.rsc Binary files differnew file mode 100644 index 000000000..18aee96d3 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser1.rsc diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser2.rsc b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser2.rsc Binary files differnew file mode 100644 index 000000000..34fc767ed --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser2.rsc diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser3.rsc b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser3.rsc Binary files differnew file mode 100644 index 000000000..49589a249 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser3.rsc diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser4.rsc b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser4.rsc Binary files differnew file mode 100644 index 000000000..1394b9c07 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser4.rsc diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser5.rsc b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser5.rsc Binary files differnew file mode 100644 index 000000000..77cade3a8 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/parser5.rsc diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java new file mode 100644 index 000000000..c76ca4fb3 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java @@ -0,0 +1,135 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + + package org.aspectj.ajdt.internal.compiler.problem; + +import java.lang.reflect.Modifier; +import java.util.Iterator; + +import org.aspectj.ajdt.internal.compiler.ast.Proceed; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.*; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.patterns.DeclareSoft; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.ast.AstNode; +import org.eclipse.jdt.internal.compiler.impl.*; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; + +public class AjProblemReporter extends ProblemReporter { + private static final boolean DUMP_STACK = false; + + public EclipseWorld world; + + public AjProblemReporter( + IErrorHandlingPolicy policy, + CompilerOptions options, + IProblemFactory problemFactory) { + super(policy, options, problemFactory); + } + + + + public void unhandledException( + TypeBinding exceptionType, + AstNode location) + { + if (!world.getDeclareSoft().isEmpty()) { + Shadow callSite = world.makeShadow(location, referenceContext); + if (callSite == null) { + super.unhandledException(exceptionType, location); + return; + } + Shadow enclosingExec = world.makeShadow(referenceContext); + // System.err.println("about to show error for unhandled exception: " + exceptionType + + // " at " + location + " in " + referenceContext); + + + for (Iterator i = world.getDeclareSoft().iterator(); i.hasNext(); ) { + DeclareSoft d = (DeclareSoft)i.next(); + FuzzyBoolean match = d.getPointcut().match(callSite); + if (match.alwaysTrue()) { + //System.err.println("matched callSite: " + callSite + " with " + d); + return; + } else if (!match.alwaysFalse()) { + throw new RuntimeException("unimplemented, shouldn't have fuzzy match here"); + } + + match = d.getPointcut().match(enclosingExec); + if (match.alwaysTrue()) { + //System.err.println("matched enclosingExec: " + enclosingExec + " with " + d); + return; + } else if (!match.alwaysFalse()) { + throw new RuntimeException("unimplemented, shouldn't have fuzzy match here"); + } + } + } + + //??? is this always correct + if (location instanceof Proceed) { + return; + } + + super.unhandledException(exceptionType, location); + } + + public void handle( + int problemId, + String[] problemArguments, + int severity, + int problemStartPosition, + int problemEndPosition, + ReferenceContext referenceContext, + CompilationResult unitResult) { + + if (severity != Ignore && DUMP_STACK) { + Thread.currentThread().dumpStack(); + } + super.handle( + problemId, + problemArguments, + severity, + problemStartPosition, + problemEndPosition, + referenceContext, + unitResult); + } + + + public void abstractMethodMustBeImplemented( + SourceTypeBinding type, + MethodBinding abstractMethod) + { + // if we implemented this method by an inter-type declaration, then there is no error + //??? be sure this is always right + ResolvedTypeX onTypeX = world.fromEclipse(type); //abstractMethod.declaringClass); + for (Iterator i = onTypeX.getInterTypeMungers().iterator(); i.hasNext(); ) { + ConcreteTypeMunger m = (ConcreteTypeMunger)i.next(); + if (m.matches(onTypeX)) { + ResolvedMember sig = m.getSignature(); + if (Modifier.isPublic(sig.getModifiers()) && !Modifier.isAbstract(sig.getModifiers())) { + if (ResolvedTypeX.matches(sig, world.makeResolvedMember(abstractMethod))) { + return; + } + } + } + } + + super.abstractMethodMustBeImplemented(type, abstractMethod); + } + +} 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 new file mode 100644 index 000000000..8a43cfa33 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java @@ -0,0 +1,205 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.File; +import java.util.*; + +/** + * All configuration information needed to run the AspectJ compiler. + */ +public class AjBuildConfig { + + public static final String AJLINT_INGORE = "ignore"; + public static final String AJLINT_WARN = "warn"; + public static final String AJLINT_ERROR = "error"; + public static final String AJLINT_DEFAULT = "default"; + + private File outputDir; + private File outputJar; + private List/*File*/ sourceRoots = new ArrayList(); + private List/*File*/ files = new ArrayList(); + private List/*File*/ inJars = new ArrayList(); + private List/*File*/ aspectpath = new ArrayList(); + private List/*String*/ classpath = new ArrayList(); + private Map javaOptions = new HashMap(); + private Map ajOptions = new HashMap(); + private File configFile; + private boolean generateModelMode = false; + private boolean emacsSymMode = false; + private boolean noWeave = false; + private boolean XserializableAspects = false; + private String lintMode = AJLINT_DEFAULT; + private File lintSpecFile = null; + + /** + * returned files includes <ul> + * <li>files explicitly listed on command-line</li> + * <li>files listed by reference in argument list files</li> + * <li>files contained in sourceRootDir if that exists</li> + * </ul> + * + * @return all source files that should be compiled. + */ + public List/*File*/ getFiles() { + return files; + } + + public File getOutputDir() { + return outputDir; + } + + public void setFiles(List files) { + this.files = files; + } + + public void setOutputDir(File outputDir) { + this.outputDir = outputDir; + } + + public Map getAjOptions() { + return ajOptions; + } + + /** + * @return the Map expected by org.eclipse.jdt.core.internal.Compiler. + */ + public Map getJavaOptions() { + return javaOptions; + } + + public void setAjOptions(Map ajOptions) { + this.ajOptions = ajOptions; + } + + public void setJavaOptions(Map javaOptions) { + this.javaOptions = javaOptions; + } + + /** + * This includes all entries from -bootclasspath, -extdirs, -classpath, + */ + public List getClasspath() { + return classpath; + } + + public void setClasspath(List classpath) { + this.classpath = classpath; + } + + public File getOutputJar() { + return outputJar; + } + + public List/*File*/ getInJars() { + return inJars; + } + + public void setOutputJar(File outputJar) { + this.outputJar = outputJar; + } + + public void setInJars(List sourceJars) { + this.inJars = sourceJars; + } + + public List getSourceRoots() { + return sourceRoots; + } + + public void setSourceRoots(List sourceRootDir) { + this.sourceRoots = sourceRootDir; + } + + public File getConfigFile() { + return configFile; + } + + public void setConfigFile(File configFile) { + this.configFile = configFile; + } + + public boolean isEmacsSymMode() { + return emacsSymMode; + } + + public void setEmacsSymMode(boolean emacsSymMode) { + this.emacsSymMode = emacsSymMode; + } + + public boolean isGenerateModelMode() { + return generateModelMode; + } + + public void setGenerateModelMode(boolean structureModelMode) { + this.generateModelMode = structureModelMode; + } + + /** + * This includes injars and aspectpath + */ + public List getFullClasspath() { + if (inJars.isEmpty() && aspectpath.isEmpty()) return getClasspath(); + List full = new ArrayList(); + for (Iterator i = inJars.iterator(); i.hasNext(); ) { + full.add(((File)i.next()).getAbsolutePath()); + } + for (Iterator i = aspectpath.iterator(); i.hasNext(); ) { + full.add(((File)i.next()).getAbsolutePath()); + } + full.addAll(getClasspath()); + return full; + } + + public String getLintMode() { + return lintMode; + } + + public File getLintSpecFile() { + return lintSpecFile; + } + + public List getAspectpath() { + return aspectpath; + } + + public boolean isNoWeave() { + return noWeave; + } + + public void setLintMode(String lintMode) { + this.lintMode = lintMode; + } + + public void setLintSpecFile(File lintSpecFile) { + this.lintSpecFile = lintSpecFile; + } + + public void setAspectpath(List aspectpath) { + this.aspectpath = aspectpath; + } + + public void setNoWeave(boolean noWeave) { + this.noWeave = noWeave; + } + + public boolean isXserializableAspects() { + return XserializableAspects; + } + + public void setXserializableAspects(boolean xserializableAspects) { + XserializableAspects = xserializableAspects; + } + +} 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 new file mode 100644 index 000000000..34d0a95a2 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java @@ -0,0 +1,845 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import org.aspectj.ajdt.internal.compiler.AjCompiler; +import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; +import org.aspectj.ajdt.internal.compiler.parser.AjParser; +import org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter; +import org.aspectj.asm.*; +import org.aspectj.bridge.*; +import org.aspectj.util.LangUtil; +import org.aspectj.weaver.bcel.*; +import org.aspectj.workbench.resources.*; +import org.eclipse.core.internal.events.ResourceDelta; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.util.Util; +import org.eclipse.jdt.internal.core.builder.*; +import org.eclipse.jdt.internal.compiler.Compiler; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.jar.*; + +public class AjBuildManager { + + public static final IProject DEFAULT_PROJECT // XXX + = new SimpleProject(new Path(""), "DefaultProject"); + + private JavaBuilder javaBuilder; + private StructureModel structureModel; + private BuildNotifier buildNotifier = null; + public AjBuildConfig buildConfig; + + private BcelWeaver bcelWeaver; + private BcelWorld bcelWorld; + + /** temp handler for callbacks */ + private IMessageHandler currentHandler; // XXX wrong lifecyle, used for callbacks + + ClassFileCache classFileCache; + + Set addedFiles; + Set deletedFiles; + + public AjBuildManager(IMessageHandler holder) { + super(); + LangUtil.throwIaxIfNull(holder, "holder"); + } + + /** @return true if we should generate a model as a side-effect */ + public boolean doGenerateModel() { + return buildConfig.isGenerateModelMode(); + } + + /** @throws AbortException if check for runtime fails */ + public boolean batchBuild(AjBuildConfig buildConfig, IMessageHandler handler) + throws IOException, AbortException { + final CountingMessageHandler counter = new CountingMessageHandler(handler); + handler = null; // fyi - use counter only + try { + setBuildConfig(buildConfig); + currentHandler = counter; + String check = checkRtJar(buildConfig); + // XXX MessageUtil.abortUnlessNull(counter, check); + if (check != null) { + // XXX change to ABORT? + IMessage message = new Message(check, Message.WARNING, null, null); + // give delegate a chance to implement different message (abort)? + counter.handleMessage(message); + throw new AbortException(message); + } + + setupModel(); + initBcelWorld(counter); + if (counter.hasErrors()) { + return false; + } + initJavaBuilder(counter); + if (counter.hasErrors()) { + return false; + } + + //XXX disabling structure building until Mik can make it optional + if (buildConfig.isEmacsSymMode()) bcelWorld.setModel(StructureModelManager.INSTANCE.getStructureModel()); + BatchBuilder builder = new BatchBuilder(javaBuilder, counter); + State newState = builder.run(); + if (buildConfig.isEmacsSymMode()) { + new org.aspectj.ajdt.internal.core.builder.EmacsStructureModelManager().externalizeModel(); + } +// System.err.println("check error: " + counter + ", " + +// counter.numMessages(IMessage.ERROR) + ", " + counter.numMessages(IMessage.FAIL, false)); + if (counter.hasErrors()) { + return false; + } + + boolean weaved = weaveAndGenerateClassFiles(newState); + //XXX more sturucture disabling until it's optional + if (false) StructureModelManager.INSTANCE.fireModelUpdated(); + return weaved; + } catch (CoreException ce) { + counter.handleMessage(new Message("core exception", IMessage.ABORT, ce, null)); + //messageAdapter.handleAbort("core exception", ce); + return false; + } finally { + currentHandler = null; + } + } + + /** extruded method as testing backdoor */ + IncrementalBuilder getIncrementalBuilder(IMessageHandler handler) { + return new IncrementalBuilder(javaBuilder, handler); + } + + private void setupModel() { + String rootLabel = "<root>"; + if (buildConfig.getConfigFile() != null) { + rootLabel = buildConfig.getConfigFile().getName(); + StructureModelManager.INSTANCE.getStructureModel().setConfigFile( + buildConfig.getConfigFile().getAbsolutePath() + ); + } + StructureModelManager.INSTANCE.getStructureModel().setRoot( + new ProgramElementNode( + rootLabel, + ProgramElementNode.Kind.FILE_JAVA, + new ArrayList())); + + HashMap modelFileMap = new HashMap(); + StructureModelManager.INSTANCE.getStructureModel().setFileMap(new HashMap()); + setStructureModel(StructureModelManager.INSTANCE.getStructureModel()); + + } + + public boolean incrementalBuild(AjBuildConfig buildConfig, IMessageHandler messageHandler) throws CoreException, IOException { + try { + currentHandler = messageHandler; + IncrementalBuilder builder = getIncrementalBuilder(messageHandler); + // SimpleLookupTable deltas = + //XXX for Mik, replace this with a call to builder.build(SimpleLookupTable deltas) + + IContainer[] sourceFolders = new IContainer[buildConfig.getSourceRoots().size()]; + int count = 0; + for (Iterator i = buildConfig.getSourceRoots().iterator(); i.hasNext(); count++) { + sourceFolders[count] = new FilesystemFolder(((File)i.next()).getAbsolutePath()); + } + builder.setSourceFolders(sourceFolders); + getJavaBuilder().binaryResources = new SimpleLookupTable(); + SimpleLookupTable deltas = getDeltas(buildConfig); + + boolean succeeded = builder.build(deltas); + + if (succeeded) { + return weaveAndGenerateClassFiles(builder.getNewState()); + } else { + return batchBuild(buildConfig, messageHandler); + } + } finally { + currentHandler = null; + } + + } + + SimpleLookupTable getDeltas(AjBuildConfig newBuildConfig) { + updateBuildConfig(newBuildConfig); + // !!! support multiple source roots + SimpleLookupTable deltas = new SimpleLookupTable(); + for (Iterator i = newBuildConfig.getSourceRoots().iterator(); i.hasNext(); ) { + makeDeltas(deltas, getModifiedFiles(), deletedFiles, ((File)i.next()).getAbsolutePath()); + } + return deltas; + } + + void makeDeltas(SimpleLookupTable deltas, Collection modifiedAndAdded, Collection deletedFiles, String sourcePath) { + + IProject project = javaBuilder.currentProject; //??? + + List deltaChildren = new ArrayList(); + //??? do we need to distinguish added from modified +// for (Iterator it = addedFiles.iterator(); it.hasNext(); ) { +// File addedFile = (File)it.next(); +// CommandLineResourceDelta addedDelta = new CommandLineResourceDelta( +// new Path(addedFile.getAbsolutePath()), null); +// addedDelta.setKind(IResourceDelta.ADDED); +// deltaChildren.add(addedDelta); +// } + + for (Iterator it = deletedFiles.iterator(); it.hasNext(); ) { + File addedFile = (File)it.next(); + CommandLineResourceDelta addedDelta = new CommandLineResourceDelta( + new FilesystemFile(addedFile.getAbsolutePath())); + addedDelta.setKind(IResourceDelta.REMOVED); + deltaChildren.add(addedDelta); + } + + for (Iterator it = modifiedAndAdded.iterator(); it.hasNext(); ) { + File addedFile = (File)it.next(); + CommandLineResourceDelta addedDelta = new CommandLineResourceDelta( + new FilesystemFile(addedFile.getAbsolutePath())); + addedDelta.setKind(IResourceDelta.CHANGED); + deltaChildren.add(addedDelta); + } + + CommandLineResourceDelta delta = new CommandLineResourceDelta( + new FilesystemFile(sourcePath)); + delta.setKind(IResourceDelta.CHANGED); + delta.setChildren((ResourceDelta[])deltaChildren.toArray(new ResourceDelta[deltaChildren.size()])); + deltas.put(project,delta); + } + + void updateBuildConfig(AjBuildConfig newBuildConfig) { + Set oldFiles = new HashSet(buildConfig.getFiles()); + Set newFiles = new HashSet(newBuildConfig.getFiles()); + + addedFiles = new HashSet(newFiles); + addedFiles.removeAll(oldFiles); + deletedFiles = new HashSet(oldFiles); + deletedFiles.removeAll(newFiles); + setBuildConfig(newBuildConfig); + } + + private void initBcelWorld(IMessageHandler handler) throws IOException { + bcelWorld = new BcelWorld(buildConfig.getClasspath(), handler); + bcelWeaver = new BcelWeaver(bcelWorld); + + for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) { + File f = (File) i.next(); + bcelWeaver.addLibraryJarFile(f); + } + + String lintMode = buildConfig.getLintMode(); + + if (buildConfig.getLintMode().equals(AjBuildConfig.AJLINT_DEFAULT)) { + bcelWorld.getLint().loadDefaultProperties(); + } else { + bcelWorld.getLint().setAll(buildConfig.getLintMode()); + } + + if (buildConfig.getLintSpecFile() != null) { + bcelWorld.getLint().setFromProperties(buildConfig.getLintSpecFile()); + } + } + + //??? do this well + private void initJavaBuilder(IMessageHandler handler) { + javaBuilder = new JavaBuilder(); + javaBuilder.currentProject = DEFAULT_PROJECT; + if (buildConfig.getOutputDir() == null) { + //XXX must handle this case better to get javac output compatibility + javaBuilder.outputFolder = new FilesystemFolder(new Path(".")); + } else { + javaBuilder.outputFolder = new FilesystemFolder(new Path(buildConfig.getOutputDir().getPath())); //outputDir.getPath())); + } + classFileCache = new ClassFileCache(javaBuilder.outputFolder, handler); + javaBuilder.outputFolder = classFileCache; + + javaBuilder.sourceFolders = new IContainer[0]; + + javaBuilder.classpath = makeClasspathLocations(); + + //XXX override build notifier to get progress info + if (buildNotifier == null) buildNotifier = new BuildNotifier(null, javaBuilder.currentProject); + javaBuilder.notifier = buildNotifier; + } + + public static String[] getFilenames(List files) { + int len = files.size(); + String[] ret = new String[len]; + for (int i=0; i < len; i++) { + File file = (File)files.get(i); + ret[i] = file.getPath(); + } + return ret; + } + + public static String[] getInitialTypeNames(List files) { + int len = files.size(); + String[] ret = new String[len]; + for (int i=0; i < len; i++) { + File file = (File)files.get(i); + String name = file.getName(); + int dot = name.indexOf('.'); //XXX what if there's no '.' + ret[i] = name.substring(0, dot); + } + return ret; + } + + void addAspectClassFilesToWeaver() throws IOException { + //System.out.println("added or changed: " + classFileCache.getAddedOrChanged()); + for (Iterator i = buildConfig.getInJars().iterator(); i.hasNext(); ) { + File inJar = (File)i.next(); + bcelWeaver.addJarFile(inJar, buildConfig.getOutputDir()); + } + + for (Iterator i = classFileCache.getAddedOrChanged().iterator(); i.hasNext(); ) { + UnwovenClassFile classFile = (UnwovenClassFile) i.next(); + bcelWeaver.addClassFile(classFile); + } + for (Iterator i = classFileCache.getDeleted().iterator(); i.hasNext(); ) { + UnwovenClassFile classFile = (UnwovenClassFile) i.next(); + bcelWeaver.deleteClassFile(classFile.getClassName()); + classFile.deleteRealFile(); + } + } + + public boolean weaveAndGenerateClassFiles(State newState) throws IOException, CoreException { + currentHandler.handleMessage(MessageUtil.info("weaving")); + javaBuilder.lastState = newState; + addAspectClassFilesToWeaver(); + if (buildConfig.isNoWeave()) { + if (buildConfig.getOutputJar() != null) { + bcelWeaver.dumpUnwoven(buildConfig.getOutputJar()); + } else { + bcelWeaver.dumpUnwoven(); + } + } else { + if (buildConfig.getOutputJar() != null) { + bcelWeaver.weave(buildConfig.getOutputJar()); + } else { + bcelWeaver.weave(); + } + } + return true; + //return messageAdapter.getErrorCount() == 0; //!javaBuilder.notifier.anyErrors(); + } + + /** TEST-ONLY access to builder */ + JavaBuilder getJavaBuilder() { + return javaBuilder; + } + + private void setBuildConfig(AjBuildConfig buildConfig) { + this.buildConfig = buildConfig; + + // clear previous error info and incremental info when build config is set + if (javaBuilder != null) { + javaBuilder.notifier = new BuildNotifier(null, javaBuilder.currentProject); + } + if (classFileCache != null) { + classFileCache.resetIncrementalInfo(); + } + } + + private Collection getModifiedFiles() { + return getModifiedFiles(javaBuilder.lastState.lastStructuralBuildTime); + } + + Collection getModifiedFiles(long lastBuildTime) { + List ret = new ArrayList(); + //not our job to account for new and deleted files + for (Iterator i = buildConfig.getFiles().iterator(); i.hasNext(); ) { + File file = (File)i.next(); + + long modTime = file.lastModified(); + //System.out.println("check: " + file + " mod " + modTime + " build " + lastBuildTime); + if (modTime > lastBuildTime) { + ret.add(file); + } + } + return ret; + } + + ClasspathLocation makeClasspathLocation(String entry) { + if (entry.endsWith(".jar") || entry.endsWith(".zip")) { + return ClasspathLocation.forLibrary(entry); + } else { + return ClasspathLocation.forBinaryFolder(entry); + } + } + + ClasspathLocation makeUnwovenClassfileLocation(IContainer container) { + return new ClasspathContainer(container); + } + + /** + * Adds in this order<UL> + * skip this for now, incremental may need some version<LI>magic source path + * <LI>output path + * <LI>classpath + * </UL> + */ + ClasspathLocation[] makeClasspathLocations() { + List locations = new ArrayList(); + + locations.add(makeUnwovenClassfileLocation(classFileCache)); + + //System.out.println("full classpath: " + buildConfig.getFullClasspath()); + + for (Iterator it = buildConfig.getFullClasspath().iterator(); it.hasNext(); ) { + locations.add(makeClasspathLocation((String)it.next())); + } + return (ClasspathLocation[])locations.toArray(new ClasspathLocation[locations.size()]); + } + + + String makeClasspathString() { + if (buildConfig == null || buildConfig.getClasspath() == null) return ""; + StringBuffer buf = new StringBuffer(); + boolean first = true; + for (Iterator it = buildConfig.getClasspath().iterator(); it.hasNext(); ) { + if (first) { first = false; } + else { buf.append(File.pathSeparator); } + buf.append(it.next().toString()); + } + return buf.toString(); + } + + + /** + * This will return null if aspectjrt.jar is present and has the correct version. + * Otherwise it will return a string message indicating the problem. + */ + public String checkRtJar(AjBuildConfig buildConfig) { + // omitting dev info + if (Version.text.equals(Version.DEVELOPMENT)) { + // in the development version we can't do this test usefully +// MessageUtil.info(holder, "running development version of aspectj compiler"); + return null; + } + + if (buildConfig == null || buildConfig.getClasspath() == null) return "no classpath specified"; + for (Iterator it = buildConfig.getClasspath().iterator(); it.hasNext(); ) { + File p = new File( (String)it.next() ); + if (p.isFile() && p.getName().equals("aspectjrt.jar")) { + + try { + String version = null; + Attributes attr = new JarFile(p).getManifest().getAttributes("org/aspectj/lang/"); + if (null != attr) { + version = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION); + if (null != version) { + version = version.trim(); + } + } + // assume that users of development aspectjrt.jar know what they're doing + if (Version.DEVELOPMENT.equals(version)) { +// MessageUtil.info(holder, +// "running with development version of aspectjrt.jar in " + +// p.getAbsolutePath()); + return null; + } else if (!Version.text.equals(version)) { + return "bad version number found in " + p.getAbsolutePath() + + " expected " + Version.text + " found " + version; + } + } catch (IOException ioe) { + return "bad jar file found in " + p.getAbsolutePath() + " error: " + ioe; + } + return null; + } else { + // might want to catch other classpath errors + } + } + + return "couldn't find aspectjrt.jar on classpath, checked: " + makeClasspathString(); + } + + + /** + * Just like AbstractImageBuilder.newCompiler, except doesn't use JavaCore + */ + Compiler makeCompiler( // XXX restore private + final AbstractImageBuilder builder, + NameEnvironment nameEnvironment, + IMessageHandler handler) { + // called once when the builder is initialized... can override if needed + AjCompiler compiler = new AjCompiler( + nameEnvironment, + DefaultErrorHandlingPolicies.proceedWithAllProblems(), + buildConfig.getJavaOptions(), + builder, + ProblemFactory.getProblemFactory(Locale.getDefault())); + + + AjProblemReporter pr = new AjProblemReporter(DefaultErrorHandlingPolicies.proceedWithAllProblems(), + compiler.options, ProblemFactory.getProblemFactory(Locale.getDefault())); + + compiler.problemReporter = pr; + + AjLookupEnvironment le = + new AjLookupEnvironment(compiler, compiler.options, + pr, nameEnvironment); + EclipseWorld ew = new EclipseWorld(le, handler); + ew.setLint(bcelWorld.getLint()); + le.world = ew; + pr.world = ew; + le.world.buildManager = this; + + compiler.lookupEnvironment = le; + + compiler.parser = + new AjParser( + pr, + compiler.options.parseLiteralExpressionsAsConstants, + compiler.options.assertMode); + + + + //EclipseWorld world = EclipseWorld.forLookupEnvironment(compiler.lookupEnvironment); + return compiler; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("AjBuildManager("); + buf.append(")"); + return buf.toString(); + } + + + public void setStructureModel(StructureModel structureModel) { + this.structureModel = structureModel; + } + + /** + * Returns null if there is no structure model + */ + public StructureModel getStructureModel() { + return structureModel; + } + + public void setBuildNotifier(BuildNotifier notifier) { + buildNotifier = notifier; + } + + /** callback for builders used only during build */ + private boolean handleProblem(ICompilationUnit unit, IProblem problem) { // XXX + IMessageHandler handler = currentHandler; + if (null == handler) { + throw new IllegalStateException("no current handler when handling " + + problem + " in " + unit); + } + IMessage message = EclipseAdapterUtils.makeMessage(unit, problem); + return handler.handleMessage(message); + } + + /** initialization for testing purposes */ + boolean testInit(IMessageHandler handler) { + try { + initBcelWorld(handler); + initJavaBuilder(handler); + } catch (Throwable e) { + return false; + } + return true; + } + /** invasive test has to set handler */ + void testSetHandler(IMessageHandler handler) { + currentHandler = handler; + } + + // ---------------------------------------------------- + + /** build batch command; alive during batchBuild(...) only */ + private class BatchBuilder extends BatchImageBuilder { + boolean initialized; + boolean running; + + public BatchBuilder(JavaBuilder builder, IMessageHandler handler) { + super(builder); + this.compiler = makeCompiler(this, nameEnvironment, handler); + } + + /** + * XXXwe'll want to preload aspects from projects or library .jars + * XXXthat we depend on + * + * compile all files and store in generatedClassFiles + * then collect aspects + * then weave into generatedClassFiles and dump to disk + * + * a possible optimization is to generate all aspects first, it's unclear + * that this is worth the effort or loss of clarity + */ + public State run() throws IOException, CoreException { + compile(getFilenames(buildConfig.getFiles()), + getInitialTypeNames(buildConfig.getFiles())); + return newState; + } + + /** + * Only used to get source files + * + * XXX verify this rigourously + */ + protected IResource resourceForLocation(String sourceLocation) { + return new FilesystemFile(new Path(sourceLocation)); + } + + protected void createErrorFor(IResource resource, String message) { + //XXX don't think there's anything to do here + } + + protected void updateProblemsFor( + String sourceLocation, + CompilationResult result) + throws CoreException { + IProblem[] problems = result.getProblems(); + if (problems == null || problems.length == 0) return; + + notifier.updateProblemCounts(problems); + for (int i=0, len=problems.length; i < len; i++) { + handleProblem(result.getCompilationUnit(), problems[i]); + } + } + + /** + * We can't create a compiler until after our super's constructor has run + * We will fill in the right value then. + */ + protected Compiler newCompiler() { // XXX unimplemented?? + return null; + } + + protected SourceFile makeSourceFile(String filename, String initialTypeName) { + SourceFile sourceFile = super.makeSourceFile(filename, initialTypeName); + sourceFile.packageName = null; // tells eclipse that we don't know this package + return sourceFile; + } + } // class BatchBuilder + + class IncrementalBuilder extends IncrementalImageBuilder { + + public IncrementalBuilder(JavaBuilder builder, IMessageHandler handler) { + super(builder); + this.compiler = makeCompiler(this, nameEnvironment, handler); + } + + + List getLocations() { + return locations; + } + + public State getNewState() { + return newState; + } + + public boolean build(SimpleLookupTable deltas) { + return super.build(deltas); + } + + /** + * @param changedFiles includes both new files and changed files + */ + public boolean build(Collection changedFiles, Collection deletedFiles) { + + // initialize builder + // walk this project's deltas, find changed source files + // walk prereq projects' deltas, find changed class files & add affected source files + // use the build state # to skip the deltas for certain prereq projects + // ignore changed zip/jar files since they caused a full build + // compile the source files & acceptResult() + // compare the produced class files against the existing ones on disk + // recompile all dependent source files of any type with structural changes or new/removed secondary type + // keep a loop counter to abort & perform a full build + + if (JavaBuilder.DEBUG) + System.out.println("INCREMENTAL build"); //$NON-NLS-1$ + + try { + resetCollections(); + + notifier.subTask(Util.bind("build.analyzingDeltas")); //$NON-NLS-1$ + if (!addFileLocations(changedFiles, deletedFiles)) return false; + + //XXX deal with deleted files here too + + + // IResourceDelta sourceDelta = (IResourceDelta) deltas.get(javaBuilder.currentProject); + // if (sourceDelta != null) + // if (!findSourceFiles(sourceDelta)) return false; + // notifier.updateProgressDelta(0.10f); + + // Object[] keyTable = deltas.keyTable; + // Object[] valueTable = deltas.valueTable; + // for (int i = 0, l = keyTable.length; i < l; i++) { + // IResourceDelta delta = (IResourceDelta) valueTable[i]; + // if (delta != null) { + // IResource[] binaryResources = (IResource[]) javaBuilder.binaryResources.get(keyTable[i]); + // if (binaryResources != null) + // if (!findAffectedSourceFiles(delta, binaryResources)) return false; + // } + // } + // notifier.updateProgressDelta(0.10f); + + notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$ + addAffectedSourceFiles(); + notifier.updateProgressDelta(0.05f); + + int compileLoop = 0; + float increment = 0.40f; + while (locations.size() > 0) { // added to in acceptResult + if (++compileLoop > MaxCompileLoop) { + if (JavaBuilder.DEBUG) + System.out.println("ABORTING incremental build... exceeded loop count"); //$NON-NLS-1$ + return false; + } + notifier.checkCancel(); + + String[] allSourceFiles = new String[locations.size()]; + locations.toArray(allSourceFiles); + String[] initialTypeStrings = new String[typeNames.size()]; + typeNames.toArray(initialTypeStrings); + resetCollections(); + + workQueue.addAll(allSourceFiles); + notifier.setProgressPerCompilationUnit(increment / allSourceFiles.length); + increment = increment / 2; + compile(allSourceFiles, initialTypeStrings); + //removeSecondaryTypes(); + addAffectedSourceFiles(); + } + } catch (AbortIncrementalBuildException e) { + // abort the incremental build and let the batch builder handle the problem + if (JavaBuilder.DEBUG) + System.out.println("ABORTING incremental build... cannot find " + e.qualifiedTypeName + //$NON-NLS-1$ + ". Could have been renamed inside its existing source file."); //$NON-NLS-1$ + return false; + // } catch (CoreException e) { + // throw internalException(e); + } finally { + cleanUp(); + } + return true; + } + + public void setSourceFolders(IContainer[] sourceFolders) { + super.sourceFolders = sourceFolders; + } + + public IContainer[] getSourceFolders() { + return sourceFolders; + } + + private boolean addFileLocations(Collection changedFiles, Collection deletedFiles) { + addDeletedFiles(deletedFiles); + + for (Iterator i = changedFiles.iterator(); i.hasNext(); ) { + File file = (File)i.next(); + locations.add(getSourceLocation(file)); + typeNames.add(file.getName().substring(0, file.getName().length()-5)); + } + return changedFiles.size() > 0 || deletedFiles.size() > 0; + } + + private String getSourceLocation(File file) { + return file.getPath().replace('\\', '/'); + } + + + /** + * @see IncrementalImageBuilder.findSourceFiles + */ + private void addDeletedFiles(Collection deletedFiles) { + } + // for (Iterator i = deletedFiles.iterator(); i.hasNext(); ) { + // File file = (File)i.next(); + // String sourceLocation = getSourceLocation(file); + // char[][] definedTypeNames = newState.getDefinedTypeNamesFor(sourceLocation); + // + // if (definedTypeNames == null) { // defined a single type matching typePath + // removeClassFile(typePath); + // } else { + // if (JavaBuilder.DEBUG) + // System.out.println("Add dependents of removed source file " + typePath.toString()); //$NON-NLS-1$ + // addDependentsOf(typePath, true); // add dependents of the source file since it may be involved in a name collision + // if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type + // IPath packagePath = typePath.removeLastSegments(1); + // for (int i = 0, length = definedTypeNames.length; i < length; i++) + // removeClassFile(packagePath.append(new String(definedTypeNames[i]))); + // } + // } + // newState.remove(sourceLocation); + // } + + + // public void acceptResult(CompilationResult result) { + // System.out.println("result: " + result); + // buildManager.noteRecompiled(new File(new String(result.fileName))); + // //newState.dump(); + // super.acceptResult(result); + // //newState.dump(); + // } + + protected IResource resourceForLocation(String sourceLocation) { + return new FilesystemFile(new Path(sourceLocation)); + } + + protected void createErrorFor(IResource resource, String message) { + //XXX don't think there's anything to do here + } + + protected void updateProblemsFor( + String sourceLocation, + CompilationResult result) + throws CoreException { + IProblem[] problems = result.getProblems(); + if (problems == null || problems.length == 0) return; + + notifier.updateProblemCounts(problems); + for (int i=0, len=problems.length; i < len; i++) { + handleProblem(result.getCompilationUnit(), problems[i]); + } + } + + + protected String extractTypeNameFrom(String sourceLocation) { + File file = new File(sourceLocation); + return file.getName().substring(0, file.getName().length()-5); + } + + /** + * We can't create a compiler until after our super's constructor has run + * We will fill in the right value then. + */ + protected Compiler newCompiler() { + return null; + } + + protected SourceFile makeSourceFile(String filename, String initialTypeName) { + SourceFile sourceFile = super.makeSourceFile(filename, initialTypeName); + sourceFile.packageName = null; // tells eclipse that we don't know this package + return sourceFile; + } + + } // class IncrementalBuilder + +} // class AjBuildManager + diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java new file mode 100644 index 000000000..e3545ea39 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java @@ -0,0 +1,28 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.util.Map; + +/** + * ??? should this go away? + */ +public class AjCompilerOptions { + + public static final String OPTION_Xlint = "org.aspectj.ajdt.core.compiler.Xlint"; + public static final String OPTION_InJARs = "org.aspectj.ajdt.core.compiler.injars"; + public static final String OPTION_OutJAR = "org.aspectj.ajdt.core.compiler.outjar"; + +} + diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjNameEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjNameEnvironment.java new file mode 100644 index 000000000..3e65a5da8 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjNameEnvironment.java @@ -0,0 +1,40 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.util.*; + +import org.aspectj.ajdt.internal.compiler.ast.*; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.internal.core.builder.*; + +public class AjNameEnvironment extends NameEnvironment { + private Set aspectDeclarations = new HashSet(); + + public AjNameEnvironment(ClasspathLocation[] classpathLocations) { + super(classpathLocations); + } + + public AjNameEnvironment(IJavaProject javaProject) { + super(javaProject); + } + + //??? do I want this or a more general getAspects??? + public Collection getAspectDeclarations() { return aspectDeclarations; } + + public void addAspectDeclaration(AspectDeclaration dec) { + aspectDeclarations.add(dec); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmBuilder.java new file mode 100644 index 000000000..6abd8b518 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmBuilder.java @@ -0,0 +1,317 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.File; +import java.text.CollationElementIterator; +import java.util.*; +import java.util.List; + +import org.aspectj.ajdt.internal.compiler.ast.*; +import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration; +import org.aspectj.ajdt.internal.compiler.lookup.*; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseShadow; +import org.aspectj.asm.*; +import org.aspectj.asm.StructureModel; +import org.aspectj.bridge.*; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.weaver.Member; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter; +import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; +import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; +import org.eclipse.jdt.internal.compiler.problem.ProblemHandler; + +public class AsmBuilder extends AbstractSyntaxTreeVisitorAdapter { + + private Stack stack = new Stack(); + private CompilationResult currCompilationResult = null; + + public static void build( + CompilationUnitDeclaration unit, + StructureModel structureModel) { + new AsmBuilder().internalBuild(unit, structureModel); + } + + private void internalBuild(CompilationUnitDeclaration unit, StructureModel structureModel) { + currCompilationResult = unit.compilationResult(); + File file = new File(new String(unit.getFileName())); + ISourceLocation sourceLocation = new SourceLocation(file, 1); + + ProgramElementNode cuNode = new ProgramElementNode( + new String(file.getName()), + ProgramElementNode.Kind.FILE_JAVA, + sourceLocation, + 0, + "", + new ArrayList()); + + ImportReference currentPackage = unit.currentPackage; + if (currentPackage != null) { + StringBuffer nameBuffer = new StringBuffer(); + for (int i = 0; i < currentPackage.getImportName().length; i++) { + nameBuffer.append(new String(currentPackage.getImportName()[i])); + if (i < currentPackage.getImportName().length-1) nameBuffer.append('.'); + } + String pkgName = nameBuffer.toString(); + + boolean found = false; + ProgramElementNode pkgNode = null; + for (Iterator it = StructureModelManager.INSTANCE.getStructureModel().getRoot().getChildren().iterator(); it.hasNext(); ) { + ProgramElementNode currNode = (ProgramElementNode)it.next(); + if (currNode.getName().equals(pkgName)) pkgNode = currNode; + } + if (pkgNode == null) { + pkgNode = new ProgramElementNode( + pkgName, + ProgramElementNode.Kind.PACKAGE, + new ArrayList()); + StructureModelManager.INSTANCE.getStructureModel().getRoot().addChild(pkgNode); + } + pkgNode.addChild(cuNode); + } else { + StructureModelManager.INSTANCE.getStructureModel().getRoot().addChild(cuNode); + } + + stack.push(cuNode); + unit.traverse(this, unit.scope); + + StructureModelManager.INSTANCE.getStructureModel().getFileMap().put( + file.getAbsolutePath().replace('\\', '/'), + cuNode + ); +// if (currImports != null) peNode.addChild(0, currImports); +// currImports = null; + } + + public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) { + String name = new String(typeDeclaration.name); + ProgramElementNode.Kind kind = ProgramElementNode.Kind.CLASS; + if (typeDeclaration instanceof AspectDeclaration) kind = ProgramElementNode.Kind.ASPECT; + else if (typeDeclaration.isInterface()) kind = ProgramElementNode.Kind.INTERFACE; + + ProgramElementNode peNode = new ProgramElementNode( + name, + kind, + makeLocation(typeDeclaration), + typeDeclaration.modifiers, + "", + new ArrayList()); + + ((StructureNode)stack.peek()).addChild(peNode); + stack.push(peNode); + return true; + } + public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) { + stack.pop(); + } + + // ??? share impl with visit(TypeDeclaration, ..) ? + public boolean visit(MemberTypeDeclaration memberTypeDeclaration, ClassScope scope) { + String name = new String(memberTypeDeclaration.name); + ProgramElementNode.Kind kind = ProgramElementNode.Kind.CLASS; + if (memberTypeDeclaration instanceof AspectDeclaration) kind = ProgramElementNode.Kind.ASPECT; + else if (memberTypeDeclaration.isInterface()) kind = ProgramElementNode.Kind.INTERFACE; + + ProgramElementNode peNode = new ProgramElementNode( + name, + kind, + makeLocation(memberTypeDeclaration), + memberTypeDeclaration.modifiers, + "", + new ArrayList()); + + ((StructureNode)stack.peek()).addChild(peNode); + stack.push(peNode); + return true; + } + public void endVisit(MemberTypeDeclaration memberTypeDeclaration, ClassScope scope) { + stack.pop(); + } + + // !!! improve name and type generation + public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { + ProgramElementNode.Kind kind = ProgramElementNode.Kind.METHOD; + String label = new String(methodDeclaration.selector); + + if (methodDeclaration instanceof AdviceDeclaration) { + kind = ProgramElementNode.Kind.ADVICE; + label = translateAdviceName(label); + } else if (methodDeclaration instanceof PointcutDeclaration) { + kind = ProgramElementNode.Kind.POINTCUT; + } else if (methodDeclaration instanceof DeclareDeclaration) { + DeclareDeclaration declare = (DeclareDeclaration)methodDeclaration; + label = translateDeclareName(declare.toString()); + if (label.indexOf("warning") != -1) kind = ProgramElementNode.Kind.DECLARE_WARNING; + if (label.indexOf("error") != -1) kind = ProgramElementNode.Kind.DECLARE_ERROR; + } else if (methodDeclaration instanceof InterTypeDeclaration) { + kind = ProgramElementNode.Kind.INTRODUCTION; + label = translateInterTypeDecName(new String(((InterTypeDeclaration)methodDeclaration).selector)); + } + + ProgramElementNode peNode = new ProgramElementNode( + label, + kind, + makeLocation(methodDeclaration), + methodDeclaration.modifiers, + "", + new ArrayList()); + + Member member = EclipseWorld.makeResolvedMember(methodDeclaration.binding); + peNode.setBytecodeName(member.getName()); + peNode.setBytecodeSignature(member.getSignature()); + ((StructureNode)stack.peek()).addChild(peNode); + stack.push(peNode); + + return true; + } + + + public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) { + stack.pop(); + } + + public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { + ProgramElementNode peNode = new ProgramElementNode( + new String(fieldDeclaration.name), + ProgramElementNode.Kind.FIELD, + makeLocation(fieldDeclaration), + fieldDeclaration.modifiers, + "", + new ArrayList()); + ((StructureNode)stack.peek()).addChild(peNode); + stack.push(peNode); + return true; + } + public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) { + stack.pop(); + } + + +// public boolean visit(ImportReference importRef, CompilationUnitScope scope) { +// ProgramElementNode peNode = new ProgramElementNode( +// new String(importRef.toString()), +// ProgramElementNode.Kind., +// makeLocation(importRef), +// 0, +// "", +// new ArrayList()); +// ((StructureNode)stack.peek()).addChild(0, peNode); +// stack.push(peNode); +// return true; +// } +// public void endVisit(ImportReference importRef,CompilationUnitScope scope) { +// stack.pop(); +// } + + public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { + if (constructorDeclaration.isDefaultConstructor) { + stack.push(null); // a little wierd but does the job + return true; + } + ProgramElementNode peNode = new ProgramElementNode( + new String(constructorDeclaration.selector), + ProgramElementNode.Kind.CONSTRUCTOR, + makeLocation(constructorDeclaration), + constructorDeclaration.modifiers, + "", + new ArrayList()); + ((StructureNode)stack.peek()).addChild(peNode); + stack.push(peNode); + return true; + } + public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { + stack.pop(); + } + +// public boolean visit(Clinit clinit, ClassScope scope) { +// ProgramElementNode peNode = new ProgramElementNode( +// "<clinit>", +// ProgramElementNode.Kind.INITIALIZER, +// makeLocation(clinit), +// clinit.modifiers, +// "", +// new ArrayList()); +// ((StructureNode)stack.peek()).addChild(peNode); +// stack.push(peNode); +// return false; +// } +// public void endVisit(Clinit clinit, ClassScope scope) { +// stack.pop(); +// } + + /** This method works-around an odd traverse implementation on Initializer + */ + private Initializer inInitializer = null; + public boolean visit(Initializer initializer, MethodScope scope) { + if (initializer == inInitializer) return false; + inInitializer = initializer; + + ProgramElementNode peNode = new ProgramElementNode( + "...", + ProgramElementNode.Kind.INITIALIZER, + makeLocation(initializer), + initializer.modifiers, + "", + new ArrayList()); + ((StructureNode)stack.peek()).addChild(peNode); + stack.push(peNode); + initializer.block.traverse(this, scope); + stack.pop(); + return false; + } + + // ??? handle non-existant files + private ISourceLocation makeLocation(AstNode node) { + String fileName = new String(currCompilationResult.getFileName()); + int line = ProblemHandler.searchLineNumber( + currCompilationResult.lineSeparatorPositions, + node.sourceStart); + return new SourceLocation(new File(fileName), line); + } + + // !!! move or replace + private String translateAdviceName(String label) { + if (label.indexOf("before") != -1) return "before"; + if (label.indexOf("returning") != -1) return "after returning"; + if (label.indexOf("after") != -1) return "after"; + if (label.indexOf("around") != -1) return "around"; + else return "<advice>"; + } + + // !!! move or replace + private String translateDeclareName(String name) { + int colonIndex = name.indexOf(":"); + if (colonIndex != -1) { + return name.substring(0, colonIndex); + } else { + return name; + } + } + + // !!! move or replace + private String translateInterTypeDecName(String name) { + int index = name.lastIndexOf('$'); + if (index != -1) { + return name.substring(index+1); + } else { + return name; + } + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClassFileCache.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClassFileCache.java new file mode 100644 index 000000000..7f06461cf --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClassFileCache.java @@ -0,0 +1,184 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + + +import java.util.*; + +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.workbench.resources.AbstractContainer; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +public class ClassFileCache extends AbstractContainer { + + private IContainer container; + private Map cache = new HashMap(); + private IMessageHandler handler; + private Map/*IPath->ClassFileCacheFolder*/ folders = new HashMap(); + + public ClassFileCache(IContainer container, IMessageHandler handler) { +// super(container); + this.container = container; + this.handler = handler; + try { + getFolder(new Path("")).create(true, true, null); + } catch (CoreException e) { + throw new RuntimeException("can't happen"); + } + } + + private Object makeKey(IPath path) { + return path.toString(); //??? make sure this is stable + } + + public boolean exists(IPath path) { + if (folders.keySet().contains(makeKey(path))) { + return getFolder(path).exists(); + } else { + return getFile(path).exists(); //??? what if this is called for a folder + } + } + + public IFile getFile(IPath path) { + EclipseUnwovenClassFile cachedFile = (EclipseUnwovenClassFile)cache.get(makeKey(path)); + if (cachedFile == null) { + cachedFile = new EclipseUnwovenClassFile(container.getFile(path), handler); + cache.put(makeKey(path), cachedFile); + } + + return cachedFile.getFile(); + } + + public IFolder getFolder(IPath path) { + //??? too naive + ClassFileCacheFolder folder = (ClassFileCacheFolder)folders.get(makeKey(path)); + if (folder == null) { + folder = new ClassFileCacheFolder(this, path, container.getFolder(path)); + folders.put(makeKey(path), folder); + } + return folder; + } + + //XXX this doesn't include folders, is that okay? + public IResource[] members() throws CoreException { + List ret = new ArrayList(); + for (Iterator i = cache.values().iterator(); i.hasNext(); ) { + EclipseUnwovenClassFile cachedFile = (EclipseUnwovenClassFile)i.next(); + ret.add(cachedFile.getFile()); + } + return (IResource[])ret.toArray(new IResource[ret.size()]); + } + + // extra methods for incremental use + public void resetIncrementalInfo() { + for (Iterator i = cache.values().iterator(); i.hasNext(); ) { + EclipseUnwovenClassFile cachedFile = (EclipseUnwovenClassFile)i.next(); + DeferredWriteFile file = (DeferredWriteFile)cachedFile.getFile(); + file.setDirty(false); + } + } + + public List getDeleted() { + List ret = new ArrayList(); + for (Iterator i = cache.values().iterator(); i.hasNext(); ) { + EclipseUnwovenClassFile cachedFile = (EclipseUnwovenClassFile)i.next(); + DeferredWriteFile file = (DeferredWriteFile)cachedFile.getFile(); + if (file.isDirty() && !file.exists()) { + ret.add(cachedFile); + } + } + return ret; + } + + public List getAddedOrChanged() { + List ret = new ArrayList(); + for (Iterator i = cache.values().iterator(); i.hasNext(); ) { + EclipseUnwovenClassFile cachedFile = (EclipseUnwovenClassFile)i.next(); + DeferredWriteFile file = (DeferredWriteFile)cachedFile.getFile(); + if (file.isDirty() && file.exists()) { + ret.add(cachedFile); + } + } + return ret; + } + + + public IResource findMember(IPath path) { + throw new RuntimeException("unimplemented"); + } + + public void copy( + IPath destination, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void delete(boolean force, IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public boolean exists() { + return true; + } + + + public IPath getFullPath() { + return container.getFullPath(); + } + + public IPath getLocation() { + return container.getLocation(); + } + + public long getModificationStamp() { + throw new RuntimeException("unimplemented"); + } + + public String getName() { + return container.getName(); + } + + public IContainer getParent() { + return null; + } + + public int getType() { + return IResource.FOLDER; + } + + public boolean isDerived() { + return true; + } + public void setDerived(boolean isDerived) { + if (isDerived) return; + throw new RuntimeException("unimplemented"); + } + + public boolean isReadOnly() { + return false; + } + + public void setReadOnly(boolean readOnly) { + throw new RuntimeException("unimplemented"); + } + + public void touch(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClassFileCacheFolder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClassFileCacheFolder.java new file mode 100644 index 000000000..52eae60da --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClassFileCacheFolder.java @@ -0,0 +1,140 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import org.aspectj.workbench.resources.AbstractFolder; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +public class ClassFileCacheFolder extends AbstractFolder { + ClassFileCache parent; + IPath myPath; + boolean exists; + IFolder folder; + + public ClassFileCacheFolder(ClassFileCache parent, IPath path, IFolder folder) { + this.folder = folder; + this.myPath = path; + this.parent = parent; + } + + + public IFile getFile(IPath path) { + return parent.getFile(myPath.append(path)); + } + + public IFolder getFolder(IPath path) { + return parent.getFolder(myPath.append(path)); + } + + public IResource[] members() throws CoreException { + throw new RuntimeException("unimplemented"); + } + + + public void create(boolean force, boolean local, IProgressMonitor monitor) + throws CoreException + { + exists = true; + //XXX is this sufficient +// super.create(force, local, monitor); + } + + public boolean exists() { + return exists; + } + + public boolean exists(IPath path) { + if (exists) { + return parent.exists(myPath.append(path)); + } else { + return false; + } + } + + /** + * @see org.eclipse.core.resources.IResource#delete(boolean, IProgressMonitor) + */ + public void delete(boolean force, IProgressMonitor monitor) + throws CoreException { + exists = false; + } + + + public void move( + IPath destination, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("not implemented"); + } + + public IResource findMember(IPath path) { + throw new RuntimeException("unimplemented"); + } + + public void copy( + IPath destination, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IPath getFullPath() { + throw new RuntimeException("unimplemented"); + } + + public IPath getLocation() { + throw new RuntimeException("unimplemented"); + } + + public long getModificationStamp() { + throw new RuntimeException("unimplemented"); + } + + public String getName() { + throw new RuntimeException("unimplemented"); + } + + public IContainer getParent() { + throw new RuntimeException("unimplemented"); + } + + public int getType() { + return IResource.FOLDER; + } + + public boolean isDerived() { + return true; + } + public void setDerived(boolean isDerived) { + if (isDerived) return; + throw new RuntimeException("unimplemented"); + } + + public boolean isReadOnly() { + throw new RuntimeException("unimplemented"); + } + + public void setReadOnly(boolean readOnly) { + throw new RuntimeException("unimplemented"); + } + + public void touch(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClasspathContainer.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClasspathContainer.java new file mode 100644 index 000000000..08d4e8bee --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClasspathContainer.java @@ -0,0 +1,81 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import org.eclipse.jdt.internal.core.builder.*; +import org.aspectj.util.FileUtil; +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.util.Util; + +import java.io.*; + +class ClasspathContainer extends ClasspathLocation { + + IContainer container; + + ClasspathContainer(IContainer container) { + this.container = container; + } + + public void cleanup() { + } + + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof ClasspathContainer)) + return false; + + return container.equals(((ClasspathContainer) o).container); + } + + public NameEnvironmentAnswer findClass( + String binaryFileName, + String qualifiedPackageName, + String qualifiedBinaryFileName) + { + IFile file = container.getFile(makePath(qualifiedBinaryFileName)); + if (!file.exists()) return null; + + try { + byte[] classFileBytes = Util.getInputStreamAsByteArray(file.getContents(), -1); + ClassFileReader reader = + new ClassFileReader(classFileBytes, file.getFullPath().toString().toCharArray()); + return new NameEnvironmentAnswer(reader); + } catch (Exception e) { + } // treat as if class file is missing + return null; + } + + public boolean isPackage(String qualifiedPackageName) { + return container.getFolder(makePath(qualifiedPackageName)).exists(); + } + + private IPath makePath(String qualifiedPackageName) { + return new Path(qualifiedPackageName); + } + + + public void reset() { + } + + public String toString() { + return "Container classpath directory " + container; //$NON-NLS-1$ + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClasspathSourcefiles.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClasspathSourcefiles.java new file mode 100644 index 000000000..7bf742b6d --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/ClasspathSourcefiles.java @@ -0,0 +1,42 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.util.List; + +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.core.builder.ClasspathLocation; + +public class ClasspathSourcefiles extends ClasspathLocation { + private List/*File*/ files; + private String[] knownFileNames; + + public ClasspathSourcefiles(List files) { + this.files = files; + } + + //XXX this doesn't always work + public NameEnvironmentAnswer findClass( + String binaryFileName, + String qualifiedPackageName, + String qualifiedBinaryFileName) + { + return null; + } + + public boolean isPackage(String qualifiedPackageName) { + return false; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/CommandLineResourceDelta.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/CommandLineResourceDelta.java new file mode 100644 index 000000000..79e48ff53 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/CommandLineResourceDelta.java @@ -0,0 +1,82 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import org.apache.bcel.generic.RETURN; +import org.aspectj.workbench.resources.FilesystemFile; +import org.eclipse.core.internal.events.*; +import org.eclipse.core.internal.resources.ResourceInfo; +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.runtime.IPath; + +public class CommandLineResourceDelta extends ResourceDelta { + + private int kind; + private IResource resource; + + public CommandLineResourceDelta(IResource resource) { + super(resource.getFullPath(), null); + setNewInfo(new ResourceInfo()); + setOldInfo(new ResourceInfo()); + children = new ResourceDelta[0]; + this.resource = resource; + } + + public void setKind(int kind) { + this.kind = kind; + if (kind == IResourceDelta.CHANGED) { + status |= IResourceDelta.CONTENT; // ??? is this alwyas right + } + } + + public int getKind() { + return kind; + } + + public void setChildren(IResourceDelta[] children) { + this.children = children; + } + + public IResource getResource() { + return resource; + } + + public String toString() { + return super.toDeepDebugString(); +// StringBuffer s = new StringBuffer(); +// s.append("ResourceDelta("); +// s.append("path: " + path); +// s.append(","); +// s.append("kind: "); +// s.append(kind); +// if (children != null) { +// for (int i = 0; i < children.length; i++) { +// s.append(children[i].toString()); +// } +// } +// s.append(")"); +// return s.toString(); + } + public IResourceDelta findMember(IPath path) { + if (resource.getFullPath().equals(path)) { + return this; + } else { + for (int i = 0; i < children.length; i++) { + return children[i].findMember(path); + } + } + return null; + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/DeferredWriteFile.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/DeferredWriteFile.java new file mode 100644 index 000000000..8f7fd3f19 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/DeferredWriteFile.java @@ -0,0 +1,179 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.*; + +import org.aspectj.workbench.resources.AbstractFile; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.internal.compiler.util.Util; + +public class DeferredWriteFile extends AbstractFile { + + private IFile file; + private byte[] unwovenBytes; + private boolean dirty = false; + + public DeferredWriteFile(IFile file) { + this.file = file; + } + + public byte[] getUnwovenBytes() { + return unwovenBytes; + } + + public void writeInnerWovenBytes(String innerName, byte[] bytes) throws CoreException { + IContainer folder = file.getParent(); + IFile innerFile = folder.getFile(new Path(makeInnerName(innerName))); + innerFile.create(new ByteArrayInputStream(bytes), true, null); + + } + + private String makeInnerName(String innerName) { + String filename = file.getName(); + String prefix = filename.substring(0, filename.length()-6); // strip the .class + return prefix + "$" + innerName + ".class"; + } + + + + public void writeWovenBytes(byte[] wovenBytes) throws CoreException { + file.create(new ByteArrayInputStream(wovenBytes), true, null); + } + + public void create( + InputStream source, + boolean force, + IProgressMonitor monitor) + throws CoreException + { + try { + dirty = true; + unwovenBytes = + Util.getInputStreamAsByteArray(source, -1); + //??? understand this betterwriteWovenBytes(unwovenBytes); + } catch (IOException e) { + throw new JavaModelException( + e, + IJavaModelStatusConstants.IO_EXCEPTION); + } + } + + public void delete(boolean force, IProgressMonitor monitor) + throws CoreException { + //System.out.println("delete: " + this); + unwovenBytes = null; + dirty = true; + } + + public InputStream getContents(boolean force) throws CoreException { + return new ByteArrayInputStream(unwovenBytes); + } + + + public boolean exists() { + return unwovenBytes != null; + } + + public boolean isDirty() { + return dirty; + } + + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + public void deleteRealFile() throws CoreException { + file.delete(true, null); + } + + public String toString() { + return "DeferredWriteFile(" + getName() + ", " + exists() + ")"; + } + + public IContainer getParent() { + throw new RuntimeException("unimplemented"); + } + + public int getEncoding() throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void setContents( + InputStream source, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void copy( + IPath destination, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public String getFileExtension() { + return file.getFileExtension(); + } + + public IPath getFullPath() { + return file.getFullPath(); + } + + public IPath getLocation() { + return file.getLocation(); + } + + public long getModificationStamp() { + throw new RuntimeException("unimplemented"); + } + + public String getName() { + return file.getName(); + } + + public int getType() { + return IResource.FILE; + } + + public boolean isDerived() { + return true; + } + + public void setDerived(boolean isDerived) { + if (isDerived) return; + throw new RuntimeException("unimplemented"); + } + + public boolean isReadOnly() { + return false; + } + + public void setReadOnly(boolean readOnly) { + throw new RuntimeException("unimplemented"); + } + + public void touch(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java new file mode 100644 index 000000000..c19efc2e7 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java @@ -0,0 +1,141 @@ +/* ******************************************************************* + * Copyright (c) 1999-2001 Xerox Corporation, + * 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.core.builder; + +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.Message; +import org.aspectj.bridge.SourceLocation; +import org.aspectj.util.LangUtil; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.util.Util; + +import java.io.File; + +/** + * + */ +public class EclipseAdapterUtils { + + //XXX some cut-and-paste from eclipse sources + public static String makeLocationContext(ICompilationUnit compilationUnit, IProblem problem) { + //extra from the source the innacurate token + //and "highlight" it using some underneath ^^^^^ + //put some context around too. + + //this code assumes that the font used in the console is fixed size + + //sanity ..... + int startPosition = problem.getSourceStart(); + int endPosition = problem.getSourceEnd(); + + if ((startPosition > endPosition) + || ((startPosition <= 0) && (endPosition <= 0))) + return Util.bind("problem.noSourceInformation"); //$NON-NLS-1$ + + final char SPACE = '\u0020'; + final char MARK = '^'; + final char TAB = '\t'; + char[] source = compilationUnit.getContents(); + //the next code tries to underline the token..... + //it assumes (for a good display) that token source does not + //contain any \r \n. This is false on statements ! + //(the code still works but the display is not optimal !) + + //compute the how-much-char we are displaying around the inaccurate token + int begin = startPosition >= source.length ? source.length - 1 : startPosition; + int relativeStart = 0; + int end = endPosition >= source.length ? source.length - 1 : endPosition; + int relativeEnd = 0; + label : for (relativeStart = 0;; relativeStart++) { + if (begin == 0) + break label; + if ((source[begin - 1] == '\n') || (source[begin - 1] == '\r')) + break label; + begin--; + } + label : for (relativeEnd = 0;; relativeEnd++) { + if ((end + 1) >= source.length) + break label; + if ((source[end + 1] == '\r') || (source[end + 1] == '\n')) { + break label; + } + end++; + } + //extract the message form the source + char[] extract = new char[end - begin + 1]; + System.arraycopy(source, begin, extract, 0, extract.length); + char c; + //remove all SPACE and TAB that begin the error message... + int trimLeftIndex = 0; + while (((c = extract[trimLeftIndex++]) == TAB) || (c == SPACE)) { + }; + System.arraycopy( + extract, + trimLeftIndex - 1, + extract = new char[extract.length - trimLeftIndex + 1], + 0, + extract.length); + relativeStart -= trimLeftIndex; + //buffer spaces and tabs in order to reach the error position + int pos = 0; + char[] underneath = new char[extract.length]; // can't be bigger + for (int i = 0; i <= relativeStart; i++) { + if (extract[i] == TAB) { + underneath[pos++] = TAB; + } else { + underneath[pos++] = SPACE; + } + } + //mark the error position + for (int i = startPosition; + i <= (endPosition >= source.length ? source.length - 1 : endPosition); + i++) + underneath[pos++] = MARK; + //resize underneathto remove 'null' chars + System.arraycopy(underneath, 0, underneath = new char[pos], 0, pos); + + return new String(extract) + "\n" + new String(underneath); //$NON-NLS-2$ //$NON-NLS-1$ + } + + public static ISourceLocation makeSourceLocation(ICompilationUnit unit, IProblem problem) { + int line = problem.getSourceLineNumber(); + File file = new File(new String(problem.getOriginatingFileName())); + return new SourceLocation(file, line, line, 0); + } + + /** This renders entire message text, but also sets up source location */ + public static IMessage makeMessage(ICompilationUnit unit, IProblem problem) { + //??? would like to know the column as well as line + //??? and also should generate highlighting info + ISourceLocation sourceLocation = makeSourceLocation(unit, problem); + + String locationContext = makeLocationContext(unit, problem); + StringBuffer mssg = new StringBuffer(); + + mssg.append(problem.getOriginatingFileName()); + mssg.append(":" + problem.getSourceLineNumber()); + mssg.append(": "); + mssg.append(problem.getMessage()); + mssg.append(LangUtil.EOL); + mssg.append(locationContext); + + return new Message(mssg.toString(), sourceLocation, problem.isError()); + } + + private EclipseAdapterUtils() { + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseMessageHandler.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseMessageHandler.java new file mode 100644 index 000000000..4d77254db --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseMessageHandler.java @@ -0,0 +1,190 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.*; + +import org.aspectj.bridge.*; +import org.eclipse.jdt.core.compiler.*; +import org.eclipse.jdt.internal.compiler.env.*; +import org.eclipse.jdt.internal.compiler.problem.*; +import org.eclipse.jdt.internal.compiler.util.*; + +/** @deprecated EclipseMessageAdapter */ +public class EclipseMessageHandler { // implements IMessageHandler { + IMessageHandler handler; + private int errorCount = 0; + + private EclipseMessageHandler(IMessageHandler handler) { + super(); + this.handler = handler; + } +} + +// private IMessage makeMessage(ICompilationUnit unit, IProblem problem) { +// //??? would like to know the column as well as line +// //??? and also should generate highlighting info +// int line = problem.getSourceLineNumber(); +// SourceLocation loc = +// new SourceLocation(new File(new String(problem.getOriginatingFileName())), +// line, line, 0); +// +// String locationContext = makeLocationContext(unit, problem); +//// System.err.println("(" + locationContext + ")"); +// +// return new CommandLineMessage(problem.getMessage(), +// problem.isError() ? IMessage.ERROR : IMessage.WARNING, +// null, loc, locationContext); +// } +// +// +// //XXX some cut-and-paste from eclipse sources +// public String makeLocationContext(ICompilationUnit compilationUnit, IProblem problem) { +// //extra from the source the innacurate token +// //and "highlight" it using some underneath ^^^^^ +// //put some context around too. +// +// //this code assumes that the font used in the console is fixed size +// +// //sanity ..... +// int startPosition = problem.getSourceStart(); +// int endPosition = problem.getSourceEnd(); +// +// if ((startPosition > endPosition) +// || ((startPosition <= 0) && (endPosition <= 0))) +// return Util.bind("problem.noSourceInformation"); //$NON-NLS-1$ +// +// final char SPACE = '\u0020'; +// final char MARK = '^'; +// final char TAB = '\t'; +// char[] source = compilationUnit.getContents(); +// //the next code tries to underline the token..... +// //it assumes (for a good display) that token source does not +// //contain any \r \n. This is false on statements ! +// //(the code still works but the display is not optimal !) +// +// //compute the how-much-char we are displaying around the inaccurate token +// int begin = startPosition >= source.length ? source.length - 1 : startPosition; +// int relativeStart = 0; +// int end = endPosition >= source.length ? source.length - 1 : endPosition; +// int relativeEnd = 0; +// label : for (relativeStart = 0;; relativeStart++) { +// if (begin == 0) +// break label; +// if ((source[begin - 1] == '\n') || (source[begin - 1] == '\r')) +// break label; +// begin--; +// } +// label : for (relativeEnd = 0;; relativeEnd++) { +// if ((end + 1) >= source.length) +// break label; +// if ((source[end + 1] == '\r') || (source[end + 1] == '\n')) { +// break label; +// } +// end++; +// } +// //extract the message form the source +// char[] extract = new char[end - begin + 1]; +// System.arraycopy(source, begin, extract, 0, extract.length); +// char c; +// //remove all SPACE and TAB that begin the error message... +// int trimLeftIndex = 0; +// while (((c = extract[trimLeftIndex++]) == TAB) || (c == SPACE)) { +// }; +// System.arraycopy( +// extract, +// trimLeftIndex - 1, +// extract = new char[extract.length - trimLeftIndex + 1], +// 0, +// extract.length); +// relativeStart -= trimLeftIndex; +// //buffer spaces and tabs in order to reach the error position +// int pos = 0; +// char[] underneath = new char[extract.length]; // can't be bigger +// for (int i = 0; i <= relativeStart; i++) { +// if (extract[i] == TAB) { +// underneath[pos++] = TAB; +// } else { +// underneath[pos++] = SPACE; +// } +// } +// //mark the error position +// for (int i = startPosition; +// i <= (endPosition >= source.length ? source.length - 1 : endPosition); +// i++) +// underneath[pos++] = MARK; +// //resize underneathto remove 'null' chars +// System.arraycopy(underneath, 0, underneath = new char[pos], 0, pos); +// +// return new String(extract) + "\n" + new String(underneath); //$NON-NLS-2$ //$NON-NLS-1$ +// } +// +// +// public boolean handleProblem(ICompilationUnit unit, IProblem problem) { +// return handleMessage(makeMessage(unit, problem)); +// } +// +// public boolean handleThrowable(Throwable t) { +// return handleThrowable(t.toString(), t); +// } +// +// public boolean handleThrowable(String message, Throwable t) { +// return handleMessage(new Message(message, IMessage.ERROR, t, null)); +// } +// +// public boolean handleMessage(IMessage message) throws AbortException { +// if (message.getKind() == Message.ERROR) errorCount++; +// +// //XXX Mik and Jim will figure out what this is doing +// if (message.getKind() == Message.ERROR || message.getKind() == Message.WARNING) { +// ISourceLocation loc = message.getISourceLocation(); +// String msg = message.getMessage(); +// if (loc == null) { +// System.err.println(msg); +// } else { +// StringBuffer buf = new StringBuffer(); +// buf.append(loc.getSourceFile().getPath() + ":" + loc.getLine()); +// if (loc.getColumn() != -1) { +// buf.append(":" + loc.getColumn()); +// } +// buf.append(": "); +// buf.append(msg); +// buf.append("\n"); +// if (message instanceof CommandLineMessage) { +// buf.append(((CommandLineMessage)message).getLocationContext()); +// } +// System.err.println(buf.toString()); +// } +// +// } +// return handler.handleMessage(message); +// } +// +// public boolean isIgnoring(IMessage.Kind kind) { +// return handler.isIgnoring(kind); +// } +// +// public boolean handleError(String string) { +// return handleMessage(new Message(string, IMessage.ERROR, null, null)); +// } +// +// public int getErrorCount() { +// return errorCount; +// } +// +// public void resetErrorCount() { +// this.errorCount = 0; +// } + + diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java new file mode 100644 index 000000000..e398a9d84 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java @@ -0,0 +1,37 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.weaver.*; +import org.aspectj.weaver.ISourceContext; +import org.eclipse.jdt.internal.compiler.CompilationResult; + + + +public class EclipseSourceContext implements ISourceContext { + + CompilationResult result; + + public EclipseSourceContext(CompilationResult result) { + this.result = result; + } + + + public ISourceLocation makeSourceLocation(IHasPosition position) { + return new EclipseSourceLocation(result, position.getStart(), position.getEnd()); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseUnwovenClassFile.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseUnwovenClassFile.java new file mode 100644 index 000000000..a3008b49d --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseUnwovenClassFile.java @@ -0,0 +1,113 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.IOException; +import java.util.*; +import java.util.List; + +import org.aspectj.weaver.bcel.UnwovenClassFile; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.bridge.Message; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import sun.misc.MessageUtils; + +public class EclipseUnwovenClassFile extends UnwovenClassFile { + + private DeferredWriteFile file = null; + private IMessageHandler handler = null; + + public EclipseUnwovenClassFile(IFile file, IMessageHandler handler) { + super(null, null); + this.file = new DeferredWriteFile(file); + this.handler = handler; + } + + public String getFilename() { + return getFile().getLocation().toString(); + } + + + public IFile getFile() { + return file; + } + + public void clear() { +// javaClass = null; + } + + public byte[] getBytes() { + bytes = file.getUnwovenBytes(); + return bytes; + } + + public void deleteRealFile() throws IOException { + try { + file.deleteRealFile(); + } catch (CoreException ce) { + throw new RuntimeException("unimplemented"); + } + } + + public UnwovenClassFile makeInnerClassFile( + String innerName, + byte[] bytes) { + throw new RuntimeException("unimplemented"); + } + + public void writeWovenBytes(byte[] bytes, List childClasses) throws IOException { + if (!childClasses.isEmpty()) { + writeChildClasses(childClasses); + } + try { + file.writeWovenBytes(bytes); + handler.handleMessage(new Message("wrote class file: " + file.getLocation().toFile().getAbsolutePath(), IMessage.INFO, null, null)); + } catch (CoreException ce) { + //XXX more difficult than this + throw new IOException(ce.toString()); + } + } + + private void writeChildClasses(List childClasses) throws IOException { + //??? we only really need to delete writtenChildClasses whose + //??? names aren't in childClasses; however, it's unclear + //??? how much that will affect performance + //XXXdeleteAllChildClasses(); + + //XXXchildClasses.removeAll(writtenChildClasses); + + for (Iterator iter = childClasses.iterator(); iter.hasNext();) { + ChildClass childClass = (ChildClass) iter.next(); + writeChildClassFile(childClass.name, childClass.bytes); + + } + + writtenChildClasses = childClasses; + + } + + private void writeChildClassFile(String innerName, byte[] bytes) throws IOException { + try { + file.writeInnerWovenBytes(innerName, bytes); + //handler.handleMessage(new Message("wrote class file: " + file.getLocation().toFile().getAbsolutePath(), IMessage.INFO, null, null)); + } catch (CoreException ce) { + //XXX more difficult than this + throw new IOException(ce.toString()); + } + } + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EmacsStructureModelManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EmacsStructureModelManager.java new file mode 100644 index 000000000..b0ae3eeeb --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EmacsStructureModelManager.java @@ -0,0 +1,217 @@ +/* ******************************************************************* + * Copyright (c) 1999-2001 Xerox Corporation, + * 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import java.util.*; +import java.io.*; +//import org.aspectj.tools.ide.*; +import org.aspectj.asm.*; +//import org.aspectj.ajde.compiler.AjdeCompiler; + +/** + * @author Mik Kersten + */ +public class EmacsStructureModelManager { + + private static final String EXTERN_FILE_SUFFIX = ".ajesym"; + + public EmacsStructureModelManager() { + super(); + } + + public void externalizeModel() { + if (!StructureModelManager.INSTANCE.getStructureModel().isValid()) return; + + try { + Set fileSet = StructureModelManager.INSTANCE.getStructureModel().getFileMap().entrySet(); + for (Iterator it = fileSet.iterator(); it.hasNext(); ) { + ProgramElementNode peNode = (ProgramElementNode)((Map.Entry)it.next()).getValue(); + dumpStructureToFile(peNode); + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + +// private void dumpStructureToFile(ProgramElementNode node) throws IOException { +// String sourceName = node.getSourceLocation().getSourceFilePath(); +// String fileName = sourceName.substring(0, sourceName.lastIndexOf(".")) + EXTERN_FILE_SUFFIX; +// BufferedWriter writer = new BufferedWriter(new FileWriter(new File(fileName))); +// new SExpressionPrinter(writer).printDecls(node); +// writer.flush(); +// } + + private void dumpStructureToFile(ProgramElementNode node) throws IOException { + String sourceName = node.getSourceLocation().getSourceFile().getAbsolutePath(); + String fileName = sourceName.substring(0, sourceName.lastIndexOf(".")) + EXTERN_FILE_SUFFIX; + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(new File(fileName))); + new SExpressionPrinter(writer).printDecls(node); + writer.flush(); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) {} // ignore + } + } + } + + /** + * This class was not written in an OO style. + */ + private static class SExpressionPrinter { + + private BufferedWriter writer = null; + + public SExpressionPrinter(BufferedWriter writer) { + this.writer = writer; + } + + private void printDecls(ProgramElementNode node) { + print("("); + for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) { + // this ignores relations on the compile unit + Object nodeObject = it.next(); + if (nodeObject instanceof ProgramElementNode) { + ProgramElementNode child = (ProgramElementNode)nodeObject; + printDecl(child, true); + } else if (nodeObject instanceof LinkNode) { + LinkNode child = (LinkNode)nodeObject; + printDecl(child.getProgramElementNode(), false); + } + } + print(") "); + } + + private void printDecls(RelationNode node) { + for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) { + // this ignores relations on the compile unit + Object nodeObject = it.next(); + if (nodeObject instanceof LinkNode) { + LinkNode child = (LinkNode)nodeObject; + if (//!child.getProgramElementNode().getKind().equals("stmnt") && + !child.getProgramElementNode().getKind().equals("<undefined>")) { + printDecl(child.getProgramElementNode(), false); +// printDecl(child.getProgramElementNode(), false); + } + } + } + } + + /** + * @param structureNode can be a ProgramElementNode or a LinkNode + */ + private void printDecl(ProgramElementNode node, boolean recurse) { + if (node == null || node.getSourceLocation() == null) return; + String kind = node.getKind().toLowerCase(); + print("("); + print("(" + node.getSourceLocation().getLine() + " . " + node.getSourceLocation().getColumn() + ") "); + print("(" + node.getSourceLocation().getLine() + " . " + node.getSourceLocation().getColumn() + ") "); + print(kind + " "); //2 + + // HACK: + String displayName = node.toString().replace('\"', ' '); + + print("\"" + displayName + "\" "); + if (node.getSourceLocation().getSourceFile().getAbsolutePath() != null) { + print("\"" + fixFilename(node.getSourceLocation().getSourceFile().getAbsolutePath()) + "\""); //4 + } else { + print("nil"); + } + if (node.getSignature() != null) { + print("\"" + node.getDeclaringType() + "\" "); //5 + } else { + print("nil"); + } + + if (!recurse) { + print("nil"); + print("nil"); + print("nil"); + } else { + print("("); + if (node instanceof ProgramElementNode) { + java.util.List relations = ((ProgramElementNode)node).getRelations(); + if (relations != null) { + for (Iterator it = relations.iterator(); it.hasNext(); ) { + RelationNode relNode = (RelationNode)it.next(); + if (relNode.getRelation().getAssociationName().equals(AdviceAssociation.NAME) || + relNode.getRelation().getAssociationName().equals(IntroductionAssociation.NAME)) { + printDecls(relNode); // 6 + } + } + } + } + print(") "); + print("("); + print(") "); + print("("); + Iterator it3 = node.getChildren().iterator(); + if (it3.hasNext()) { + while (it3.hasNext()) { + // this ignores relations on the compile unit + Object nodeObject = it3.next(); + if (nodeObject instanceof ProgramElementNode) { + ProgramElementNode currNode = (ProgramElementNode)nodeObject; + if (//!currNode.isStmntKind() && + !currNode.getKind().equals("<undefined>")) { + printDecl(currNode, true); + } + } + } + } + print(") "); + } + + print(node.getKind().equals("class") ? "t " : "nil "); // 9 +// print(node.getKind().equals("introduction") ? "t " : "nil "); // 10 + print(node.getKind().equals("introduction") ? "nil " : "nil "); // 10 + print("nil "); // 11 + print("nil "); // 12 + print(")"); + } + + String fixFilename(String filename) { + return subst("\\\\", "\\", filename); + } + + private void print(String string) { + try { + writer.write(string + "\n"); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + private String subst(String n, String o, String in) { + int pos = in.indexOf(o); + if (pos == -1) + return in; + return in.substring(0, pos) + + n + + subst(n, o, (in.substring(pos + o.length()))); + } + + private void lose(Error e) { + try { + print("(ERROR \"" + e.toString() + "\")"); + } + catch(Error ex) { } + } + } +} + diff --git a/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java b/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java new file mode 100644 index 000000000..e698d2b40 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java @@ -0,0 +1,562 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + + +package org.aspectj.tools.ajc; + +import org.aspectj.bridge.AbortException; +import org.aspectj.bridge.ICommand; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.bridge.IMessageHolder; +import org.aspectj.bridge.Message; +import org.aspectj.bridge.MessageHandler; +import org.aspectj.bridge.MessageUtil; +import org.aspectj.bridge.ReflectionFactory; +import org.aspectj.bridge.Version; +import org.aspectj.util.LangUtil; + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Programmatic and command-line interface to AspectJ compiler. + * The compiler is an ICommand obtained by reflection. + * Not thread-safe. + */ +public class Main { + + /** @param args the String[] of command-line arguments */ + public static void main(String[] args) throws IOException { + new Main().runMain(args, true); + } + + + /** append nothing if numItems is 0, + * numItems + label + (numItems > 1? "s" : "") otherwise, + * prefixing with " " if sink has content + */ + private static void appendNLabel(StringBuffer sink, String label, int numItems) { + if (0 == numItems) { + return; + } + if (0 < sink.length()) { + sink.append(", "); + } + sink.append(numItems + " "); + if (!LangUtil.isEmpty(label)) { + sink.append(label); + } + if (1 < numItems) { + sink.append("s"); + } + } + + /** control iteration/continuation for command (compiler) */ + protected CommandController controller; + + /** ReflectionFactory identifier for command (compiler) */ + protected String commandName; + + /** client-set message sink */ + private IMessageHolder clientHolder; + + /** internally-set message sink */ + private final MessageHandler ourHandler; + + private int lastFails; + private int lastErrors; + + public Main() { + controller = new CommandController(); + commandName = ReflectionFactory.ECLIPSE; + ourHandler = new MessageHandler(true); + } + + /** + * Run without throwing exceptions but optionally using System.exit(..). + * This sets up a message handler which emits messages immediately, + * so report(boolean, IMessageHandler) only reports total number + * of errors or warnings. + * @param args the String[] command line for the compiler + * @param useSystemExit if true, use System.exit(int) to complete + * unless one of the args is -noExit. + * and signal result (0 no exceptions/error, <0 exceptions, >0 compiler errors). + */ + public void runMain(String[] args, boolean useSystemExit) { + boolean verbose = (-1 != ("" + LangUtil.arrayAsList(args)).indexOf("-verbose")); + IMessageHolder holder = clientHolder; + if (null == holder) { + holder = ourHandler; + if (verbose) { + ourHandler.setInterceptor(MessagePrinter.VERBOSE); + } else { + ourHandler.ignore(IMessage.INFO); + ourHandler.setInterceptor(MessagePrinter.TERSE); + } + } + run(args, holder); + + boolean skipExit = false; + if (useSystemExit && !LangUtil.isEmpty(args)) { // sigh - pluck -noExit + for (int i = 0; i < args.length; i++) { + if ("-noExit".equals(args[i])) { + skipExit = true; + break; + } + } + } + if (useSystemExit && !skipExit) { + systemExit(holder); + } + } + + /** + * Run without using System.exit(..), putting all messages in holder: + * <ul> + * <li>ERROR: compiler error</li> + * <li>WARNING: compiler warning</li> + * <li>FAIL: command error (bad arguments, exception thrown)</li> + * </ul> + * This handles incremental behavior: + * <ul> + * <li>If args include "-incremental", repeat for every input char + * until 'q' is entered.<li> + * <li>If args include "-incrementalTagFile {file}", repeat every time + * we detect that {file} modification time has changed. </li> + * <li>Either way, list files recompiled each time if args includes "-verbose".</li> + * <li>Exit when the commmand/compiler throws any Throwable.</li> + * </ul> + * When complete, this contains all the messages of the final + * run of the command and/or any FAIL messages produced in running + * the command, including any Throwable thrown by the command itself. + * + * @param args the String[] command line for the compiler + * @param holder the MessageHandler sink for messages. + */ + public void run(String[] args, IMessageHolder holder) { + if (LangUtil.isEmpty(args)) { + args = new String[] { "-help" }; + } else if (Arrays.asList(args).contains("-version")) { + System.out.println("AspectJ Compiler " + Version.text); + System.out.println(); + return; + } else if (controller.running()) { + fail(holder, "already running with controller: " + controller, null); + return; + } + args = controller.init(args, holder); + if ((0 < holder.numMessages(IMessage.ERROR, true)) + || (!validArgs(args, controller.incremental(), holder))) { + return; + } + ICommand command = ReflectionFactory.makeCommand(commandName, holder); + if (0 < holder.numMessages(IMessage.ERROR, true)) { + return; + } + try { + boolean verbose = (-1 != ("" + Arrays.asList(args)).indexOf("-verbose")); + boolean passed = command.runCommand(args, holder); + if (report(passed, holder) && controller.incremental()) { + final boolean onCommandLine = controller.commandLineIncremental(); + while (controller.doRepeatCommand()) { + passed = command.repeatCommand(holder); + if (!report(passed, holder)) { + break; + } else { + holder.clearMessages(); + } + } + } + } catch (AbortException ae) { + if (AbortException.ABORT.equals(ae)) { + quit(); + } else { + IMessage message = ae.getIMessage(); + Throwable thrown = ae.getThrown(); + if (null == thrown) { // toss AbortException wrapper + if (null != message) { + holder.handleMessage(message); + } else { + fail(holder, "abort without message", ae); + } + } else if (null == message) { + fail(holder, "aborted", thrown); + } else { + String mssg = MessageUtil.MESSAGE_MOST.renderToString(message); + fail(holder, mssg, thrown); + } + } + } catch (Throwable t) { + fail(holder, "thrown?", t); + } + } + + /** call this to stop after the next iteration of incremental compile */ + public void quit() { + controller.quit(); + } + + /** + * Set holder to be passed all messages. + * When holder is set, messages will not be printed by default. + * @param holder the IMessageHolder sink for all messages + * (use null to restore default behavior) + */ + public void setHolder(IMessageHolder holder) { + clientHolder = holder; + } + + /** + * Nicer messages for some illegal argument combinations + */ + protected boolean validArgs( + String[] args, + boolean incremental, + IMessageHandler handler) { + if (incremental) { + List list = LangUtil.arrayAsList(args); + if (!list.contains("-sourceroots")) { // XXX -sourceroot name + fail(handler, "incremental mode requires -sourceroots", null); + return false; + } + // XXX also check for -argfile, @... or ...[.java|.aj] + } + return true; + } + + /** + * Call System.exit(int) with values derived from the number + * of failures/aborts or errors in messages. + * @param messages the IMessageHolder to interrogate. + * @param messages + */ + protected void systemExit(IMessageHolder messages) { + int num = lastFails; // messages.numMessages(IMessage.FAIL, true); + if (0 < num) { + System.exit(-num); + } + num = lastErrors; // messages.numMessages(IMessage.ERROR, false); + if (0 < num) { + System.exit(num); + } + System.exit(0); + } + + /** Messages to the user */ + protected void outMessage(String message) { // XXX coordinate with MessagePrinter + System.out.print(message); + System.out.flush(); + } + + /** + * Report results from a (possibly-incremental) compile run. + * This delegates to any reportHandler or otherwise + * prints summary counts of errors/warnings to System.err (if any errors) + * or System.out (if only warnings). + * WARNING: this silently ignores other messages like FAIL, + * but clears the handler of all messages when returning true. XXX false + * + * This implementation ignores the pass parameter but + * clears the holder after reporting + * on the assumption messages were handled/printed already. + * (ignoring UnsupportedOperationException from holder.clearMessages()). + * @param pass true result of the command + * @param holder IMessageHolder with messages from the command + * @see reportCommandResults(IMessageHolder) + * @return false if the process should abort + */ + protected boolean report(boolean pass, IMessageHolder holder) { + lastFails = holder.numMessages(IMessage.FAIL, true); + boolean result = (0 == lastFails); + if (holder == ourHandler) { + lastErrors = holder.numMessages(IMessage.ERROR, false); + int warnings = holder.numMessages(IMessage.WARNING, false); + StringBuffer sb = new StringBuffer(); + appendNLabel(sb, "fail|abort", lastFails); + appendNLabel(sb, "error", lastErrors); + appendNLabel(sb, "warning", warnings); + if (0 < sb.length()) { + PrintStream out = (0 < (lastErrors + lastFails) + ? System.err + : System.out); + out.println(""); // XXX "wrote class file" messages no eol? + out.println(sb.toString()); + if (false) { // printed elsewhere so printed when found + if (0 < lastFails) { + MessageUtil.print(System.err, holder, "", MessageUtil.MESSAGE_ALL, MessageUtil.PICK_FAIL_PLUS); + } + if (0 < lastErrors) { + MessageUtil.print(System.err, holder, "", MessageUtil.MESSAGE_ALL, MessageUtil.PICK_ERROR); + } + if (0 < warnings) { + MessageUtil.print(System.err, holder, "", MessageUtil.MESSAGE_ALL, MessageUtil.PICK_WARNING); + } + } + } + } + return result; + } + + /** convenience API to make fail messages (without MessageUtils's fail prefix) */ + protected static void fail(IMessageHandler handler, String message, Throwable thrown) { + handler.handleMessage(new Message(message, IMessage.FAIL, thrown, null)); + } + + /** interceptor IMessageHandler to print as we go */ + public static class MessagePrinter implements IMessageHandler { + // XXX change as needed before each release + public static final String THROWN_PREFIX = + "Exception thrown from AspectJ "+ Version.text + LangUtil.EOL + + ""+ LangUtil.EOL + + "Please email to us as follows:" + LangUtil.EOL + + " to: jitterbug@aspectj.org" + LangUtil.EOL + + " subject: top stack trace File:line, e.g., \"SomeFile.java:243\"" + LangUtil.EOL + + " message: copy the entire stack trace." + LangUtil.EOL + + "" + LangUtil.EOL + + "Your message can also request follow-up or provide a workaround." + LangUtil.EOL + + "To make the bug a priority, please include a test program." + LangUtil.EOL + + "" + LangUtil.EOL + + "You may search for duplicate bugs (i.e., known workarounds):" + LangUtil.EOL + + "" + LangUtil.EOL + + "http://aspectj.org/bugs" + LangUtil.EOL + + "http://aspectj.org/bugs/incoming?expression=SomeFile.java:243" + LangUtil.EOL + + "" + LangUtil.EOL; + + public static final IMessageHandler VERBOSE + = new MessagePrinter(true); + public static final IMessageHandler TERSE + = new MessagePrinter(false); + + final boolean verbose; + protected MessagePrinter(boolean verbose) { + this.verbose = verbose; + } + + /** + * Print errors and warnings to System.err, + * and optionally info to System.out, + * rendering message String only. + * @return false always + */ + public boolean handleMessage(IMessage message) { + if (null != message) { + PrintStream out = getStreamFor(message.getKind()); + if (null != out) { + out.println(render(message)); + } + } + return false; + } + + protected String render(IMessage message) { + IMessage.Kind kind = message.getKind(); + if (kind.equals(IMessage.ABORT)) { + Throwable t = message.getThrown(); + if (null == t) { + return "abort (no message)"; + } else { + return render(t); + } + } + String m = message.getMessage(); + if (LangUtil.isEmpty(m)) { + m = message.toString(); + } + return m; + } + + protected String render(Throwable t) { + String m = t.getMessage(); + return THROWN_PREFIX + + (null != m ? m + "\n": "") + + LangUtil.renderException(t, true); + } + + public boolean isIgnoring(IMessage.Kind kind) { + return (null != getStreamFor(kind)); + } + + /** @return System.err for FAIL, ABORT, ERROR, and WARNING, + * System.out for INFO if verbose. + */ + protected PrintStream getStreamFor(IMessage.Kind kind) { + if (IMessage.FAIL.equals(kind) + || IMessage.ERROR.equals(kind) + || IMessage.WARNING.equals(kind) + || IMessage.ABORT.equals(kind)) { + return System.err; + } else if (verbose && IMessage.INFO.equals(kind)) { + return System.out; + } else { + return null; + } + } + } + + /** controller for repeatable command delays until input or file changed or removed */ + public static class CommandController { + public static String TAG_FILE_OPTION = "-XincrementalFile"; + public static String INCREMENTAL_OPTION = "-incremental"; + + /** maximum 10-minute delay between filesystem checks */ + public static long MAX_DELAY = 1000 * 600; + + /** default 5-second delay between filesystem checks */ + public static long DEFAULT_DELAY = 1000 * 5; + + /** @see init(String[]) */ + private static String[][] OPTIONS = new String[][] + { new String[] { INCREMENTAL_OPTION }, + new String[] { TAG_FILE_OPTION, null } }; + + + /** true between init(String[]) and doRepeatCommand() that returns false */ + private boolean running; + + /** true after quit() called */ + private boolean quit; + + /** true if incremental mode, waiting for input other than 'q' */ + private boolean incremental; + + /** true if incremental mode, waiting for file to change (repeat) or disappear (quit) */ + private File tagFile; + + /** last modification time for tagFile as of last command - 0 to start */ + private long fileModTime; + + /** delay between filesystem checks for tagFile modification time */ + private long delay; + + public CommandController() { + delay = DEFAULT_DELAY; + } + + /** + * @param argList read and strip incremental args from this + * @param sink IMessageHandler for error messages + * @return String[] remainder of args + */ + public String[] init(String[] args, IMessageHandler sink) { + running = true; + if (!LangUtil.isEmpty(args)) { + String[][] options = LangUtil.copyStrings(OPTIONS); + args = LangUtil.extractOptions(args, options); + incremental = (null != options[0][0]); + if (null != options[1][0]) { + tagFile = new File(options[1][1]); + if (!tagFile.exists()) { + MessageUtil.abort(sink, "tag file does not exist: " + tagFile); + } + } + } + return args; + } + + /** @return true if init(String[]) called but doRepeatCommand has not + * returned false */ + public boolean running() { + return running; + } + + /** @param delay milliseconds between filesystem checks */ + public void setDelay(long delay) { + if ((delay > -1) && (delay < MAX_DELAY)) { + this.delay = delay; + } + } + + /** @return true if INCREMENTAL_OPTION or TAG_FILE_OPTION was in args */ + public boolean incremental() { + return (incremental || (null != tagFile)); + } + + + /** @return true if INCREMENTAL_OPTION was in args */ + public boolean commandLineIncremental() { + return incremental; + } + + public void quit() { + if (!quit) { + quit = true; + } + } + + /** @return false if we should quit, true to do another command */ + boolean doRepeatCommand() { + if (!running) { + return false; + } + boolean result = false; + if (quit) { + result = false; + } else if (incremental) { + try { + System.out.println(" press enter to recompile (q to quit): "); + System.out.flush(); + boolean doMore = false; + // seek for one q or a series of [\n\r]... + do { + int input = System.in.read(); + if ('q' == input) { + break; // result = false; + } else if (('\n' == input) || ('\r' == input)) { + result = true; + } // else eat anything else + } while (!result); + System.in.skip(Integer.MAX_VALUE); + } catch (IOException e) { // XXX silence for error? + result = false; + } + } else if (null != tagFile) { + long curModTime; + while (true) { + if (!tagFile.exists()) { + result = false; + break; + } else if (fileModTime == (curModTime = tagFile.lastModified())) { + fileCheckDelay(); + } else { + fileModTime = curModTime; + result = true; + break; + } + } + } // else, not incremental - false + if (!result && running) { + running = false; + } + return result; + } + + /** delay between filesystem checks, returning if quit is set */ + protected void fileCheckDelay() { + final Thread thread = Thread.currentThread(); + long targetTime = System.currentTimeMillis() + delay; + long curTime; + while (targetTime > (curTime = System.currentTimeMillis())) { + if (quit) { + return; + } + try { Thread.sleep(300); } // 1/3-second delta for quit check + catch (InterruptedException e) {} + } + } + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractContainer.java b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractContainer.java new file mode 100644 index 000000000..edccbfc3f --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractContainer.java @@ -0,0 +1,64 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.runtime.*; + +public abstract class AbstractContainer extends AbstractResource implements IContainer { + + public AbstractContainer() { + super(); + } + + public abstract boolean exists(IPath path); + + public IFile[] findDeletedMembersWithHistory( + int depth, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IResource findMember(IPath path, boolean includePhantoms) { + return findMember(path); + } + + public abstract IResource findMember(IPath path); + + public IResource findMember(String name, boolean includePhantoms) { + return findMember(new Path(name), includePhantoms); + } + + public IResource findMember(String name) { + return findMember(new Path(name)); + } + + public abstract IFile getFile(IPath path); + + public abstract IFolder getFolder(IPath path); + + public abstract IResource[] members() throws CoreException; + + public IResource[] members(boolean includePhantoms) throws CoreException { + return members(); + } + + public IResource[] members(int memberFlags) throws CoreException { + return members(); + } + + public final String getFileExtension() { return null; } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractFile.java b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractFile.java new file mode 100644 index 000000000..249c3b316 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractFile.java @@ -0,0 +1,121 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import java.io.InputStream; + +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.*; + +public abstract class AbstractFile extends AbstractResource implements IFile { + + public AbstractFile() { + super(); + } + + public void appendContents( + InputStream source, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void appendContents( + InputStream source, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + appendContents(source, isForce(updateFlags), isHistory(updateFlags), monitor); + } + + public abstract void create( + InputStream source, + boolean force, + IProgressMonitor monitor) + throws CoreException; + + public void create( + InputStream source, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + create(source, isForce(updateFlags), monitor); + } + + public void delete( + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + delete(force, monitor); + } + + public InputStream getContents() throws CoreException { + return getContents(true); + } + + public abstract InputStream getContents(boolean force) throws CoreException; + + public abstract int getEncoding() throws CoreException; + + public IFileState[] getHistory(IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void move( + IPath destination, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void setContents( + IFileState source, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + setContents(source.getContents(), force, keepHistory, monitor); + } + + public void setContents( + IFileState source, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + setContents(source.getContents(), updateFlags, monitor); + } + + public abstract void setContents( + InputStream source, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException; + + public void setContents( + InputStream source, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + setContents(source, isForce(updateFlags), isHistory(updateFlags), monitor); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractFolder.java b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractFolder.java new file mode 100644 index 000000000..1e516451e --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractFolder.java @@ -0,0 +1,62 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.runtime.*; + +public abstract class AbstractFolder extends AbstractContainer implements IFolder { + + public AbstractFolder() { + super(); + } + + public abstract void create(boolean force, boolean local, IProgressMonitor monitor) + throws CoreException; + + public void create( + int updateFlags, + boolean local, + IProgressMonitor monitor) + throws CoreException { + create(isForce(updateFlags), local, monitor); + } + + public void delete( + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + delete(force, monitor); + } + + public IFile getFile(String name) { + return getFile(new Path(name)); + } + + public IFolder getFolder(String name) { + return getFolder(new Path(name)); + } + + public void move( + IPath destination, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractResource.java b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractResource.java new file mode 100644 index 000000000..0f2f046ab --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/AbstractResource.java @@ -0,0 +1,248 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +public abstract class AbstractResource implements IResource { + + public AbstractResource() { + super(); + } + + public void accept(IResourceVisitor visitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void accept( + IResourceVisitor visitor, + int depth, + boolean includePhantoms) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void accept(IResourceVisitor visitor, int depth, int memberFlags) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void clearHistory(IProgressMonitor monitor) throws CoreException { + // nothing to do + } + + public void copy( + IProjectDescription description, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public abstract void copy( + IPath destination, + boolean force, + IProgressMonitor monitor) + throws CoreException; + + public void copy( + IProjectDescription description, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void copy( + IPath destination, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + copy(destination, isForce(updateFlags), monitor); + } + + protected static boolean isForce(int updateFlags) { + return (updateFlags & IResource.FORCE) != 0; + } + + protected static boolean isHistory(int updateFlags) { + return (updateFlags & IResource.KEEP_HISTORY) != 0; + } + + public IMarker createMarker(String type) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public abstract void delete(boolean force, IProgressMonitor monitor) + throws CoreException; + + public void delete(int updateFlags, IProgressMonitor monitor) + throws CoreException { + delete(isForce(updateFlags), monitor); + } + + public void deleteMarkers(String type, boolean includeSubtypes, int depth) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public abstract boolean exists(); + + public IMarker findMarker(long id) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IMarker[] findMarkers( + String type, + boolean includeSubtypes, + int depth) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public abstract String getFileExtension(); + + public abstract IPath getFullPath(); + + public abstract IPath getLocation(); + + public IMarker getMarker(long id) { + throw new RuntimeException("unimplemented"); + } + + public abstract long getModificationStamp(); + + public abstract String getName(); + + public abstract IContainer getParent(); + + public String getPersistentProperty(QualifiedName key) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IProject getProject() { + throw new RuntimeException("unimplemented"); + } + + public IPath getProjectRelativePath() { + throw new RuntimeException("unimplemented"); + } + + public Object getSessionProperty(QualifiedName key) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public abstract int getType(); + + public IWorkspace getWorkspace() { + throw new RuntimeException("unimplemented"); + } + + public boolean isAccessible() { + return exists(); + } + + public boolean isLocal(int depth) { + return true; + } + + public boolean isPhantom() { + return false; + } + + public abstract boolean isReadOnly(); + + public boolean isSynchronized(int depth) { + return true; + } + + public void move( + IProjectDescription description, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void move( + IPath destination, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); //??? we could make abstract + } + + public void move( + IProjectDescription description, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void move( + IPath destination, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + move(destination, isForce(updateFlags), monitor); + } + + public void refreshLocal(int depth, IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void setLocal(boolean flag, int depth, IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void setPersistentProperty(QualifiedName key, String value) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public abstract void setReadOnly(boolean readOnly); + + public void setSessionProperty(QualifiedName key, Object value) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public abstract void touch(IProgressMonitor monitor) throws CoreException; + + public abstract boolean isDerived(); + + public void setDerived(boolean isDerived) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public boolean isTeamPrivateMember() { + return false; + } + + public void setTeamPrivateMember(boolean isTeamPrivate) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public Object getAdapter(Class adapter) { + throw new RuntimeException("unimplemented"); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/FilesystemFile.java b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/FilesystemFile.java new file mode 100644 index 000000000..5c7dbd0bf --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/FilesystemFile.java @@ -0,0 +1,193 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import java.io.*; + +import org.aspectj.util.FileUtil; +import org.eclipse.core.internal.resources.*; +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.*; + +public class FilesystemFile extends AbstractFile implements IFile { + + private java.io.File file; + + public FilesystemFile(String pathname) { + super(); + file = new java.io.File(pathname); + } + + public FilesystemFile(IPath path) { + super(); + file = path.toFile(); + } + + /** + * Closes the source stream. + */ + public void create( + InputStream source, + boolean force, + IProgressMonitor monitor) + throws CoreException { + FileOutputStream destination = null; + try { + try { + byte[] buffer = new byte[Math.max(256, source.available())]; //XXX does available always work? + //??? is this always right + file.getParentFile().mkdirs(); + + destination = new FileOutputStream(file); + + while (true) { + int bytesRead = -1; + bytesRead = source.read(buffer); + // System.out.println("READ: " + bytesRead); + if (bytesRead == -1) + break; + if (bytesRead == 0) { + throw new RuntimeException("read 0 bytes"); + } + destination.write(buffer, 0, bytesRead); + if (monitor != null) monitor.worked(1); + } + } finally { + if (destination != null) destination.close(); + source.close(); + } + } catch (IOException e) { + throw new RuntimeException("unexpected: " + e); + //throw new CoreException(new IStatus() {}); + } + } + + public InputStream getContents(boolean force) throws CoreException { + try { + return new FileInputStream(file); + } catch (FileNotFoundException fnfe) { + throw new CoreException(null); + } + } + + public int getEncoding() throws CoreException { + return 0; + } + + public void setContents( + InputStream source, + boolean force, + boolean keepHistory, + IProgressMonitor monitor) + throws CoreException { + create(source, force, monitor); + } + + public void copy( + IPath destination, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public java.io.File getFile() { + return file; + } + + public void delete(boolean force, IProgressMonitor monitor) + throws CoreException + { + if (!file.delete()) { + throw new RuntimeException("couldn't delete: " + this); //XXX should be CoreException + } + } + + public boolean exists() { + return file.exists() && file.isFile(); + } + + public String getFileExtension() { + String fileName = file.getName(); + int dotIndex = fileName.indexOf('.'); + if (dotIndex != -1) { + return fileName.substring(dotIndex+1); + } else { + return null; + } + } + + public IPath getFullPath() { + return new Path(file.getPath()); + } + + public IPath getLocation() { + return new Path(file.getAbsolutePath()); + } + + public long getModificationStamp() { + return file.lastModified(); + } + + public String getName() { + return file.getName(); + } + + /** + * This will create a new instance of a folder rather than looking up a new + * folder first. + * + * ??? is the above correct + */ + public IContainer getParent() { + return new FilesystemFolder(file.getParent()); + } + + public int getType() { + return IResource.FILE; + } + + public boolean isDerived() { + return false; + } + + public boolean isReadOnly() { + if (!file.canWrite()) { + return true; + } else { + return false; + } + } + + public void setReadOnly(boolean readOnly) { + if (readOnly) { + file.setReadOnly(); + } + } + + public void touch(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public String toString() { + return getFullPath().toString(); + } + +// private IStatus genStatus(Throwable t) { +// return new Status(IStatus.ERROR, "", 0, "file operation failed for: " + file.getName(), t); +// } + + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/FilesystemFolder.java b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/FilesystemFolder.java new file mode 100644 index 000000000..7084f1187 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/FilesystemFolder.java @@ -0,0 +1,134 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import org.apache.bcel.generic.RETURN; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +/** + * When lookup for parent or contained paths is done a new instance of a folder or file + * is returned instead of using an existing instance. + * + * ??? is the above correct behavior + */ +public class FilesystemFolder extends AbstractFolder implements IFolder { + + private java.io.File dir; + + public FilesystemFolder(IPath path) { + super(); + dir = path.toFile(); + } + + + public FilesystemFolder(String pathname) { + super(); + dir = new java.io.File(pathname); + } + + public void create(boolean force, boolean local, IProgressMonitor monitor) + throws CoreException + { + dir.mkdir(); + } + + public void copy( + IPath destination, + boolean force, + IProgressMonitor monitor) + throws CoreException + { + throw new RuntimeException("unimplemented"); + } + + public void delete(boolean force, IProgressMonitor monitor) + throws CoreException { + dir.delete(); + } + + public boolean exists() { + return dir.exists() && dir.isDirectory(); + } + + public IPath getFullPath() { + return new Path(dir.getPath()); + } + + public IPath getLocation() { + return new Path(dir.getAbsolutePath()); + } + + public long getModificationStamp() { + return dir.lastModified(); + } + + public String getName() { + return dir.getName(); + } + + public int getType() { + return IResource.FILE; + } + + public boolean isReadOnly() { + return !dir.canWrite(); + } + + public void setReadOnly(boolean readOnly) { + if (readOnly) dir.setReadOnly(); + } + + public void touch(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public boolean isDerived() { + return false; + } + + public IContainer getParent() { + return new FilesystemFolder(dir.getParent()); + } + + public boolean exists(IPath path) { + String pathString = new java.io.File(path.toString()).getAbsolutePath(); + String dirPathString = dir.getAbsolutePath(); + return pathString.startsWith(dirPathString); + } + + public IFile getFile(IPath path) { + return new FilesystemFile(dir.getPath() + java.io.File.separator + path.toString()); + } + + public IFolder getFolder(IPath path) { + return new FilesystemFolder(dir.getPath() + java.io.File.separator + path.toString()); + } + + public IResource[] members() throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IResource findMember(IPath path) { + throw new RuntimeException("unimplemented"); + } + /** + * @return the full path + * ??? is this wrong + */ + public IPath getProjectRelativePath() { + return getFullPath(); + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/SimpleProject.java b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/SimpleProject.java new file mode 100644 index 000000000..8cc422798 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/workbench/resources/SimpleProject.java @@ -0,0 +1,136 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import java.util.*; + +import org.eclipse.core.internal.resources.*; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +public class SimpleProject extends FilesystemFolder implements IProject { + IProjectDescription description; + + public SimpleProject(IPath path, String name) { + super(path.toString()); + description = new ProjectDescription(); + description.setName(name); + description.setLocation(path); + } + + public void build( + int kind, + String builderName, + Map args, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void build(int kind, IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void close(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void create( + IProjectDescription description, + IProgressMonitor monitor) + throws CoreException { + create(monitor); + } + + public void create(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void delete( + boolean deleteContent, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IProjectDescription getDescription() throws CoreException { + return description; + } + + public IFile getFile(String name) { + throw new RuntimeException("unimplemented"); + } + + public IFolder getFolder(String name) { + throw new RuntimeException("unimplemented"); + } + + public IProjectNature getNature(String natureId) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IPath getPluginWorkingLocation(IPluginDescriptor plugin) { + throw new RuntimeException("unimplemented"); + } + + public IProject[] getReferencedProjects() throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public IProject[] getReferencingProjects() { + throw new RuntimeException("unimplemented"); + } + + public boolean hasNature(String natureId) throws CoreException { + return false; + } + + public boolean isNatureEnabled(String natureId) throws CoreException { + return false; + } + + public boolean isOpen() { + return false; + } + + public void move( + IProjectDescription description, + boolean force, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void open(IProgressMonitor monitor) throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void setDescription( + IProjectDescription description, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + + public void setDescription( + IProjectDescription description, + int updateFlags, + IProgressMonitor monitor) + throws CoreException { + throw new RuntimeException("unimplemented"); + } + +} diff --git a/org.aspectj.ajdt.core/testdata/Hello.txt b/org.aspectj.ajdt.core/testdata/Hello.txt new file mode 100644 index 000000000..72c6c3506 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/Hello.txt @@ -0,0 +1,13 @@ + class Hello extends java.lang.Object: + void <init>(): + ALOAD_0 // Hello this + INVOKESPECIAL java.lang.Object.<init> ()V + RETURN + end void <init>() + + public static void main(String[]): + GETSTATIC A.ajc$perSingletonInstance LA; + INVOKEVIRTUAL A.ajc_before_1 ()V + RETURN + end public static void main(String[]) +end class Hello diff --git a/org.aspectj.ajdt.core/testdata/ajc/A.java b/org.aspectj.ajdt.core/testdata/ajc/A.java new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/ajc/A.java diff --git a/org.aspectj.ajdt.core/testdata/ajc/B.java b/org.aspectj.ajdt.core/testdata/ajc/B.java new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/ajc/B.java diff --git a/org.aspectj.ajdt.core/testdata/ajc/X.aj b/org.aspectj.ajdt.core/testdata/ajc/X.aj new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/ajc/X.aj diff --git a/org.aspectj.ajdt.core/testdata/ajc/Y.aj b/org.aspectj.ajdt.core/testdata/ajc/Y.aj new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/ajc/Y.aj diff --git a/org.aspectj.ajdt.core/testdata/ajc/pkg/Hello.java b/org.aspectj.ajdt.core/testdata/ajc/pkg/Hello.java new file mode 100644 index 000000000..69728b337 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/ajc/pkg/Hello.java @@ -0,0 +1,3 @@ +package pkg; + +public class Hello {}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/lintspec.properties b/org.aspectj.ajdt.core/testdata/lintspec.properties new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/lintspec.properties diff --git a/org.aspectj.ajdt.core/testdata/resources/empty.txt b/org.aspectj.ajdt.core/testdata/resources/empty.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/resources/empty.txt diff --git a/org.aspectj.ajdt.core/testdata/resources/file.txt b/org.aspectj.ajdt.core/testdata/resources/file.txt new file mode 100644 index 000000000..699b1680f --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/resources/file.txt @@ -0,0 +1,2 @@ +abcd +12345
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/resources/javaFile.txt b/org.aspectj.ajdt.core/testdata/resources/javaFile.txt new file mode 100644 index 000000000..699b1680f --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/resources/javaFile.txt @@ -0,0 +1,2 @@ +abcd +12345
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/.cvsignore b/org.aspectj.ajdt.core/testdata/src1/.cvsignore new file mode 100644 index 000000000..c06bd3c77 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/.cvsignore @@ -0,0 +1,2 @@ +*~ +*.class diff --git a/org.aspectj.ajdt.core/testdata/src1/A.java b/org.aspectj.ajdt.core/testdata/src1/A.java new file mode 100644 index 000000000..9be597f7e --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/A.java @@ -0,0 +1,41 @@ +public aspect A issingleton() { + public void m(int x) { + System.out.println(x); + } + + pointcut foo(String[] args): I.foo(args) && execution(void Hello.*(..)); + + ///XXX add a test for this correctly + //XXXpublic int Hello.fromA; + + before(): execution(* Hello.*(..)) { + System.out.println("enter"); + } + + + public void pingHello(Hello h) { + int x = 2; + System.out.println(x); + } + + public static void main(String[] args) { + Hello.main(args); + } +} + +class Hello { + public static void main(String[] args) { + } +} + + +interface I { + pointcut foo(String[] i): args(i); + + static aspect InnerA { + before(): this(String) { + System.out.println("hi"); + } + } + //void foo(); +} diff --git a/org.aspectj.ajdt.core/testdata/src1/A1.java b/org.aspectj.ajdt.core/testdata/src1/A1.java new file mode 100644 index 000000000..7f82c3631 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/A1.java @@ -0,0 +1,23 @@ +aspect A1 { + after() throwing (Throwable t): execution(* Hello.*(..)) { + System.out.println("enter"); + } + + after() throwing: execution(* Hello.*(..)) { + System.out.println("enter"); + } + + after() returning: execution(* Hello.*(..)) { + System.out.println("enter"); + } + + after(): execution(void Hello.*ai*(..)) { + } +} + + +class Hello { + public static void main(String[] args) { + System.out.println("hello"); + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/A2.java b/org.aspectj.ajdt.core/testdata/src1/A2.java new file mode 100644 index 000000000..c8fd65aa7 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/A2.java @@ -0,0 +1,19 @@ +aspect A2 { + after(Object thisObject): target(thisObject) && execution(public * Hello.*(..)) { + } + after(Object thisObject): this(thisObject) && execution(* Hello.*(..)) { + System.out.println(thisObject); + } + after() returning (String s): execution(* Hello.*(..)) { + //System.out.println(s); + } +} + +class Hello { + public static void main(String[] args) { + System.out.println("hello"); + } + + void m() { + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/Ap.java b/org.aspectj.ajdt.core/testdata/src1/Ap.java new file mode 100644 index 000000000..9975367cf --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Ap.java @@ -0,0 +1,51 @@ +package src1; + +aspect Ap { + public void m(int x) { + System.out.println(x); + } + + pointcut foo(String[] args): args(args) && execution(void Hello.*(..)); + + //pointcut ref(): foo12(); + + before(): execution(* Hello.*(..)) { + System.out.println("enter"); + } + +// before(): get(* java.lang.System.out) { +// System.out.println("exit get"); +// } + + public int Hello.fromA; + + public void pingHello(Hello h) { + int x = 2; //XXXh.fromA; + System.out.println(x); + } + +// after(): abc { +// System.out.println("enter"); +// } +// after() throwing (Throwable t): abc { +// System.out.println("enter"); +// } + +// public int Hello.m() { +// System.out.println("m()"); +// return 10; +// } + +// void around(int x): abc { +// System.out.println("enter"); +// } +} + +class Hello { + public static void main(String[] args) { + } +} + +interface I { + //void foo(); +} diff --git a/org.aspectj.ajdt.core/testdata/src1/AroundA.java b/org.aspectj.ajdt.core/testdata/src1/AroundA.java new file mode 100644 index 000000000..8bc7b2f93 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/AroundA.java @@ -0,0 +1,27 @@ +aspect AroundA { + pointcut foo(): execution(void main(..)); + + int around(int i, boolean b): args(i, b) && foo() { + System.out.println("enter"); + return proceed(10, false); + } + + + void around(Object a): args(a) && foo() { + System.out.println("enter"); + proceed("new: " + a); + System.out.println("exit"); + } + + void around(final String[] a): args(a) && foo() { + Runnable r = new Runnable() { + public void run() { + proceed(a); + } + }; + r.run(); + r.run(); + } +} + +
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/AroundA1.java b/org.aspectj.ajdt.core/testdata/src1/AroundA1.java new file mode 100644 index 000000000..8230a80e0 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/AroundA1.java @@ -0,0 +1,45 @@ +public class AroundA1 { + + public static void main(String[] args) { + System.err.println(new AroundA1().main(3, (short)1, true)); + } + + public int main(int xx, short s, boolean yy) { + System.err.println(xx); + System.err.println(s); + System.err.println(yy); + return 10; + } +} + +aspect MyAroundAspect { + int field = 10; + + pointcut foo(): call(int main(..)); + + Object around(AroundA1 o, int i, boolean b): target(o) && args(i, *, b) && foo() { + System.err.println("enter: " + o + " with " + field); + Object x = proceed(o, 10, false); + System.err.println("got: " + x); + return new Integer(42); + } + + +// void around(Object a): args(a) && foo() { +// System.out.println("enter"); +// proceed("new: " + a); +// System.out.println("exit"); +// } +// +// void around(final String[] a): args(a) && foo() { +// Runnable r = new Runnable() { +// public void run() { +// proceed(a); +// } +// }; +// r.run(); +// r.run(); +// } +} + +
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/BadA.java b/org.aspectj.ajdt.core/testdata/src1/BadA.java new file mode 100644 index 000000000..2529297e9 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/BadA.java @@ -0,0 +1,35 @@ +aspect BadA { + public void m(int x) { + System.out.println(x); + } + +// pointcut foo(): execution(void Hello.*(..)); + pointcut foo1(): abc); + pointcut foo2(): abc ; + + + +// pointcut bar(): this(Bazoo); + + //pointcut foo2(): abc; + //pointcut foo3(): abc; + +// before(): abc { +// System.out.println("enter"); +// } +// after(): abc { +// System.out.println("enter"); +// } +// after() throwing (Throwable t): abc { +// System.out.println("enter"); +// } + +// public int Hello.m() { +// System.out.println("m()"); +// return 10; +// } + +// void around(int x): abc { +// System.out.println("enter"); +// } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/BadBinding.java b/org.aspectj.ajdt.core/testdata/src1/BadBinding.java new file mode 100644 index 000000000..33545b414 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/BadBinding.java @@ -0,0 +1,22 @@ +aspect A2 { + after(Object thisObject1): target(thisObject) { // ERR unbound + } + after(Object o1, Object o2): target(o1) || target(o2) { // ERR inconsistent + } + after(Object o1, Object o2): target(o1) && target(o2) { // NO PROB + } + after(Object o1): target(o1) && target(o1) { // ERR multiple + } + after(Object o1): !target(o1) { // ERR can't bind here + } + void around(Object o1): target(o1) { + proceed(2); //ERR can't convert from int to Object + } + void around(Object o1): target(o1) { + proceed(null, 2); //ERR wrong number of args + } + void around(Object o1): target(o1) { + proceed(); //ERR wrong number of args + } + +} diff --git a/org.aspectj.ajdt.core/testdata/src1/BadHello.java b/org.aspectj.ajdt.core/testdata/src1/BadHello.java new file mode 100644 index 000000000..504e82815 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/BadHello.java @@ -0,0 +1,6 @@ +public class BadHello { + public static void main(String[] args) { + new BadHello().m(); + } + public void m() { return 2; } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/DeclareSoft.java b/org.aspectj.ajdt.core/testdata/src1/DeclareSoft.java new file mode 100644 index 000000000..b42a82453 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/DeclareSoft.java @@ -0,0 +1,26 @@ +import java.io.*; +import org.aspectj.lang.*; + +public class DeclareSoft { + public static void main(String[] args) { + try { + new DeclareSoft().m(); + } catch (SoftException se) { + return; + } + } + + void m() { + InputStream s = new FileInputStream("foobar"); + s.close(); + } +} + + +aspect A { + //declare soft: IOException: execution(void m()); + + declare soft: IOException: foo(); + + pointcut foo(): execution(void m()); +} diff --git a/org.aspectj.ajdt.core/testdata/src1/DeclareWarning.java b/org.aspectj.ajdt.core/testdata/src1/DeclareWarning.java new file mode 100644 index 000000000..0c6ecf6b1 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/DeclareWarning.java @@ -0,0 +1,11 @@ +public class DeclareWarning { + public void m() { // should be error on this line + } +} + +aspect Checker { + declare warning: execution(* m()): "too short method name"; + declare warning: execution(* n()): "too short method name"; // no effect +} + + diff --git a/org.aspectj.ajdt.core/testdata/src1/Declares.java b/org.aspectj.ajdt.core/testdata/src1/Declares.java new file mode 100644 index 000000000..b3c6a065b --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Declares.java @@ -0,0 +1,13 @@ +public class Declares { + public void m() { // should be error on this line + } +} + +aspect Checker { + declare error: execution(* m()): "too short method name"; + declare error: execution(* n()): "too short method name"; // no effect + + //declare warning: exec: "bar"; +} + + diff --git a/org.aspectj.ajdt.core/testdata/src1/DummyAspect.java b/org.aspectj.ajdt.core/testdata/src1/DummyAspect.java new file mode 100644 index 000000000..dafef6e64 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/DummyAspect.java @@ -0,0 +1,6 @@ +public abstract aspect DummyAspect { + public abstract pointcut traced(Object o); + + before (Object exc): traced(exc) { + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/Good.java b/org.aspectj.ajdt.core/testdata/src1/Good.java new file mode 100644 index 000000000..f21b04c6b --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Good.java @@ -0,0 +1,61 @@ + +import java.util.*; +import java.io.IOException; + +public class Good { + + public static String foo; + public int publicA = 1; + private int privateA = 2; + protected int protectedA = 3; + int packageA = 4; + + { publicA = 5; } + + static { foo = "hi"; } + + public Good() { } + + public void foo() { + int i = 0; + i += 1; + i += 2; + + int aspect = 2; + + System.out.println(1 + aspect +", " + aspect++); + } + + { publicA = 6; } + + + static aspect x { } +} + +aspect A { + public void m() { } +} + +/* + +aspect A { + int j; + + public void m() { } + + pointcut all(): call(* *(..)); + + after all(): { System.out.println(""); } + + before(): call(* *(..)) { + System.out.println(""); + } +} + +interface I { } +*/ + +//privileged aspect PrivilegedAspect { } + + + diff --git a/org.aspectj.ajdt.core/testdata/src1/Handler.java b/org.aspectj.ajdt.core/testdata/src1/Handler.java new file mode 100644 index 000000000..bcb88d7e6 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Handler.java @@ -0,0 +1,50 @@ +public class Handler { + public static void main(String[] args) { + m(); + } + +// public static void m() { +// while(true) { +// foo: {try { +// int x = 2+3; +// if (x >3) break foo; +// x = x+10; +// //return; +// } catch (Throwable t) { +// System.err.println(t); +// }} +// System.out.println("still in loop"); +// } +// //System.out.println("outside"); +// +// } + + public static void m() { + try { + int x = 0; + int y = 3/x; + throw new RuntimeException("shouldn't be here"); + } catch (Throwable t) { + return; + } + } + + public void m1(int x) { + boolean b = true; + if (b) { + m(); + } else { + m(); + } + } +} + +aspect A { + before(Throwable t): handler(Throwable) && args(t) { + System.out.println("caught " + t + " at " + thisJoinPointStaticPart); + } + +// before(int i): cflow(execution(void m1(int)) && args(i)) && call(void m()) { +// System.out.println("i"); +// } +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/Hello.java b/org.aspectj.ajdt.core/testdata/src1/Hello.java new file mode 100644 index 000000000..9af032526 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Hello.java @@ -0,0 +1,5 @@ +public class Hello { + public static void main(String[] args) { + System.out.println("hello world"); + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/IfPcd.java b/org.aspectj.ajdt.core/testdata/src1/IfPcd.java new file mode 100644 index 000000000..4318f3d41 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/IfPcd.java @@ -0,0 +1,37 @@ +public aspect IfPcd { + private static int foo = 393; + + before(): execution(void IfPcd.main(..)) && if(foo == 393) { + System.err.println("Hiya"); + foo++; + main(null); // saved from an infinite loop by the if + } + + before(): execution(void IfPcd.main(..)) && if(thisJoinPoint.getThis() == null) { + System.err.println("!has this: "+ thisJoinPoint.getThis()); + } + + before(): execution(void IfPcd.main(..)) && if(thisJoinPointStaticPart.getKind() == "method-execution") { + System.err.println("is method-exec"); + } + + + before(Object o): execution(void IfPcd.main(..)) && args(o) && if(o != null) { + System.err.println("got: " + o); + } + + pointcut fun(Object o): args(o) && if(o != null); + + before(Object o1, Object o2): execution(void IfPcd.main(..)) && args(o1) && fun(o2) { + System.err.println("got: " + o2); + } + + before(): execution(void IfPcd.main(..)) && fun(Object) { + System.err.println("got nothin"); + } + + public static void main(String[] args) { + System.err.println("actual body: " + args); + } +} + diff --git a/org.aspectj.ajdt.core/testdata/src1/Initialization.java b/org.aspectj.ajdt.core/testdata/src1/Initialization.java new file mode 100644 index 000000000..4b738a975 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Initialization.java @@ -0,0 +1,46 @@ +public class Initialization extends Super { + public static void main(String[] args) { + new Initialization(); + new Initialization(331); + } + + Initialization() { + this(98); + } + Initialization(int i) { + super(i+1); + foo(i); + } + + static void foo(int i) { + System.out.println("running foo with " + i); + } +} + +class Super { + Super(int i) { + } +} + +aspect Foo { + + +// void around(int i): initialization(Initialization.new(int)) && args(i) { +// System.out.println(thisJoinPoint); +// System.out.println(java.util.Arrays.asList(thisJoinPoint.getArgs())); +// proceed(993); +// } +// + + + Object around(): preinitialization(Initialization.new()) { + System.out.println("i"); + return null; + } + +// before(int i): execution(Initialization.new(int)) && args(i) { +// System.err.println(i); +// } +} + + diff --git a/org.aspectj.ajdt.core/testdata/src1/InterType.java b/org.aspectj.ajdt.core/testdata/src1/InterType.java new file mode 100644 index 000000000..af51afb11 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/InterType.java @@ -0,0 +1,86 @@ +import junit.framework.Assert; + +public class InterType { + + public static void main(String[] args) { + Target t = new Target(); + Assert.assertEquals(0, t.i); + t.i = 37; + Assert.assertEquals(37, t.i); + Assert.assertEquals(37, t.i++); + Assert.assertEquals(38, t.i); + Assert.assertEquals(39, ++t.i); + Assert.assertEquals(39, t.i); + + System.out.println("t.i = " + t.i); + + Assert.assertEquals(0, ((I)t).i); + + Assert.assertEquals("foo", t.s); + t.s += "-bar"; + Assert.assertEquals("foo-bar", t.s); + System.out.println("t.s = " + t.s); + + // this captures an interesting property of initializers: + // that introduced inits run before non-introduced inits + Assert.assertEquals("inst00onA", A.getInstS(t)); + System.out.println("t.instS = " + A.getInstS(t)); + + I i = t; + Assert.assertEquals("dummy", i.myString); + i.myString = "foo"; + Assert.assertEquals(i.myString, "foo"); + System.out.println("t.myString = " + t.myString); + + Assert.assertNotNull(A.aspectOf()); + Assert.assertEquals(A.aspectOf(), A.aspectOf()); + Assert.assertTrue(A.hasAspect()); + + //XXX don't handle constants +// int x = 10; +// switch(x) { +// case Target.CONST: break; +// default: Assert.fail("bad switch"); +// } + + } +} + +class Target implements I { + public int j = 2; + private boolean instS = true; // potential conflict need to handle gracefully + public boolean getInstS() { return instS; } + + String conflict = "boo"; +} + +class SubTarget extends Target { + public static String foo() { + return A.aspectOf().toString(); + } +} + + +interface I { } + + + +aspect A { + private static String aStatic = "onA"; + + public int Target.foobarvas = 0; + public int I.i = 0; + public int Target.i; + public static String Target.s = "foo"; + public static int Target.CONST = 10; + + private String Target.instS = "inst" + j + this.j + aStatic; + + //private String Target.conflict = "goo"; error + + public static String getInstS(Target t) { + return t.instS; + } + + public String I.myString = "dummy"; +} diff --git a/org.aspectj.ajdt.core/testdata/src1/InterTypeConstructors.java b/org.aspectj.ajdt.core/testdata/src1/InterTypeConstructors.java new file mode 100644 index 000000000..d11f3bf4d --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/InterTypeConstructors.java @@ -0,0 +1,73 @@ +import junit.framework.Assert; + +public class InterTypeConstructors { + + public static void main(String[] args) { + Target t = A.makeT(); + } +} + +class Target implements I { + private Target(String s) { + System.err.println(s); + } + + public Target() { + this(10); + } + + int f = 10; + static int ss() { return 100; } + + String getS() { return "Target" + this.instS("Foo"); } + + private int instS(String s) { return 10; } + + public int mmmm() { System.err.println("noarg"); return 3;} + +} + +class C { + class SubTarget extends Target { + final String s; + + public SubTarget() { + super(10); + s = "hi"; + } + } +} + +//class SubTarget extends Target { +// String getS() { return "SubTarget"; } +// static int ss() { return 10; } +// +// public void foobar() { +// mmmm(333); +// } +// +// //public int mmmm(int x) { return x; } +//} + +interface SuperI {} + + +interface I extends SuperI { } + + + +aspect A { + public static Target makeT() { + return new Target(10); + } + + Target.new(int foo) { + this("hi" + ++foo); + this.f = mmmm() + foo; + System.err.println(f == 14); + } + + //C.SubTarget.new(String value) { // uncomment for an error + //this.s = value; + //} +} diff --git a/org.aspectj.ajdt.core/testdata/src1/InterTypeMethods.java b/org.aspectj.ajdt.core/testdata/src1/InterTypeMethods.java new file mode 100644 index 000000000..4bc44186c --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/InterTypeMethods.java @@ -0,0 +1,79 @@ +import junit.framework.Assert; + +public class InterTypeMethods { + + public static void main(String[] args) { + Target t = new Target(); + Assert.assertEquals(23, t.instM(1)); + Assert.assertEquals("foo10", A.instS(t, "foo")); + + System.out.println("t: " + t); + + Assert.assertEquals(12, SubTarget.staticM()); + + SubTarget st = new SubTarget(); + + Assert.assertEquals("100Target10", st.foo()); + + st.foobar(); + t.mmmm(2); + + Assert.assertEquals("xyz-foo", st.onI("xyz-")); + } +} + +class Target implements I { + int f = 10; + static int ss() { return 100; } + + String getS() { return "Target" + this.instS("Foo"); } + + private int instS(String s) { return 10; } + + public int mmmm() { System.err.println("noarg"); return 3;} + +} + +class SubTarget extends Target { + String getS() { return "SubTarget"; } + static int ss() { return 10; } + + public void foobar() { + mmmm(333); + } + + //public int mmmm(int x) { return x; } +} + +interface SuperI {} + + +interface I extends SuperI { } + + + +aspect A { + public static String instS(Target t, String s) { + return t.instS(s); + } + + public int Target.instM(int x) { return x+2 + f + this.f; } + private String Target.instS(String s) { return s + this.f; } + + static int SubTarget.staticM() { return ss() + 2; } + + public String SubTarget.foo() { return super.ss() + super.getS(); } + + public int Target.mmmm(int i) { System.err.println("onearg"); return 3;} + public int SubTarget.mmmm(int i) { System.err.println("onearg on Sub"); return 4;} + + public String I.v = "foo"; + + public String I.onI(String a) { + return a + v; + } + + public String SuperI.onI(String a) { + return a + "Super"; + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/MyTrace.java b/org.aspectj.ajdt.core/testdata/src1/MyTrace.java new file mode 100644 index 000000000..a4b556436 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/MyTrace.java @@ -0,0 +1,7 @@ +aspect MyTrace extends Trace { + public pointcut traced(Object foo): this(foo) && execution(* doit(..)); + + after(Object o) returning (Object ret): traced(o) { + System.out.println("exit: " /*+ thisJoinPoint.getSignature()*/ + " with " + ret); + } +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/Parents.java b/org.aspectj.ajdt.core/testdata/src1/Parents.java new file mode 100644 index 000000000..17f071927 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Parents.java @@ -0,0 +1,40 @@ +public class Parents { + public static void main(String[] args) { + A.I i = new C1(); + i.m(); + + C2 c2 = new C2(); + c2.m1(); + + A.C3 c3 = (A.C3)c2; + + C4 c4 = new C4(); + c4.m4(); + } +} + +class C1 { + public void m() { System.out.println("m"); } +} + +class C2 {} + +class C4 {} + +aspect A { + static class C3 { + public void m1() { System.out.println("from C3"); } + } + + interface I { + void m(); + } + + declare parents: (C1 && !C2) implements I; + declare parents: C2 extends C3; + + interface I4 {} + public void I4.m4() { System.out.println("I.m4"); } + + declare parents: C4 implements I4; +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/ParentsFail.java b/org.aspectj.ajdt.core/testdata/src1/ParentsFail.java new file mode 100644 index 000000000..745fb67c9 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/ParentsFail.java @@ -0,0 +1,22 @@ +public class ParentsFail { + public static void main(String[] args) { + I i = new C1(); // CE incompatible + i.m(); + } +} + +class C1 { + public void m() { System.out.println("m"); } +} +class C2 {} +class C3 extends C2 {} +interface I { + void m(); +} + +aspect A { + declare parents: C2 implements I; // CE can't implement + declare parents: C2 extends C3; // CE circular + + declare parents: C1 extends C1; // CE self +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/PerCflow.java b/org.aspectj.ajdt.core/testdata/src1/PerCflow.java new file mode 100644 index 000000000..9606c1f75 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/PerCflow.java @@ -0,0 +1,22 @@ +public class PerCflow { + public static void main(String[] args) { + m(); + } + + static void m() { + System.out.println("m()"); + } +} + + +aspect A percflow(pc()) { + pointcut pc(): execution(void main(..)); + static Object o = new Integer(2); + before(): execution(void m()) { + System.out.println("in " + o.toString()); + } + + static { + o = "hello"; + } +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/PerObject.java b/org.aspectj.ajdt.core/testdata/src1/PerObject.java new file mode 100644 index 000000000..9452ed28a --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/PerObject.java @@ -0,0 +1,22 @@ +public class PerObject { + public static void main(String[] args) { + new PerObject().m(); + } + + void m() { + System.out.println("m()"); + } +} + + +aspect A perthis(pc()) { + pointcut pc(): this(PerObject) && execution(* m(..)); + static Object o = new Integer(2); + before(): get(* *) { + System.out.println("in " + o.toString()); + } + + static { + o = "hello"; + } +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/Privileged.java b/org.aspectj.ajdt.core/testdata/src1/Privileged.java new file mode 100644 index 000000000..064f1c755 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Privileged.java @@ -0,0 +1,32 @@ +import java.io.*; +import org.aspectj.lang.*; + +public class Privileged { + public static void main(String[] args) { + Privileged p = new Privileged(); + + System.out.println("got: " + A.getX(p)); + System.out.println("s: " + s); + } + + private int m() { + return 2; + } + + private int x = 1; + + private static String s = "hi"; +} + + +privileged aspect A { + static int getX(Privileged p) { + Runnable r = new Runnable() { + public void run() { + Privileged.s += 10; + } + }; + r.run(); + return p.x + p.m(); + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/ThisAndModifiers.java b/org.aspectj.ajdt.core/testdata/src1/ThisAndModifiers.java new file mode 100644 index 000000000..c8fd65aa7 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/ThisAndModifiers.java @@ -0,0 +1,19 @@ +aspect A2 { + after(Object thisObject): target(thisObject) && execution(public * Hello.*(..)) { + } + after(Object thisObject): this(thisObject) && execution(* Hello.*(..)) { + System.out.println(thisObject); + } + after() returning (String s): execution(* Hello.*(..)) { + //System.out.println(s); + } +} + +class Hello { + public static void main(String[] args) { + System.out.println("hello"); + } + + void m() { + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/Trace.java b/org.aspectj.ajdt.core/testdata/src1/Trace.java new file mode 100644 index 000000000..d6aaf17f8 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Trace.java @@ -0,0 +1,22 @@ +public abstract aspect Trace { + public abstract pointcut traced(Object o); + + before (Object exc): traced(exc) { + System.out.println("enter: " /*+ thisJoinPoint.getSignature()*/); + } + + Object around(): execution(* doit(..)) { + Object exc = "Hi"; + System.out.println("start around: " + exc); + Object ret = proceed(); + System.out.println("exiting around with: " + ret); + return ret; + } + + Object around(Object exc): traced(exc) { + System.out.println("start around(2): " + exc); + Object ret = proceed(exc); + System.out.println("exiting around with(2): " + ret); + return ret; + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/TraceHello.java b/org.aspectj.ajdt.core/testdata/src1/TraceHello.java new file mode 100644 index 000000000..545c58ccc --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/TraceHello.java @@ -0,0 +1,5 @@ +public aspect TraceHello { + before(): execution(* Hello.*(..)) { + System.out.println("entering: " + thisJoinPoint); + } +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/UnimplementedSyntax.java b/org.aspectj.ajdt.core/testdata/src1/UnimplementedSyntax.java new file mode 100644 index 000000000..3ea1a1685 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/UnimplementedSyntax.java @@ -0,0 +1,23 @@ +/** + * + * + */ +aspect A dominates Foo persingleton() { } + +//aspect B perthis(foo()) { +//XXX don't forget an error test for foo() not found} + +aspect C { + pointcut w(int x): args(x) && if(x < 10); + pointcut x(): cflow(y()); + pointcut y(): withincode(int m()); + + pointcut z(): execution(void m()) a b c; + declare error: execution(void m()): "hi" ac; + + pointcut p(): handler(Foo); + + pointcut p2(): initialization(Object.new(..)); +} + +aspect D a b c {}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/Xlint.java b/org.aspectj.ajdt.core/testdata/src1/Xlint.java new file mode 100644 index 000000000..bec51c6d3 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/Xlint.java @@ -0,0 +1,3 @@ +public aspect Xlint { + pointcut foo(): this(NotFoundType); +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/p1/.cvsignore b/org.aspectj.ajdt.core/testdata/src1/p1/.cvsignore new file mode 100644 index 000000000..6b468b62a --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/p1/.cvsignore @@ -0,0 +1 @@ +*.class diff --git a/org.aspectj.ajdt.core/testdata/src1/p1/A.java b/org.aspectj.ajdt.core/testdata/src1/p1/A.java new file mode 100644 index 000000000..be6b96b2f --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/p1/A.java @@ -0,0 +1,28 @@ +aspect A { + public void m(int x) { + System.out.println(x); + } + + pointcut foo(String[] args): args(args) && execution(void Hello.*(..)); + + before(): execution(* Hello.*(..)) { + System.out.println("enter"); + } + + public int Hello.fromA; + + public void pingHello(Hello h) { + int x = 2; + System.out.println(x); + } + +} + +class Hello { + public static void main(String[] args) { + } +} + +interface I { + //void foo(); +} diff --git a/org.aspectj.ajdt.core/testdata/src1/p1/Foo.java b/org.aspectj.ajdt.core/testdata/src1/p1/Foo.java new file mode 100644 index 000000000..0a0b8b22a --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/p1/Foo.java @@ -0,0 +1,7 @@ +package p1; + +public class Foo { + public static void main(String[] args) { + System.out.println("Foo"); + } +} diff --git a/org.aspectj.ajdt.core/testdata/src1/trace/ExecTrace.java b/org.aspectj.ajdt.core/testdata/src1/trace/ExecTrace.java new file mode 100644 index 000000000..c0ac25f34 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/trace/ExecTrace.java @@ -0,0 +1,7 @@ +package trace; + +public aspect ExecTrace extends MegaTrace { + pointcut where(): execution(public * *(..)); + + declare parents: * implements Marker; +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/trace/MegaTrace.java b/org.aspectj.ajdt.core/testdata/src1/trace/MegaTrace.java new file mode 100644 index 000000000..dff9a8f20 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/trace/MegaTrace.java @@ -0,0 +1,33 @@ +package trace; + +public abstract aspect MegaTrace { + abstract pointcut where(); + + Object around(): where() { + System.out.println("around enter: " + thisJoinPointStaticPart); + Object ret = proceed(); + System.out.println("around exit: " + thisJoinPointStaticPart); + return ret; + } + + before(): where() { + System.out.println("enter: " + thisJoinPointStaticPart); + } + + after(): where() { + System.out.println("exit: " + thisJoinPointStaticPart); + } + + + declare warning: where() && execution(void main(..)): + "tracing execution of main"; + + public interface Marker{} + private String Marker.name = "foo-bar"; + + public String sayHi() { return "hi"; } + + public static String getName(Marker m) { + return m.name; + } +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/tracep1/TraceTest.java b/org.aspectj.ajdt.core/testdata/src1/tracep1/TraceTest.java new file mode 100644 index 000000000..e639bd5a3 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/tracep1/TraceTest.java @@ -0,0 +1,11 @@ +package tracep1; + +public class TraceTest { + + public static void test() { + TraceTest t = new TraceTest(); + + System.out.println(trace.MegaTrace.getName(t)); + System.out.println(t.sayHi()); + } +}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/testclasses.jar b/org.aspectj.ajdt.core/testdata/testclasses.jar Binary files differnew file mode 100644 index 000000000..94cebaa30 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/testclasses.jar diff --git a/org.aspectj.ajdt.core/testdata/testclasses/Hello.java b/org.aspectj.ajdt.core/testdata/testclasses/Hello.java new file mode 100644 index 000000000..9af032526 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/testclasses/Hello.java @@ -0,0 +1,5 @@ +public class Hello { + public static void main(String[] args) { + System.out.println("hello world"); + } +} diff --git a/org.aspectj.ajdt.core/testdata/testclasses/p1/Foo.class b/org.aspectj.ajdt.core/testdata/testclasses/p1/Foo.class Binary files differnew file mode 100644 index 000000000..d6c418c88 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/testclasses/p1/Foo.class diff --git a/org.aspectj.ajdt.core/testdata/testclasses/p1/Foo.java b/org.aspectj.ajdt.core/testdata/testclasses/p1/Foo.java new file mode 100644 index 000000000..0a0b8b22a --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/testclasses/p1/Foo.java @@ -0,0 +1,7 @@ +package p1; + +public class Foo { + public static void main(String[] args) { + System.out.println("Foo"); + } +} diff --git a/org.aspectj.ajdt.core/testsrc/AroundAMain.java b/org.aspectj.ajdt.core/testsrc/AroundAMain.java new file mode 100644 index 000000000..21cf5e3ec --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/AroundAMain.java @@ -0,0 +1,47 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +import java.util.Arrays; + +import junit.framework.TestCase; + +import org.aspectj.runtime.internal.AroundClosure; +import org.aspectj.util.Reflection; + +public class AroundAMain extends TestCase { + + public AroundAMain(String name) { + super(name); + } + + + public static void main(String[] args) throws ClassNotFoundException { + AroundClosure closure = new AroundClosure() { + public Object run(Object[] args) throws Throwable { +// System.out.println("run with: " + Arrays.asList(args)); + return new Integer(10); + } + }; + + Object instance = Reflection.getStaticField(Class.forName("AroundA"), + "ajc$perSingletonInstance"); + + Reflection.invoke(Class.forName("AroundA"), instance, "ajc$around$AroundA$46", + new Integer(10), new Boolean(true), closure); + + Reflection.invoke(Class.forName("AroundA"), instance, "ajc$around$AroundA$c5", + "hello there", closure); + Reflection.invoke(Class.forName("AroundA"), instance, "ajc$around$AroundA$150", + new String[1], closure); + + } +} diff --git a/org.aspectj.ajdt.core/testsrc/EajcModuleTests.java b/org.aspectj.ajdt.core/testsrc/EajcModuleTests.java new file mode 100644 index 000000000..09bd583ee --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/EajcModuleTests.java @@ -0,0 +1,33 @@ +/* ******************************************************************* + * Copyright (c) 1999-2001 Xerox Corporation, + * 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +// default package + +import junit.framework.*; +import junit.framework.Test; + +public class EajcModuleTests extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(EajcModuleTests.class.getName()); + suite.addTest(org.aspectj.ajdt.ajc.AjdtAjcTests.suite()); + suite.addTest(org.aspectj.ajdt.internal.compiler.batch.AjdtBatchTests.suite()); + suite.addTest(org.aspectj.ajdt.internal.core.builder.AjdtBuilderTests.suite()); + suite.addTest(org.aspectj.workbench.resources.WorkspaceResourcesTests.suite()); + return suite; + } + + public EajcModuleTests(String name) { super(name); } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/AjdtAjcTests.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/AjdtAjcTests.java new file mode 100644 index 000000000..9893c4bcc --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/AjdtAjcTests.java @@ -0,0 +1,33 @@ +/* ******************************************************************* + * Copyright (c) 1999-2001 Xerox Corporation, + * 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.ajc; + +import junit.framework.*; + +public class AjdtAjcTests extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(AjdtAjcTests.class.getName()); + //$JUnit-BEGIN$ + suite.addTestSuite(AjdtCommandTestCase.class); + suite.addTestSuite(BuildArgParserTestCase.class); + suite.addTestSuite(ConsoleMessageHandlerTestCase.class); + //$JUnit-END$ + return suite; + } + + public AjdtAjcTests(String name) { super(name); } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/AjdtCommandTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/AjdtCommandTestCase.java new file mode 100644 index 000000000..40f7f13b4 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/AjdtCommandTestCase.java @@ -0,0 +1,111 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.ajc; + +import org.aspectj.ajdt.internal.core.builder.AjBuildConfig; +import org.aspectj.bridge.AbortException; +import org.aspectj.bridge.MessageWriter; +import org.aspectj.util.StreamPrintWriter; +import org.eclipse.jdt.core.compiler.InvalidInputException; + +import java.io.PrintWriter; + +import junit.framework.TestCase; + +/** + * Some black-box test is happening here. + */ +public class AjdtCommandTestCase extends TestCase { + + private StreamPrintWriter outputWriter = new StreamPrintWriter(new PrintWriter(System.out)); + private AjdtCommand command = new AjdtCommand(); + private MessageWriter messageWriter = new MessageWriter(outputWriter, false); + + public AjdtCommandTestCase(String name) { + super(name); +// command.buildArgParser.out = outputWriter; + } + + public void testIncrementalOption() throws InvalidInputException { + AjBuildConfig config = command.genBuildConfig(new String[] { "-incremental" }, messageWriter); + + assertTrue( + "didn't specify source root", + outputWriter.getContents().indexOf("specify a source root") != -1); + + outputWriter.flushBuffer(); + config = command.genBuildConfig( + new String[] { "-incremental", "-sourceroots", "testdata/src1" }, + messageWriter); + + assertTrue( + outputWriter.getContents(), + outputWriter.getContents().equals("")); + + outputWriter.flushBuffer(); + config = command.genBuildConfig( + new String[] { "-incremental", "testdata/src1/Hello.java" }, + messageWriter); + + assertTrue( + "specified a file", + outputWriter.getContents().indexOf("can not directly specify files") != -1); ; + } + + public void testBadOptionAndUsagePrinting() throws InvalidInputException { + try { + command.genBuildConfig(new String[] { "-mubleBadOption" }, messageWriter); + } catch (AbortException ae) { } + + assertTrue( + outputWriter.getContents() + " contains? " + "Usage", + outputWriter.getContents().indexOf("Usage") != -1); + + } + + public void testHelpUsagePrinting() { + try { + command.genBuildConfig(new String[] { "-help" }, messageWriter); + } catch (AbortException ae) { } + assertTrue( + outputWriter.getContents() + " contains? " + "Usage", + outputWriter.getContents().indexOf("Usage") != -1); + } + + public void testVersionOutput() throws InvalidInputException { + try { + command.genBuildConfig(new String[] { "-version" }, messageWriter); + } catch (AbortException ae) { } + assertTrue( + "version output", + outputWriter.getContents().indexOf("AspectJ Compiler") != -1); + } + + public void testNonExistingLstFile() { + command.genBuildConfig(new String[] { "@mumbleDoesNotExist" }, messageWriter); + + assertTrue( + outputWriter.getContents(), + outputWriter.getContents().indexOf("file does not exist") != -1); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + outputWriter.flushBuffer(); + } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/BuildArgParserTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/BuildArgParserTestCase.java new file mode 100644 index 000000000..e2d23f7a1 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/BuildArgParserTestCase.java @@ -0,0 +1,401 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.ajc; + +import org.aspectj.ajdt.internal.core.builder.AjBuildConfig; +import org.aspectj.ajdt.internal.core.builder.AjCompilerOptions; +import org.aspectj.bridge.MessageWriter; +import org.aspectj.testing.util.TestUtil; +import org.eclipse.jdt.core.compiler.InvalidInputException; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import junit.framework.TestCase; + +/** + * Some black-box test is happening here. + */ +public class BuildArgParserTestCase extends TestCase { + + private BuildArgParser parser = new BuildArgParser(); + private static final String TEST_DIR = "testdata" + File.separator + "ajc" + File.separator; + private MessageWriter messageWriter = new MessageWriter(new PrintWriter(System.out), false); + + public BuildArgParserTestCase(String name) { + super(name); + } + + public void testDefaultClasspathAndTargetCombo() throws InvalidInputException { + String ENTRY = "1.jar;2.jar"; + final String classpath = System.getProperty("java.class.path"); + try { + System.setProperty("java.class.path", ENTRY); // see finally below + AjBuildConfig config = parser.genBuildConfig(new String[] { }, messageWriter); + String err = parser.getOtherMessages(true); + assertTrue(err, null == err); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("1.jar")); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("2.jar")); + + config = parser.genBuildConfig(new String[] { "-1.3" }, messageWriter); + err = parser.getOtherMessages(true); + assertTrue(err, null == err); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("1.jar")); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("2.jar")); + + config = parser.genBuildConfig(new String[] { "-1.3" }, messageWriter); + err = parser.getOtherMessages(true); + assertTrue(err, null == err); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("1.jar")); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("2.jar")); + + config = parser.genBuildConfig(new String[] { + "-classpath", ENTRY, "-1.4" }, messageWriter); + err = parser.getOtherMessages(true); + assertTrue("expected errors for missing jars", null != err); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("1.jar")); + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("2.jar")); + + } finally { + // do finally to avoid messing up classpath for other tests + System.setProperty("java.class.path", classpath); + String setPath = System.getProperty("java.class.path"); + String m = "other tests will fail - classpath not reset"; + assertEquals(m, classpath, setPath); + } + } + + public void testAjOptions() throws InvalidInputException { + AjBuildConfig config = parser.genBuildConfig(new String[] { "-Xlint" }, messageWriter); + + assertTrue( + "default options", + config.getAjOptions().get(AjCompilerOptions.OPTION_Xlint).equals( + CompilerOptions.GENERATE)); + } + + public void testAspectpath() throws InvalidInputException { + final String SOURCE_JAR = "testdata/testclasses.jar"; + final String SOURCE_JARS = "testdata/testclasses.jar" + File.pathSeparator + + "../bcweaver/testdata/tracing.jar" + File.pathSeparator + + "../bcweaver/testdata/dummyAspect.jar"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-aspectpath", SOURCE_JAR }, + messageWriter); + + assertTrue(((File)config.getAspectpath().get(0)).getName(), ((File)config.getAspectpath().get(0)).getName().equals("testclasses.jar")); + + config = parser.genBuildConfig(new String[] { + "-aspectpath", SOURCE_JARS }, + messageWriter); + assertTrue("size", + config.getAspectpath().size() == 3); + } + + public void testInJars() throws InvalidInputException { + final String SOURCE_JAR = "testdata/testclasses.jar"; + final String SOURCE_JARS = "testdata/testclasses.jar" + File.pathSeparator + + "../bcweaver/testdata/tracing.jar" + File.pathSeparator + + "../bcweaver/testdata/dummyAspect.jar"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-injars", SOURCE_JAR }, + messageWriter); + //XXX don't let this remain in both places in beta1 + assertTrue( + "" + config.getAjOptions().get(AjCompilerOptions.OPTION_InJARs), + config.getAjOptions().get(AjCompilerOptions.OPTION_InJARs).equals(CompilerOptions.PRESERVE)); + assertTrue(((File)config.getInJars().get(0)).getName(), ((File)config.getInJars().get(0)).getName().equals("testclasses.jar")); + + config = parser.genBuildConfig(new String[] { + "-injars", SOURCE_JARS }, + messageWriter); + assertTrue("size", + config.getInJars().size() == 3); + } + + public void testBadInJars() throws InvalidInputException { + final String SOURCE_JARS = "testdata/testclasses.jar" + File.pathSeparator + "b.far" + File.pathSeparator + "c.jar"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-injars", SOURCE_JARS }, + messageWriter); + assertTrue("size: " + config.getInJars().size(), config.getInJars().size() == 1); + } + + public void testMultipleSourceRoots() throws InvalidInputException { + final String SRCROOT_1 = "testdata/src1/p1"; + final String SRCROOT_2 = "testdata/ajc"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-sourceroots", SRCROOT_1 + File.pathSeparator + SRCROOT_2 }, + messageWriter); + + assertEquals(new File(SRCROOT_1).getAbsolutePath(), ((File)config.getSourceRoots().get(0)).getAbsolutePath()); + + Collection expectedFiles = Arrays.asList(new File[] { + new File(SRCROOT_1+File.separator+"A.java").getAbsoluteFile(), + new File(SRCROOT_1+File.separator+"Foo.java").getAbsoluteFile(), + new File(SRCROOT_2+File.separator+"A.java").getAbsoluteFile(), + new File(SRCROOT_2+File.separator+"B.java").getAbsoluteFile(), + new File(SRCROOT_2+File.separator+"X.aj").getAbsoluteFile(), + new File(SRCROOT_2+File.separator+"Y.aj").getAbsoluteFile(), + new File(SRCROOT_2+File.separator+"pkg"+File.separator+"Hello.java").getAbsoluteFile(), + }); + + //System.out.println(config.getFiles()); + + TestUtil.assertSetEquals(expectedFiles, config.getFiles()); + } + + public void testSourceRootDir() throws InvalidInputException { + final String SRCROOT = "testdata/ajc"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-sourceroots", SRCROOT }, + messageWriter); + + assertEquals(new File(SRCROOT).getAbsolutePath(), ((File)config.getSourceRoots().get(0)).getAbsolutePath()); + + Collection expectedFiles = Arrays.asList(new File[] { + new File(SRCROOT+File.separator+"A.java").getAbsoluteFile(), + new File(SRCROOT+File.separator+"B.java").getAbsoluteFile(), + new File(SRCROOT+File.separator+"X.aj").getAbsoluteFile(), + new File(SRCROOT+File.separator+"Y.aj").getAbsoluteFile(), + new File(SRCROOT+File.separator+"pkg"+File.separator+"Hello.java").getAbsoluteFile(), + }); + + //System.out.println(config.getFiles()); + + TestUtil.assertSetEquals(expectedFiles, config.getFiles()); + } + + public void testBadSourceRootDir() throws InvalidInputException { + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-sourceroots", + "testdata/mumbleDoesNotExist;testdata/ajc" }, + messageWriter); + + assertTrue(config.getSourceRoots().toString(), config.getSourceRoots().size() == 1); + + config = parser.genBuildConfig(new String[] { + "-sourceroots" }, + messageWriter); + + assertTrue("" + config.getSourceRoots(), config.getSourceRoots().size() == 0); + + } + + //??? we've decided not to make this an error + public void testSourceRootDirWithFiles() throws InvalidInputException { + final String SRCROOT = "testdata/ajc/pkg"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-sourceroots", SRCROOT, "testdata/src1/A.java"}, + messageWriter); + + assertEquals(new File(SRCROOT).getAbsolutePath(), ((File)config.getSourceRoots().get(0)).getAbsolutePath()); + + Collection expectedFiles = Arrays.asList(new File[] { + new File(SRCROOT+File.separator+"Hello.java").getAbsoluteFile(), + new File("testdata"+File.separator+"src1"+File.separator+"A.java").getAbsoluteFile(), + }); + + TestUtil.assertSetEquals(expectedFiles, config.getFiles()); + + } + + public void testExtDirs() throws InvalidInputException { + final String DIR = "testdata"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-extdirs", DIR }, + messageWriter); + assertTrue(config.getClasspath().toString(), config.getClasspath().contains( + new File(DIR + File.separator + "testclasses.jar").getAbsolutePath() + )); + } + + public void testBootclasspath() throws InvalidInputException { + final String PATH = "mumble/rt.jar"; + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-bootclasspath", PATH }, + messageWriter); + assertTrue(config.getClasspath().toString(), config.getClasspath().get(0).equals(PATH)); + + config = parser.genBuildConfig(new String[] { + }, + messageWriter); + assertTrue(config.getClasspath().toString(), !config.getClasspath().get(0).equals(PATH)); + } + + public void testOutputJar() throws InvalidInputException { + final String OUT_JAR = "testdata/testclasses.jar"; + + AjBuildConfig config = parser.genBuildConfig(new String[] { + "-outjar", OUT_JAR }, + messageWriter); + + //XXX don't let this remain in both places in beta1 + assertTrue( + "will generate: " + config.getAjOptions().get(AjCompilerOptions.OPTION_OutJAR), + config.getAjOptions().get(AjCompilerOptions.OPTION_OutJAR).equals(CompilerOptions.GENERATE)); + assertTrue( + "testclasses jar: " + config.getOutputJar().getName(), + config.getOutputJar().getAbsolutePath().equals(new File(OUT_JAR).getAbsolutePath())); + + File nonExistingJar = new File("testdata/mumbleDoesNotExist.jar"); + config = parser.genBuildConfig(new String[] { + "-outjar", nonExistingJar.getAbsolutePath() }, + messageWriter); + assertTrue( + "testclasses jar: " + config.getOutputJar().getName(), + config.getOutputJar().getAbsolutePath().equals(nonExistingJar.getAbsolutePath())); + + nonExistingJar.delete(); + } + + //XXX shouldn't need -1.4 to get this to pass + public void testCombinedOptions() throws InvalidInputException { + AjBuildConfig config = parser.genBuildConfig(new String[] { "-Xlint", "-target", "1.4", "-1.4" }, messageWriter); + String TARGET = "1.4"; + assertTrue( + "target set", + config.getJavaOptions().get(CompilerOptions.OPTION_TargetPlatform).equals(TARGET)); + + assertTrue( + "Xlint option set", + config.getAjOptions().get(AjCompilerOptions.OPTION_Xlint).equals( + CompilerOptions.GENERATE)); + } + + public void testOutputDirectorySetting() throws InvalidInputException { + AjBuildConfig config = parser.genBuildConfig(new String[] { "-d", TEST_DIR }, messageWriter); + + assertTrue( + new File(config.getOutputDir().getPath()).getAbsolutePath() + " ?= " + + new File(TEST_DIR).getAbsolutePath(), + config.getOutputDir().getAbsolutePath().equals((new File(TEST_DIR)).getAbsolutePath())); + } + + public void testClasspathSetting() throws InvalidInputException { + String ENTRY = "1.jar;2.jar"; + AjBuildConfig config = parser.genBuildConfig(new String[] { "-classpath", ENTRY }, messageWriter); + + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("1.jar")); + + assertTrue( + config.getClasspath().toString(), + config.getClasspath().contains("2.jar")); + } + + public void testArgInConfigFile() throws InvalidInputException { + String FILE_PATH = "@" + TEST_DIR + "configWithArgs.lst"; + String OUT_PATH = "bin"; + AjBuildConfig config = parser.genBuildConfig(new String[] { FILE_PATH }, messageWriter); + + assertNotNull(config); + File outputDir = config.getOutputDir(); + assertNotNull(outputDir); + assertEquals(outputDir.getPath(), OUT_PATH); + } + + public void testXlint() throws InvalidInputException { + AjdtCommand command = new AjdtCommand(); + AjBuildConfig config = parser.genBuildConfig(new String[] {"-Xlint"}, messageWriter); + assertTrue("", config.getLintMode().equals(AjBuildConfig.AJLINT_DEFAULT)); + config = parser.genBuildConfig(new String[] {"-Xlint:warn"}, messageWriter); + assertTrue("", config.getLintMode().equals(AjBuildConfig.AJLINT_WARN)); + config = parser.genBuildConfig(new String[] {"-Xlint:error"}, messageWriter); + assertTrue("", config.getLintMode().equals(AjBuildConfig.AJLINT_ERROR)); + config = parser.genBuildConfig(new String[] {"-Xlint:ignore"}, messageWriter); + assertTrue("", config.getLintMode().equals(AjBuildConfig.AJLINT_INGORE)); + } + + public void testXlintfile() throws InvalidInputException { + String lintFile = "testdata/lintspec.properties"; + String badLintFile = "lint.props"; + AjBuildConfig config = parser.genBuildConfig(new String[] {"-Xlintfile", lintFile}, messageWriter); + assertTrue(new File(lintFile).exists()); + assertTrue(config.getLintSpecFile().getAbsolutePath(), config.getLintSpecFile().getAbsolutePath().equals(new File(lintFile).getAbsolutePath())); + } + + public void testOptions() throws InvalidInputException { + AjdtCommand command = new AjdtCommand(); + String TARGET = "1.4"; + AjBuildConfig config = parser.genBuildConfig(new String[] {"-target", TARGET, "-source", TARGET}, messageWriter); + assertTrue( + "target set", + config.getJavaOptions().get(CompilerOptions.OPTION_TargetPlatform).equals(TARGET)); + assertTrue( + "source set", + config.getJavaOptions().get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)); + } + + public void testLstFileExpansion() throws IOException, FileNotFoundException, InvalidInputException { + String FILE_PATH = TEST_DIR + "config.lst"; + String SOURCE_PATH_1 = "A.java"; + String SOURCE_PATH_2 = "B.java"; + + File f = new File(FILE_PATH); + + AjBuildConfig config = parser.genBuildConfig(new String[] { "@" + FILE_PATH }, messageWriter); + List resultList = config.getFiles(); + + assertTrue("correct number of files", resultList.size() == 2); + assertTrue(resultList.toString() + new File(TEST_DIR + SOURCE_PATH_1).getAbsoluteFile(), + resultList.contains(new File(TEST_DIR + SOURCE_PATH_1).getAbsoluteFile())); + assertTrue(resultList.toString() + SOURCE_PATH_2, + resultList.contains(new File(TEST_DIR + SOURCE_PATH_2).getAbsoluteFile())); + } + + + //??? do we need to remove this limitation +// public void testArgInConfigFileAndRelativizingPathParam() throws InvalidInputException { +// String FILE_PATH = "@" + TEST_DIR + "configWithArgs.lst"; +// String OUT_PATH = TEST_DIR + "bin"; +// AjBuildConfig config = parser.genBuildConfig(new String[] { FILE_PATH }); +// +// assertTrue( +// config.getOutputDir().getPath() + " ?= " + OUT_PATH, +// config.getOutputDir().getAbsolutePath().equals((new File(OUT_PATH)).getAbsolutePath())); +// } + + public void testAjFileInclusion() throws InvalidInputException { + parser.genBuildConfig(new String[] { TEST_DIR + "X.aj", TEST_DIR + "Y.aj"}, messageWriter); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/ConsoleMessageHandlerTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/ConsoleMessageHandlerTestCase.java new file mode 100644 index 000000000..c359f91bb --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/ConsoleMessageHandlerTestCase.java @@ -0,0 +1,62 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.ajc; + +import java.io.PrintWriter; + +import junit.framework.TestCase; +import org.aspectj.bridge.*; +import org.aspectj.bridge.Message; +import org.aspectj.util.StreamPrintWriter; + +/** + * @author Mik Kersten + */ +public class ConsoleMessageHandlerTestCase extends TestCase { + + /** + * Constructor for ConsoleWriterTestCase. + * @param name + */ + public ConsoleMessageHandlerTestCase(String name) { + super(name); + } + + public void testIgnoringInfoMessages() { + testOutput(false); + } + + public void testHandlingInfoMessages() { + testOutput(true); + } + + private void testOutput(boolean verboseMode) { + //XXX update to new MessageHandler +// final String MESSAGE = "test;"; +// +// StreamPrintWriter output = new StreamPrintWriter(new PrintWriter(System.out)); +// ConsoleMessageHandler writer = new ConsoleMessageHandler(output); +// if (!verboseMode) writer.ignore(IMessage.INFO); +// +// writer.handleMessage(new Message(MESSAGE, Message.INFO, null, null)); +// if (verboseMode) { +// assertTrue("message=" + output.getContents(), output.getContents().equals(MESSAGE + "\n")); +// } else { +// assertTrue("message=" + output.getContents(), output.getContents().equals("")); +// } +// +// output.flushBuffer(); +// writer.handleMessage(new Message(MESSAGE, Message.ERROR, null, null)); +// assertTrue(output.getContents(), output.getContents().equals(MESSAGE + "\n")); + } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/AjdtBatchTests.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/AjdtBatchTests.java new file mode 100644 index 000000000..025e7c766 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/AjdtBatchTests.java @@ -0,0 +1,39 @@ +/* ******************************************************************* + * Copyright (c) 1999-2001 Xerox Corporation, + * 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.compiler.batch; + +import junit.framework.*; + +public class AjdtBatchTests extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(AjdtBatchTests.class.getName()); + // Abstract superclass + //suite.addTestSuite(CommandTestCase.class); + //$JUnit-BEGIN$ + suite.addTestSuite(BasicCommandTestCase.class); + suite.addTestSuite(BinaryFormsTestCase.class); + suite.addTestSuite(CompileAndRunTestCase.class); + suite.addTestSuite(ImageTestCase.class); + suite.addTestSuite(MultipleCompileTestCase.class); + // XXX suite.addTestSuite(VerifyWeaveTestCase.class); + //suite.addTestSuite(WorkingCommandTestCase.class); + //$JUnit-END$ + return suite; + } + + public AjdtBatchTests(String name) { super(name); } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BasicCommandTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BasicCommandTestCase.java new file mode 100644 index 000000000..9b5a69fb6 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BasicCommandTestCase.java @@ -0,0 +1,103 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import java.util.*; + +import org.aspectj.ajdt.ajc.*; +import org.aspectj.bridge.*; + +import junit.framework.*; + +/** + * @author hugunin + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. + * To enable and disable the creation of type comments go to + * Window>Preferences>Java>Code Generation. + */ +public class BasicCommandTestCase extends CommandTestCase { + + /** + * Constructor for CommandTestCase. + * @param name + */ + public BasicCommandTestCase(String name) { + super(name); + } + + public void testA() { + checkCompile("src1/A.java", NO_ERRORS); + } + + public void testA1() { + checkCompile("src1/A1.java", NO_ERRORS); + } + + public void testBadA() { + checkCompile("src1/BadA.java", new int[] {7, 8}); + } + + public void testHello() { + checkCompile("src1/Hello.java", NO_ERRORS); + } + + public void testBadHello() { + checkCompile("src1/BadHello.java", new int[] {5}); + } + + public void testMissingHello() { + checkCompile("src1/MissingHello.java", TOP_ERROR); + } + + public void testBadBinding() { + checkCompile("src1/BadBinding.java", new int[] {2, 4, 8, 10, 13, 16, 19}); + } + public void testThisAndModifiers() { + checkCompile("src1/ThisAndModifiers.java", NO_ERRORS); + } + public void testDeclares() { + checkCompile("src1/Declares.java", new int[] {3}); + } + + public void testDeclareWarning() { + checkCompile("src1/DeclareWarning.java", NO_ERRORS); + } + + + public void testP1() { + checkCompile("src1/p1/Foo.java", NO_ERRORS); + } + + public void testUnimplementedSyntax() { + checkCompile("src1/UnimplementedSyntax.java", + new int[] {5, 15, 16, 23}); + } + public void testXlintWarn() { + checkCompile("src1/Xlint.java", NO_ERRORS); + } + public void testXlintError() { + List args = new ArrayList(); + + args.add("-d"); + args.add("out"); + + args.add("-classpath"); + args.add("../runtime/bin;../lib/junit/junit.jar;../testing-client/bin"); + args.add("-Xlint:error"); + args.add("testdata/src1/Xlint.java"); + + runCompiler(args, new int[] {2}); + } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java new file mode 100644 index 000000000..7c232aa96 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java @@ -0,0 +1,90 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import java.io.IOException; +import java.util.*; +import java.util.ArrayList; + +public class BcweaverJarMaker { + + public BcweaverJarMaker() { + super(); + } + + public static void main(String[] args) throws IOException { + makeJar0(); + makeJar1(); + makeJar1a(); + makeJar2(); + } + + public static void makeJar0() throws IOException { + List args = new ArrayList(); + args.add("-outjar"); + args.add("../bcweaver/testdata/tracing.jar"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + args.add("testdata/src1/Trace.java"); + args.add("testdata/src1/MyTrace.java"); + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + } + + public static void makeJar1() throws IOException { + List args = new ArrayList(); + args.add("-outjar"); + args.add("../bcweaver/testdata/megatrace.jar"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + args.add("testdata/src1/trace/MegaTrace.java"); + args.add("testdata/src1/trace/ExecTrace.java"); + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + } + + + public static void makeJar1a() throws IOException { + List args = new ArrayList(); + args.add("-outjar"); + args.add("../bcweaver/testdata/megatraceNoweave.jar"); + + args.add("-noweave"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + args.add("testdata/src1/trace/MegaTrace.java"); + args.add("testdata/src1/trace/ExecTrace.java"); + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + } + + + public static void makeJar2() throws IOException { + List args = new ArrayList(); + args.add("-outjar"); + args.add("../bcweaver/testdata/dummyAspect.jar"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + args.add("testdata/src1/DummyAspect.java"); + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BinaryFormsTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BinaryFormsTestCase.java new file mode 100644 index 000000000..4fc63b0dc --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BinaryFormsTestCase.java @@ -0,0 +1,52 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import java.io.IOException; +import java.util.*; + + +public class BinaryFormsTestCase extends CommandTestCase { + + public BinaryFormsTestCase(String name) { + super(name); + } + + public void testDummy() {} + + + public void XXXtestJar1() throws IOException { + List args = new ArrayList(); + args.add("-outjar"); + args.add("out/megatrace.jar"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + args.add("testdata/src1/trace/MegaTrace.java"); + args.add("testdata/src1/trace/ExecTrace.java"); + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + + args = new ArrayList(); + args.add("-aspectpath"); + args.add("out/megatrace.jar"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + args.add("testdata/src1/tracep1/TraceTest.java"); + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java new file mode 100644 index 000000000..cd9a440de --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java @@ -0,0 +1,160 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import org.aspectj.ajdt.ajc.AjdtCommand; +import org.aspectj.bridge.ICommand; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.bridge.MessageHandler; + +import java.io.*; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.aspectj.ajdt.ajc.*; +import org.aspectj.weaver.*; +import org.aspectj.weaver.bcel.LazyClassGen; +import org.aspectj.bridge.*; + +import junit.framework.*; +import org.aspectj.weaver.*; + +public abstract class CommandTestCase extends TestCase { + + /** + * Constructor for CommandTestCase. + * @param name + */ + public CommandTestCase(String name) { + super(name); + } + + public static final int[] NO_ERRORS = new int[0]; + public static final int[] TOP_ERROR = new int[0]; + + + public static void checkCompile(String source, int[] expectedErrors) { + List args = new ArrayList(); + args.add("-verbose"); + + args.add("-d"); + args.add("out"); + + args.add("-classpath"); + args.add("../runtime/bin;../lib/junit/junit.jar"); + + args.add("-g"); //XXX need this to get sourcefile and line numbers, shouldn't + + args.add("testdata/" + source); + + runCompiler(args, expectedErrors); + } + + public void checkMultipleCompile(String source) throws InterruptedException { + List args = new ArrayList(); + args.add("-verbose"); + + args.add("-d"); + args.add("out"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + args.add("testdata/" + source); + + ICommand compiler = runCompiler(args, NO_ERRORS); + Thread.sleep(100); + + rerunCompiler(compiler); + } + + public void rerunCompiler(ICommand command) { + MessageHandler myHandler = new MessageHandler(); + List recompiledFiles = new ArrayList(); + if (!command.repeatCommand(myHandler)) { + assertTrue("recompile failed", false); + } + assertEquals(0, myHandler.numMessages(IMessage.ERROR, true)); + } + + + + public static ICommand runCompiler(List args, int[] expectedErrors) { + ICommand command = new AjdtCommand(); + MessageHandler myHandler = new MessageHandler(); + myHandler.setInterceptor(org.aspectj.tools.ajc.Main.MessagePrinter.TERSE); + command.runCommand((String[])args.toArray(new String[args.size()]), myHandler); + +// System.out.println("errors: " + Arrays.asList(myHandler.getErrors())); +// System.out.println("warnings: " + Arrays.asList(myHandler.getWarnings())); + + int nErrors = myHandler.numMessages(IMessage.ERROR, IMessageHolder.EQUAL); + if (expectedErrors == NO_ERRORS) { + if (0 != nErrors) { + String s = ""+Arrays.asList(myHandler.getErrors()); + assertTrue("unexpected errors: " + s, false); + } + } else if (expectedErrors == TOP_ERROR) { // ?? what is this? + assertTrue("expected error", nErrors > 0); + } else { + List errors = new ArrayList(Arrays.asList(myHandler.getErrors())); + for (int i=0, len=expectedErrors.length; i < len; i++) { + int line = expectedErrors[i]; + boolean found = false; + for (Iterator iter = errors.iterator(); iter.hasNext(); ) { + IMessage m = (IMessage)iter.next(); + if (m.getISourceLocation() != null && m.getISourceLocation().getLine() == line) { + found = true; + iter.remove(); + } + } + assertTrue("didn't find error on line " + line, found); + } + if (errors.size() > 0) { + assertTrue("didn't expect errors: " + errors, false); + } + } + return command; + } + + public static void printGenerated(String path, String name) throws IOException { + String fullpath = "testdata/" + path; + LazyClassGen.disassemble(fullpath, name, System.out); + } + + /** incremental test case adapter to JUnit */ + public class IncCase extends IncrementalCase { + protected void fail(IMessageHandler handler, String mssg) { + assertTrue(mssg, false); + } + protected void message( + IMessage.Kind kind, + String mssg, + IMessageHandler handler) { + if ((kind == IMessage.FAIL) || (kind == IMessage.ABORT)) { + assertTrue(mssg, false); + } else { + System.err.println("IncCase " + kind + ": " + mssg); // XXX + } + super.message(kind, mssg, handler); + } + + } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CompileAndRunTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CompileAndRunTestCase.java new file mode 100644 index 000000000..30a76570d --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CompileAndRunTestCase.java @@ -0,0 +1,90 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import java.io.IOException; + +import org.aspectj.testing.util.TestUtil; + + +public class CompileAndRunTestCase extends CommandTestCase { + + public CompileAndRunTestCase(String name) { + super(name); + } + + public void testAround() throws IOException { + checkCompile("src1/AroundA.java", NO_ERRORS); + TestUtil.runMain("out", "AroundAMain"); + } + + public void testInterType() throws IOException { + checkCompile("src1/InterType.java", NO_ERRORS); + TestUtil.runMain("out", "InterType"); + } + + public void testInterTypeMethods() throws IOException { + checkCompile("src1/InterTypeMethods.java", NO_ERRORS); + TestUtil.runMain("out", "InterTypeMethods"); + } + + public void testIf() throws IOException { + CommandTestCase.checkCompile("src1/IfPcd.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "IfPcd"); + } + + public void testDeclareParentsFail() throws IOException { + CommandTestCase.checkCompile("src1/ParentsFail.java", new int[] {3, 11, 19, 21}); + } + + public void testDeclareParents() throws IOException { + CommandTestCase.checkCompile("src1/Parents.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "Parents"); + } + + public void testPerCflow() throws IOException { + CommandTestCase.checkCompile("src1/PerCflow.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "PerCflow"); + } + + public void testPerObject() throws IOException { + CommandTestCase.checkCompile("src1/PerObject.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "PerObject"); + } + + public void testDeclareSoft() throws IOException { + CommandTestCase.checkCompile("src1/DeclareSoft.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "DeclareSoft"); + } + + public void testPrivileged() throws IOException { + CommandTestCase.checkCompile("src1/Privileged.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "Privileged"); + } + + public void testHandler() throws IOException { + CommandTestCase.checkCompile("src1/Handler.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "Handler"); + } + + public void testInterConstructors() throws IOException { + CommandTestCase.checkCompile("src1/InterTypeConstructors.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "InterTypeConstructors"); + } + + public void testAroundA1() throws IOException { + CommandTestCase.checkCompile("src1/AroundA1.java", CommandTestCase.NO_ERRORS); + TestUtil.runMain("out", "AroundA1"); + } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/ImageTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/ImageTestCase.java new file mode 100644 index 000000000..681c46668 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/ImageTestCase.java @@ -0,0 +1,58 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import java.io.*; +import java.io.File; +import java.util.*; + +import junit.framework.*; + +import org.aspectj.ajdt.internal.core.builder.*; +import org.aspectj.bridge.*; +import org.aspectj.util.*; +import org.aspectj.workbench.resources.*; +import org.eclipse.core.internal.resources.*; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; +import org.eclipse.jdt.core.compiler.*; +import org.eclipse.jdt.internal.compiler.*; +import org.eclipse.jdt.internal.compiler.Compiler; +import org.eclipse.jdt.internal.core.builder.*; + +public class ImageTestCase extends TestCase { + + + + public ImageTestCase(String name) { + super(name); + } + public void testNothing() {} + +// public void test1() throws IOException, CoreException { +// EclipseMessageHandler handler = new EclipseMessageHandler(new MessageHandler()); +// AjBuildManager config = new AjBuildManager(handler); +//// config.setArgs(new String[] { "testdata/src1/BadHello.java" }); +//// config.setArgs(new String[] { "testdata/src1/A.java" }); +// List files = new ArrayList(); +// files.add(new File("testdata/src1/A.java")); +// config.getBuildConfig().setFiles(files); +// +// SimpleBatchBuilder builder = new SimpleBatchBuilder(config); +// builder.run(); +// +// SimpleIncrementalBuilder builder1 = new SimpleIncrementalBuilder(config); +// builder1.run(); +// } +} + diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/IncrementalCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/IncrementalCase.java new file mode 100644 index 000000000..e4f645f3a --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/IncrementalCase.java @@ -0,0 +1,485 @@ +/* ******************************************************************* + * Copyright (c) 1999-2001 Xerox Corporation, + * 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import org.aspectj.bridge.ICommand; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.bridge.IMessageHolder; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.Message; +import org.aspectj.bridge.MessageHandler; +import org.aspectj.bridge.ReflectionFactory; +import org.aspectj.util.FileUtil; +import org.aspectj.util.LangUtil; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +/** + * Mostly stateless incremental test case. + * Subclass to use from junit. + */ +public class IncrementalCase { // XXX NOT bound to junit - bridge tests? + public static final String[] RA_String = new String[0]; // XXX + boolean verbose = true; + boolean ignoreWarnings = false; + + public static void main(String[] args) throws IOException { + IncrementalCase me = new IncrementalCase(); + MessageHandler h = new MessageHandler(); + boolean result; + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < args.length; i++) { + sb.append("\n###### results for " + args[i]); + sb.append("\n" + me.run(new File(args[i]), h) + ": " + h); + } + System.err.flush(); + System.out.flush(); + System.err.println(sb.toString()); + } + + /** + * Run an incremental compile case. + * For each i=1..9, copy files srcDir/*{i=1..9}0.java + * to the sandbox and compile. + * This only expects the changed files to be recompiled, but + * it also calls verifyCompile(..); + * @param handler all non-functional feedback here. + * Exceptions are logged as ABORT messages + */ + public boolean run(File srcBase, IMessageHandler handler) + throws IOException { + final String cname = ReflectionFactory.ECLIPSE; + + File targetBase = + makeDir(getSandboxDir(), "IncrementalCaseSandbox", handler); + if (null == targetBase) { + return false; + } + File targetSrc = makeDir(targetBase, "src", handler); + if (null == targetSrc) { + return false; + } + File targetClasses = makeDir(targetBase, "classes", handler); + if (null == targetClasses) { + return false; + } + final ArrayList files = new ArrayList(); + final FileFilter collector = new FileFilter() { + public boolean accept(File file) { + return files.add(file); + } + }; + final ICommand compiler = + ReflectionFactory.makeCommand(cname, handler); + + ArrayList recompiled = null; + boolean result = true; + + final String toSuffix = ".java"; + final String canonicalFrom = srcBase.getCanonicalPath(); + final Definition[] defs = getDefinitions(srcBase); + if ((null == defs) || (defs.length < 9)) { + throw new Error("did not get definitions"); + } + MessageHandler compilerMessages = new MessageHandler(); + StringBuffer commandLine = new StringBuffer(); + for (int i = 1; result && (i < 10); i++) { + String fromSuffix = "." + i + "0.java"; + // copy files, collecting as we go... + files.clear(); + FileUtil.copyDir( + srcBase, + targetSrc, + fromSuffix, + toSuffix, + collector); + if (0 == files.size()) { // XXX detect incomplete? + break; + } + List safeFiles = Collections.unmodifiableList(files); + log("Compiling ", safeFiles, handler); + if (1 == i) { + ArrayList argList = new ArrayList(); + argList.addAll(getBaseArgs(targetSrc, targetClasses)); + File[] fra = (File[]) safeFiles.toArray(new File[0]); + // sigh + argList.addAll( + Arrays.asList(FileUtil.getAbsolutePaths(fra))); + String[] args = (String[]) argList.toArray(new String[0]); + commandLine.append(""+argList); + result = compiler.runCommand(args, compilerMessages); + } else { + if (null == recompiled) { + recompiled = new ArrayList(); + } else { + recompiled.clear(); + } + compilerMessages.init(); + commandLine.append("["+i+": " + recompiled + "] "); + result = + compiler.repeatCommand(compilerMessages); + } + result = + verifyCompile( + i, + result, + srcBase, + targetSrc, + targetClasses, + defs[i - 1], + compilerMessages, + commandLine, + handler); + } + return result; + } + + // -------------------------------------- test case verification + /** + * Verify that this incremental compile step worked. + * @param recompiled the List of Files the compiler recompiled - null the first pass + * @param files the (unmodifiable) List of File passed as sources to the compiler + * @param recompiled the List sink for the Files actually recompiled + */ + // XXX argh no parent/child relationship in this world... + protected boolean verifyCompile( + int iteration, + boolean result, + File srcDir, + File sandboxSrcDir, + File sandboxClassesDir, + Definition def, + IMessageHolder compilerMessages, + StringBuffer commandLine, + IMessageHandler handler) { + log("verifyCompile - iteration ", new Integer(iteration), handler); + log("verifyCompile - def ", def, handler); + log("verifyCompile - command ", commandLine.toString(), handler); + log("verifyCompile - messages ", compilerMessages, handler); + StringBuffer failures = new StringBuffer(); + if (def.expectFail == result) { + failures.append("iteration " + iteration + + " expected to " + (def.expectFail ? "fail\n" : "pass")); + } + if (0 < failures.length()) { + fail(handler, + "\nFailures in iteration " + iteration + + "\n Command: " + commandLine + + "\nMessages: " + compilerMessages + + "\n Def: " + def + + "\nFailures: " + failures); + return false; + } + IMessage[] messages = compilerMessages.getMessages(IMessage.ERROR, IMessageHolder.EQUAL); + String[] expected = + (null != def.errors ? def.errors : def.eclipseErrors); + if (haveAll("errors", expected, messages, handler)) { + if (!ignoreWarnings) { + messages = compilerMessages.getMessages(IMessage.WARNING, IMessageHolder.EQUAL); + expected = + (null != def.warnings + ? def.warnings + : def.eclipseWarnings); + if (!haveAll("warnings", expected, messages, handler)) { + return false; + } + } + } + return true; + } + + // -------------------------------------- test case setup + /** + * Get the sandbox (parent) directory. + * This implementation uses the temporary directory + */ + protected File getSandboxDir() throws IOException { // XXX util + File tempFile = File.createTempFile("IncrementalCase", ".txt"); + File tempDir = tempFile.getParentFile(); + tempFile.delete(); + return tempDir; + } + + //XXX hack + public File outputDir; + + /** @param srcDir ignored for now */ + protected List getBaseArgs(File srcDir, File classesDir) { + outputDir = classesDir; + String[] input = + new String[] { + "-verbose", +// "-classpath", +// System.getProperty("sun.boot.class.path"), + "-d", + classesDir.getAbsolutePath()}; + return Collections.unmodifiableList( + new ArrayList(Arrays.asList(input))); + } + + protected File makeDir( + File parent, + String name, + IMessageHandler handler) { // XXX util + File result = new File(parent, name); + if (!result.exists()) { + result.mkdirs(); + if (!result.exists()) { + fail(handler, "unable to create " + result); + return null; + } + } + return result; + } + + // -------------------------------------- test case verification + + + List normalizeFilenames(String[] ra) { // XXX util + ArrayList result = new ArrayList(); + if (null != ra) { + for (int i = 0; i < ra.length; i++) { + result.add(normalizeFilename(ra[i])); + } + if (1 < ra.length) { + Collections.sort(result); + } + } + return result; + } + + /** @param list the List of File */ + List normalizeFilenames(List list) { // XXX util + ArrayList result = new ArrayList(); + for (Iterator iter = list.iterator(); iter.hasNext();) { + result.add(normalizeFilename(((File) iter.next()).getPath())); + } + Collections.sort(result); + return result; + } + + String normalizeFilename(String s) { // XXX error-prone + final String suffix = ".java"; + int loc = s.lastIndexOf(suffix); + if (-1 == loc) { + return s; // punt + } + s = s.substring(0, loc + suffix.length()).replace('\\', '/'); + loc = s.lastIndexOf("/"); + return (-1 == loc ? s : s.substring(loc+1)); + } + + + /** XXX duplicate message checking */ + boolean haveAll( + String label, + String[] expected, + IMessage[] messages, + IMessageHandler handler) { + if (null == expected) { + expected = new String[0]; + } + boolean result = true; + final int[] exp = new int[expected.length]; + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (int i = 0; i < exp.length; i++) { + String s = expected[i]; + int loc = s.lastIndexOf(":"); + if (-1 != loc) + s = s.substring(loc + 1); + try { + exp[i] = Integer.valueOf(s).intValue(); + sb.append(exp[i] + ((i < (exp.length - 1)) ? ", " : "")); + } catch (NumberFormatException e) { + info(handler, "bad " + label + ":" + expected[i]); + // XXX worse than info... + sb.append("bad" + ((i < (exp.length - 1)) ? ", " : "]")); + } + } + sb.append("]"); + final String context = + label + + "\n in context haveAll expected=" + + Arrays.asList(expected) + + " exp=" + + sb + + " actual=" + + Arrays.asList(messages); + info(handler, context); + + BitSet foundSet = new BitSet(10); + for (int i = 0; i < exp.length; i++) { + final int expLine = exp[i]; + boolean found = false; + for (int j = 0; !found && (j < messages.length); j++) { + ISourceLocation sl = messages[j].getISourceLocation(); + found = ((null != sl) && (expLine == sl.getLine())); + if (found) { + info(handler, "found " + label + " for: " + exp[i]); + if (foundSet.get(j)) { + info( + handler, + "duplicate " + label + " expected: " + exp[i]); + } + foundSet.set(j); + } + } + if (!found) { + String s = + "expected " + + label + + " not found: " + + exp[i] + + context; + fail(handler, s); // bad short-circuit + if (!result) { + result = false; + } + } + + } + sb.setLength(0); + for (int i = 0; i < messages.length; i++) { + if (!foundSet.get(i)) { + sb.append( + "\n unexpected " + label + " found: " + messages[i]); + } + } + if (0 == sb.length()) { + return true; + } else { + fail(handler, sb.toString() + context); + return false; + } + } + // -------------------------------------- messages + protected void log(String label, Object o, IMessageHandler handler) { + if (verbose) { + if (null != handler) { + message(IMessage.INFO, label + ": " + o, handler); + } else { + System.err.println("\nlog: " + label + ": " + o); + } + } + } + protected void info(IMessageHandler handler, String mssg) { + message(IMessage.INFO, mssg, handler); + } + protected void fail(IMessageHandler handler, String mssg) { + message(IMessage.FAIL, mssg, handler); + } + + /** this is the only client of the message handler - remplement to do other notification*/ + protected void message( + IMessage.Kind kind, + String mssg, + IMessageHandler handler) { + if (null != handler) { + handler.handleMessage( + new Message("\n### " + mssg, kind, null, null)); + } + } + + /** @return Definition[9] read from srceBase/Definition.PATH */ + Definition[] getDefinitions(File srcBase) { + File file = new File(srcBase, Definition.PATH); + Properties props = new Properties(); + FileInputStream in = null; + try { + in = new FileInputStream(file); + props.load(in); + } catch (IOException e) { + e.printStackTrace(System.err); + } finally { + if (null != in) + try { + in.close(); + } catch (IOException e) { + } + } + Definition[] result = new Definition[9]; + for (int i = 0; i < 9; i++) { // XXX matches run + result[i] = new Definition((1+i) + "0", props); + } + return result; + } + + static class Definition { + static final String PATH = "expected.txt"; + boolean expectFail; + String prefix; + String[] files; + String[] recompiled; + String[] errors; + String[] warnings; + String[] eclipseErrors; + String[] eclipseWarnings; + Definition(String prefix, Properties props) { + Enumeration keys = props.keys(); + this.prefix = prefix; + files = get(props, prefix + ".files"); + recompiled = get(props, prefix + ".recompiled"); + errors = get(props, prefix + ".errors"); + warnings = get(props, prefix + ".warnings"); + eclipseErrors = get(props, prefix + ".eclipse.errors"); + eclipseWarnings = get(props, prefix + ".eclipse.warnings"); + expectFail = + (((null != errors) && (0 < errors.length)) + || ((null != eclipseErrors) + && (0 < eclipseErrors.length))); + } + String[] get(Properties props, String key) { + String s = props.getProperty(key); + if (null != s) { + return LangUtil.split(s); + } + return null; + } + public String toString() { + return "Definition " + + " expectFail=" + + expectFail + + " prefix=" + + prefix + + " files=" + + safe(files) + + " recompiled=" + + safe(recompiled) + + " errors=" + + safe(errors) + + " warnings=" + + safe(warnings) + + " eclipseErrors=" + + safe(eclipseErrors) + + " eclipseWarnings=" + + safe(eclipseWarnings); + } + String safe(String[] in) { + return (null == in ? "" : "" + Arrays.asList(in)); + } + } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/MultipleCompileTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/MultipleCompileTestCase.java new file mode 100644 index 000000000..665cc98e4 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/MultipleCompileTestCase.java @@ -0,0 +1,35 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import java.io.*; + +import org.aspectj.weaver.bcel.*; + +import junit.framework.*; + +public class MultipleCompileTestCase extends CommandTestCase { + + /** + * Constructor for WorkingCommandTestCase. + * @param name + */ + public MultipleCompileTestCase(String name) { + super(name); + } + + public void testA1() throws IOException, InterruptedException { + checkMultipleCompile("src1/Hello.java"); + } +} + diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/VerifyWeaveTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/VerifyWeaveTestCase.java new file mode 100644 index 000000000..0a7471261 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/VerifyWeaveTestCase.java @@ -0,0 +1,114 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; +class Ignore {} +//import java.io.*; +//import java.util.*; +// +//import junit.framework.*; +// +////import org.apache.bcel.classfile.*; +//import org.aspectj.ajdt.ajc.*; +////import org.aspectj.weaver.bcel.*; +//import org.aspectj.bridge.*; +//import org.aspectj.testing.util.TestUtil; +//import org.aspectj.util.*; + +//public class VerifyWeaveTestCase extends WeaveTestCase { +// { +// regenerate = false; +// runTests = true; +// } +// +// static final String outDirName = "out"; +// static final String srcDir = "testdata" + File.separator + "src1"+ File.separator; +// +// public VerifyWeaveTestCase(String name) { +// super(name); +// } +// +// public void testCompile() throws IOException { +// buildTest("A", "Hello", outDirName); +// } +// +// +// public boolean doCompile(String fileToCompile, String specifiedOutDir) { +// List args = new ArrayList(); +// if (specifiedOutDir != null) { +// args.add("-d"); +// args.add(specifiedOutDir); +// } +// args.add("-classpath"); +// args.add("../runtime/bin"); +// args.add(fileToCompile); +// +// +// ICommand command = new AjdtCommand(); +// MessageHandler myHandler = new MessageHandler(); +// command.runCommand((String[])args.toArray(new String[0]), myHandler); +// IMessage[] info = myHandler.getMessages(IMessage.INFO, IMessageHolder.EQUAL); +//// System.out.println("info messages: " + Arrays.asList(info)); +//// System.out.println("compiled: " + fileToCompile); +//// System.out.println("errors: " + Arrays.asList(myHandler.getErrors())); +//// System.out.println("warnings: " + Arrays.asList(myHandler.getWarnings())); +// return true; +// } +// +// public void testBuildOutputDir() throws IOException { +// FileUtil.deleteContents(new File(outDirName)); +// +// doCompile(srcDir + "A.java", outDirName); +// assertTrue("default package, output dir specified", +// new File(outDirName + File.separator + "A.class").exists()); +// +// File testFile = new File(srcDir + "A.class"); +// //XXX These test for javac compatible behavior with output dirs +//// testFile.delete(); +//// doCompile(srcDir + "A.java", null); +//// assertTrue("default package, no output dir specified", +//// testFile.exists()); +//// +//// doCompile(srcDir + "Ap.java", null); +//// assertTrue("package named, no dir specified", +//// new File(srcDir + "Ap.class").exists()); +// +// doCompile(srcDir + "Ap.java", outDirName); +// File checkFile = +// new File(outDirName + File.separator + "src1" + File.separator + "Ap.class"); +// assertTrue("package named, dir specified: " + checkFile.getAbsolutePath(), +// checkFile.exists()); +// +// } +// +// public void buildTest(String name, String outName, String specifiedOutDir) throws IOException { +// String classDir = "bin"; +// +// doCompile(srcDir + name + ".java", specifiedOutDir); +// +// LazyClassGen gen = new LazyClassGen(new BcelObjectType(new ClassParser(outDirName + File.separator + outName +".class").parse())); +// +// try { +// checkClass(gen, outDirName, outName + ".txt"); +// if (runTests) { +// TestUtil.runMain(outDirName, "A"); +// } +// } catch (Error e) { +// gen.print(System.err); +// throw e; +// } catch (RuntimeException e) { +// gen.print(System.err); +// throw e; +// } +// } +// +//} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/WorkingTestMain.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/WorkingTestMain.java new file mode 100644 index 000000000..d93baa036 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/WorkingTestMain.java @@ -0,0 +1,131 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.batch; + +import java.io.IOException; +import java.util.*; +import java.util.List; + +import org.aspectj.testing.util.TestUtil; + +public class WorkingTestMain { + + public static void main(String[] args1) throws IOException { + //testExamples(); + testOne(); + } + + public static void testOne() throws IOException { + //CommandTestCase.checkCompile("src1/Parents.java", CommandTestCase.NO_ERRORS); + + //CommandTestCase.checkCompile("../../tests/new/ArgsInCflow2.java", CommandTestCase.NO_ERRORS); + + //CommandTestCase.checkCompile("src1/ParentsFail.java", CommandTestCase.NO_ERRORS); + + List args = new ArrayList(); + args.add("-verbose"); + + args.add("-d"); + args.add("out"); + + args.add("-classpath"); + args.add("../runtime/bin;../lib/junit/junit.jar;../testing-client/bin"); + //args.add("../runtime/bin;../lib/junit/junit.jar"); + +// args.add("-injars"); +// args.add("testdata/testclasses.jar"); + + //args.add("-aspectpath"); + //args.add("../bcweaver/testdata/megatrace.jar"); + + //args.add("testdata/src1/AroundA1.java"); + args.add("../tests/new/StrictFPAdvice.java"); + //args.add("-Xlint:error"); + //args.add("testdata/src1/InterType.java"); + //args.add("@" + examplesDir + "tjp/files.lst"); + + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + //CommandTestCase.runCompiler(args, new int[] {11, 14, 18, 32, 43}); + + CommandTestCase.printGenerated("../out", "StrictFPAdvice"); + CommandTestCase.printGenerated("../out", "A"); + + //TestUtil.runMain("out;../bcweaver/testdata/megatrace.jar", "Privileged"); + TestUtil.runMain("out;../lib/test/testing-client.jar", "StrictFPAdvice"); + } + + private static String examplesDir = "c:/aspectj/examples/"; + private static void example(String[] argfiles, String[] classes) { + List args = new ArrayList(); + args.add("-verbose"); + + args.add("-d"); + args.add("out"); + + args.add("-classpath"); + args.add("../runtime/bin"); + + for (int i=0; i < argfiles.length; i++) { + args.add("@" + examplesDir + argfiles[i]); + } + + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + for (int i=0; i < classes.length; i++) { + TestUtil.runMain("out", classes[i]); + } + } + + + public static void testExamples() throws IOException { +// example(new String[] {"observer/files.lst"}, +// new String[] {"observer.Demo"}); + +// example(new String[] {"tjp/files.lst"}, +// new String[] {"tjp.Demo"}); + + example(new String[] {"telecom/timing.lst"}, + new String[] {"telecom.TimingSimulation"}); + + example(new String[] {"telecom/billing.lst"}, + new String[] {"telecom.BillingSimulation"}); + + example(new String[] {"tracing/tracev1.lst"}, + new String[] {"tracing.version1.TraceMyClasses"}); + + example(new String[] {"tracing/tracev2.lst"}, + new String[] {"tracing.version2.TraceMyClasses"}); + + example(new String[] {"tracing/tracev3.lst"}, + new String[] {"tracing.version3.TraceMyClasses"}); + + + example(new String[] {"introduction/files.lst"}, + new String[] {"introduction.HashablePoint", "introduction.ComparablePoint"}); + + + + + example(new String[] {"bean/files.lst"}, + new String[] {"bean.Demo"}); + + example(new String[] {"spacewar/demo.lst"}, + new String[] {}); + + example(new String[] {"spacewar/debug.lst"}, + new String[] {}); + + + } + +} 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 new file mode 100644 index 000000000..4b98bba37 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java @@ -0,0 +1,366 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.*; +import java.util.*; + +import junit.framework.TestCase; +import org.aspectj.ajdt.ajc.BuildArgParser; +import org.aspectj.asm.*; +import org.aspectj.asm.StructureModelManager; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.MessageHandler; +import org.aspectj.bridge.MessageWriter; +import org.aspectj.testing.util.TestUtil; +import org.aspectj.util.*; +import org.aspectj.workbench.resources.FilesystemFolder; +import org.eclipse.core.internal.events.ResourceDelta; +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.internal.core.builder.*; +import org.eclipse.jdt.internal.core.builder.SimpleLookupTable; + +public class AjBuildManagerTest extends TestCase { + + private StreamPrintWriter outputWriter = new StreamPrintWriter(new PrintWriter(System.out)); + private MessageWriter messageWriter = new MessageWriter(outputWriter, false); + public static File source1 = new File("testdata/src1/A.java"); + public static File source2 = new File("testdata/src1/Hello.java"); + public static File source3 = new File("testdata/src1/X.java"); + + public AjBuildManagerTest(String name) { + super(name); + } + + public void testSimpleStructure() throws IOException, CoreException { + + AjBuildManager manager = new AjBuildManager(messageWriter); + BuildArgParser parser = new BuildArgParser(); + String javaClassPath = System.getProperty("java.class.path"); + AjBuildConfig buildConfig = + parser.genBuildConfig(new String[] { + "-d", "out", + "-classpath", + javaClassPath, + "testdata/src1/A.java", +// "testdata/src1/Hello.java", + }, messageWriter); + String err = parser.getOtherMessages(true); + assertTrue(err, null == err); + manager.setStructureModel(StructureModelManager.INSTANCE.getStructureModel()); + MessageHandler handler = new MessageHandler(); + manager.batchBuild(buildConfig, handler); + assertEquals(0, handler.numMessages(IMessage.WARNING, true)); +// System.out.println( +// ">> model: \n" + +// StructureModelManager.INSTANCE.getStructureModel().getRoot().toLongString() +// ); +// +// System.out.println( +// ">> children: \n" + +// ((StructureNode)StructureModelManager.INSTANCE.getStructureModel().getRoot().getChildren().get(0)).getChildren() +// ); + } + + + + + //XXX add test for resource deltas + + public void testUpdateBuildConfig() { + final File FILE_1 = new File("testdata/testclasses/Temp1.java"); + final File FILE_2 = new File("testdata/testclasses/Temp2.java"); + final File FILE_3 = new File("testdata/testclasses/Temp3.java"); + List files = new ArrayList(); + files.add(FILE_1); + files.add(FILE_2); + + AjBuildManager manager = new AjBuildManager(messageWriter); + AjBuildConfig buildConfig = new AjBuildConfig(); + manager.buildConfig = buildConfig; + buildConfig.setFiles(files); + + manager.updateBuildConfig(buildConfig); + assertTrue("no change", manager.deletedFiles.isEmpty()); + + AjBuildConfig newConfig = new AjBuildConfig(); + newConfig.getFiles().add(FILE_1); + newConfig.getFiles().add(FILE_2); + newConfig.getFiles().add(FILE_3); + manager.updateBuildConfig(newConfig); + assertTrue("added file", manager.deletedFiles.isEmpty()); + assertTrue(manager.addedFiles.size() == 1); + assertTrue(manager.addedFiles.contains(FILE_3)); + + newConfig = new AjBuildConfig(); + newConfig.getFiles().add(FILE_3); + manager.updateBuildConfig(newConfig); + assertTrue("deleted 2 files", manager.addedFiles.isEmpty()); + assertTrue(manager.deletedFiles.size() == 2); + assertTrue(manager.deletedFiles.contains(FILE_1)); + + newConfig = new AjBuildConfig(); + newConfig.getFiles().add(FILE_2); + manager.updateBuildConfig(newConfig); + assertTrue("added file", manager.addedFiles.size() == 1); + assertTrue("deleted file", manager.deletedFiles.size() == 1); + assertTrue(manager.deletedFiles.size() == 1); + assertTrue(manager.addedFiles.contains(FILE_2)); + assertTrue(manager.deletedFiles.contains(FILE_3)); + } + + /** + * Pretends that the files 'have been' modified in the future and waits. + * Tests: + * 1) no change, + * 2) added file, + * 3) removed file + * + * XXX should just test modified + */ + public void testGetModifiedFiles() throws IOException, InterruptedException { + final File TEMP_1 = new File("testdata/testclasses/TempChanged.java"); + final File EXISTS_2 = new File("testdata/testclasses/p1/Foo.java"); + final File NEW = new File("testdata/testclasses/TempNew.java"); + NEW.delete(); + touch(TEMP_1, false); + List files = new ArrayList(); + files.add(TEMP_1); + files.add(EXISTS_2); + + assertTrue("input files", TEMP_1.exists() && EXISTS_2.exists()); + assertTrue("new file", !NEW.exists()); + + Thread.sleep(100); + long lastBuildTime = System.currentTimeMillis(); + + AjBuildManager manager = new AjBuildManager(messageWriter); + manager.buildConfig = new AjBuildConfig(); + manager.buildConfig.setFiles(files); + Collection changedFiles = manager.getModifiedFiles(lastBuildTime); + assertTrue("nothing changed: " + changedFiles, changedFiles.isEmpty()); + + lastBuildTime = System.currentTimeMillis(); + Thread.sleep(100); + + touch(NEW, false); + + //NEW.createNewFile(); + files.add(NEW); + changedFiles = manager.getModifiedFiles(lastBuildTime); + assertTrue("new file: " + changedFiles, changedFiles.contains(NEW)); + + lastBuildTime = System.currentTimeMillis(); + Thread.sleep(100); + + files.remove(NEW); + changedFiles = manager.getModifiedFiles(lastBuildTime); + assertTrue("nothing changed", changedFiles.isEmpty()); + + lastBuildTime = System.currentTimeMillis(); + Thread.sleep(100); + + touch(TEMP_1, true); + changedFiles = manager.getModifiedFiles(lastBuildTime); + assertTrue("touched file: " + changedFiles, changedFiles.contains(TEMP_1)); + + lastBuildTime = System.currentTimeMillis(); + Thread.sleep(100); + + files.remove(NEW); + changedFiles = manager.getModifiedFiles(lastBuildTime); + assertTrue("nothing changed", changedFiles.isEmpty()); + + TEMP_1.delete(); + NEW.delete(); + } + + public void testMakeDeltas() throws IOException, InterruptedException { + AjBuildManager manager = new AjBuildManager(messageWriter); + manager.buildConfig = new AjBuildConfig(); + List sourceRoots = new ArrayList(); + sourceRoots.add(new File("out")); + manager.buildConfig.setSourceRoots(sourceRoots); + assertTrue(manager.testInit(messageWriter)); + List modified = Arrays.asList(new File[] { new File("A.java"), new File("B.java") }); + List deleted = Arrays.asList(new File[] { new File("X.java") }); + SimpleLookupTable deltas = new SimpleLookupTable(); + manager.makeDeltas( + deltas, + modified, + deleted, + ((File)manager.buildConfig.getSourceRoots().get(0)).getPath()); + + ResourceDelta d = (ResourceDelta)deltas.get(manager.getJavaBuilder().currentProject); + assertNotNull(d); + + assertEquals(d.getAffectedChildren().length, 3); + //XXX do more testing of children + } + + // XXX should this be working?? + public void testDeleteRealFiles() throws CoreException, IOException { + AjBuildManager manager = new AjBuildManager(messageWriter); + manager.buildConfig = new AjBuildConfig(); + List sourceRoots = new ArrayList(); + sourceRoots.add(new File("testdata/src1")); + manager.buildConfig.setSourceRoots(sourceRoots); + manager.buildConfig.setOutputDir(new File("out")); + assertTrue(manager.testInit(messageWriter)); + + File realClassFile = new File("out/X.class"); + touch(realClassFile, false); + + assertTrue(realClassFile.exists()); + + IFile classfile = manager.classFileCache.getFile(new Path("X.class")); + classfile.create(FileUtil.getStreamFromZip("testdata/testclasses.jar", "Hello.class"), true, null); + assertTrue(classfile.exists()); + + manager.addAspectClassFilesToWeaver(); + + classfile.delete(true, false, null); + assertTrue(realClassFile.exists()); + + manager.addAspectClassFilesToWeaver(); + + assertTrue(!realClassFile.exists()); + + } + + public void testIncrementalCompilerCall() throws IOException, InterruptedException, CoreException { + AjBuildManager manager = new AjBuildManager(messageWriter); + + manager.buildConfig = new AjBuildConfig(); + List roots = new ArrayList(); + roots.add(new File("testdata/src1")); + manager.testInit(messageWriter); + manager.buildConfig.setSourceRoots(roots); + assertTrue(manager.testInit(messageWriter)); + List modified = Arrays.asList(new File[] { source1, source2 }); + List deleted = Arrays.asList(new File[] { source3 }); + SimpleLookupTable deltas = new SimpleLookupTable(); + manager.makeDeltas( + deltas, + modified, + deleted, + ((File)manager.buildConfig.getSourceRoots().get(0)).getAbsolutePath()); + + JavaBuilder jbuilder = manager.getJavaBuilder(); + jbuilder.lastState = new State(jbuilder); + jbuilder.binaryResources = new SimpleLookupTable(); + + AjBuildManager.IncrementalBuilder builder + = manager.getIncrementalBuilder(messageWriter); // XXX trap errors + TestNotifier testNotifier = new TestNotifier(builder, jbuilder.currentProject); + jbuilder.notifier = testNotifier; + + IContainer[] sourceFolders = new IContainer[] { + new FilesystemFolder(((File)manager.buildConfig.getSourceRoots().get(0)).getAbsolutePath()) + }; + builder.setSourceFolders(sourceFolders); + testNotifier.builder = builder; + + IFile classfile = manager.classFileCache.getFile(new Path("X.class")); + classfile.create(new ByteArrayInputStream(new byte[] {1,2,3}), true, null); + + assertTrue(classfile.exists()); + + + try { + manager.testSetHandler(messageWriter); + boolean succeeded = builder.build(deltas); + } catch (NonLocalExit nle) { + assertEquals(nle.getExitCode(), 0); + } finally { + manager.testSetHandler(null); + } + + assertTrue(!classfile.exists()); + } + + static class TestNotifier extends BuildNotifier { + int state = 0; + AjBuildManager.IncrementalBuilder builder; + + public TestNotifier(AjBuildManager.IncrementalBuilder builder, IProject project) { + super(null, project); + this.builder = builder; + } + + + public void updateProgressDelta(float percentWorked) { + switch(state) { + case 0: + checkInitialConfig(); + break; + case 1: + checkBinaryResources(); + break; + case 2: + checkAffectedFiles(); + break; + } + state += 1; + } + + private void checkBinaryResources() { + } + + + private void checkInitialConfig() { + Collection files = builder.getLocations(); + //System.out.println("initial: " + files); + } + + private void checkAffectedFiles() { + Collection files = builder.getLocations(); + TestUtil.assertSetEquals(Arrays.asList(new String[] { + source1.getAbsolutePath().replace(File.separatorChar, '/'), + source2.getAbsolutePath().replace(File.separatorChar, '/') }), files); + throw new NonLocalExit(0); + } + } + + /** + * Method touch. + * @param NEW + * @param b + */ + private void touch(File file, boolean isAppend) throws IOException { + FileOutputStream s = new FileOutputStream(file.getAbsolutePath(), isAppend); + s.write(new byte[] {1,2,3}); + s.close(); + } + + + /* + * jar + * directory + * source directory + * container + */ +// public void testMakeClasspathLocations() { +// List classpath = new ArrayList(); +// classpath.add( +// +// AjBuildConfig config = new AjBuildConfig(); +// config.setClasspath() +// } + +// private void testClasspathLocation(String loca + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjdtBuilderTests.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjdtBuilderTests.java new file mode 100644 index 000000000..55b7690f3 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjdtBuilderTests.java @@ -0,0 +1,33 @@ +/* ******************************************************************* + * Copyright (c) 1999-2001 Xerox Corporation, + * 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.ajdt.internal.core.builder; + +import junit.framework.*; + +public class AjdtBuilderTests extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(AjdtBuilderTests.class.getName()); + //$JUnit-BEGIN$ + suite.addTestSuite(AjBuildManagerTest.class); + suite.addTestSuite(ClassFileCacheTest.class); + suite.addTestSuite(ClasspathContainerTestCase.class); + //$JUnit-END$ + return suite; + } + + public AjdtBuilderTests(String name) { super(name); } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/ClassFileCacheTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/ClassFileCacheTest.java new file mode 100644 index 000000000..1b8c78bfb --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/ClassFileCacheTest.java @@ -0,0 +1,253 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.*; +import java.util.*; + +import junit.framework.TestCase; + +import org.aspectj.bridge.MessageHandler; +import org.aspectj.testing.util.TestUtil; +import org.aspectj.util.*; +import org.aspectj.workbench.resources.FilesystemFolder; +import org.eclipse.core.resources.*; +import org.eclipse.core.runtime.*; + +public class ClassFileCacheTest extends TestCase { + + private MessageHandler handler = new MessageHandler(); + + public ClassFileCacheTest(String name) { + super(name); + } + + public void testExists() throws CoreException { + ClassFileCache cache = new ClassFileCache(new FilesystemFolder(new Path("out")), handler); + IPath folderPath = new Path("tempfolder"); + IFolder folder = cache.getFolder(folderPath); + + assertTrue("default folder always exists", cache.exists(new Path(""))); + assertTrue("default folder always exists", cache.getFolder(new Path("")).exists()); + + + assertTrue("" + folder, !cache.exists(folderPath)); + + folder.create(true, true, null); + assertTrue("created: " + folderPath, cache.exists(folderPath)); + assertTrue("created: " + folderPath, cache.getFolder(folderPath).exists()); + + folder.delete(true, null); + assertTrue("deleted: " + folderPath, !cache.exists(folderPath)); + + IPath filePath = new Path("tempfolder/TempClass.class"); + IFile file = cache.getFile(filePath); + assertTrue("" + file, !cache.exists(filePath)); + assertTrue("" + file, !cache.exists(folderPath)); + + createFile(cache, "tempfolder/TempClass.class"); + assertTrue("" + file, cache.exists(filePath)); + //XXX should be created when children are + //XXXassertTrue("" + file, cache.exists(folderPath)); + } + + public void testFilesAreCached() throws CoreException { + ClassFileCache cache = new ClassFileCache(new FilesystemFolder(new Path("out")), handler); + IFolder folder = cache.getFolder(new Path("testpath")); + IFile file1 = folder.getFile("Foo.class"); + assertTrue("" + file1.getClass(), file1 instanceof DeferredWriteFile); + + IFile file2 = cache.getFile(new Path("testpath/Foo.class")); + assertTrue("" + file2.getClass(), file2 instanceof DeferredWriteFile); + + assertTrue("" + file1 + ", " + file2, file1 == file2); + + + folder = cache.getFolder(new Path("testpath")); + folder = folder.getFolder("p1"); + assertTrue("" + folder, !folder.exists()); + + + file1 = folder.getFile(new Path("Bar.class")); + file2 = cache.getFile(new Path("testpath/p1/Bar.class")); + + assertTrue("" + file1.getClass(), file1 instanceof DeferredWriteFile); + assertTrue("" + file2.getClass(), file2 instanceof DeferredWriteFile); + + assertTrue("" + file1 + ", " + file2, file1 == file2); + + + assertTrue(!cache.exists(new Path("testpath/p1/Bar.class"))); + + InputStream source = new ByteArrayInputStream(new byte[] {0,1,2,3,4,5,6,7,8,9}); + file1.create(source, true, null); + assertTrue(cache.exists(new Path("testpath/p1/Bar.class"))); + + file1.delete(true, true, null); + assertTrue(!cache.exists(new Path("testpath/p1/Bar.class"))); + + IResource[] members = cache.members(); + assertEquals(members.length, 2); + + DeferredWriteFile dwf1 = (DeferredWriteFile) members[0]; + DeferredWriteFile dwf2 = (DeferredWriteFile) members[1]; + + if (dwf1.getName().endsWith("Bar.class")) { + DeferredWriteFile tmp = dwf1; + dwf1 = dwf2; dwf2 = tmp; + } + + assertTrue(!dwf1.exists()); + assertTrue(!dwf2.exists()); + + assertEquals(dwf1.getName(), "Foo.class"); + assertEquals(dwf2.getName(), "Bar.class"); + } + + public void testChange() throws CoreException { + MessageHandler handler = new MessageHandler(); + ClassFileCache cache = new ClassFileCache(new FilesystemFolder(new Path("out")), handler); + cache.resetIncrementalInfo(); + String path1 = "testpath/Foo.class"; + String path2 = "testpath/Bar.class"; +// cache.getFolder(new Path("testpath")).delete(true, false, null); + assertTrue(!cache.getFolder(new Path("testpath")).exists()); + + createFile(cache, path1); + createFile(cache, path2); + + //XXX assertTrue(cache.getFolder(new Path("testpath")).exists()); + + checkFileMatch(cache.getAddedOrChanged(), + new String[] { "out/" + path1, "out/" + path2 }); + checkFileMatch(cache.getDeleted(), new String[0] ); + + // added + cache.resetIncrementalInfo(); + String path3 = "testpath/Baz.class"; + createFile(cache, path3); + checkFileMatch(cache.getAddedOrChanged(), new String[] { "out/" + path3 }); + checkFileMatch(cache.getDeleted(), new String[0] ); + + // remove + cache.resetIncrementalInfo(); + deleteFile(cache, path3); + checkFileMatch(cache.getDeleted(), new String[] { "out/" + path3 }); + checkFileMatch(cache.getAddedOrChanged(), new String[0] ); + + // change + cache.resetIncrementalInfo(); + createFile(cache, path1); + + deleteFile(cache, path2); + createFile(cache, path2); + + checkFileMatch(cache.getAddedOrChanged(), + new String[] { "out/" + path1, "out/" + path2 }); + checkFileMatch(cache.getDeleted(), new String[0] ); + } + + public void testWrite() throws CoreException { + MessageHandler handler = new MessageHandler(); + clearDirectory("out"); + checkEmpty("out"); + + ClassFileCache cache = new ClassFileCache(new FilesystemFolder(new Path("out")), handler); + cache.resetIncrementalInfo(); + String path1 = "testpath/Foo.class"; + String path2 = "testpath/Bar.class"; + createFile(cache, path1); + createFile(cache, path2); + + checkEmpty("out"); + + writeCache(cache); + + checkContents("out", new String[] {"out/" + path1, "out/" + path2}); + + deleteFile(cache, path2); + checkContents("out", new String[] {"out/" + path1, "out/" + path2}); + writeCache(cache); + + checkContents("out", new String[] {"out/" + path1}); + } + + private void writeCache(ClassFileCache cache) throws CoreException { + IResource[] members = cache.members(); + for (int i = 0; i < members.length; i++) { + IResource iResource = members[i]; + DeferredWriteFile file = (DeferredWriteFile) iResource; + //System.out.println("about to write: " + file); + if (file.exists()) { + file.writeWovenBytes(new byte[] { 0, 1, 2,3}); + } else { + file.deleteRealFile(); + } + } + } + + private void checkContents(String path, String[] files) { + File dir = new File(path); + assertTrue(dir.exists()); + List allFiles = new ArrayList(); + listRecursively(new File(path), allFiles, ""); + TestUtil.assertSetEquals(Arrays.asList(files), allFiles); + } + + private void listRecursively(File file, List accumulator, String prefix) { + if (file.isDirectory()) { + if (prefix.length() == 0) prefix = file.getName() + "/"; + else prefix = prefix + file.getName() + "/"; + File[] files = file.listFiles(); + for (int i = 0; i < files.length; i++) { + listRecursively(files[i], accumulator, prefix); + } + } else { + accumulator.add(prefix + file.getName()); + } + } + + + + private void checkEmpty(String path) { + checkContents(path, new String[0]); + } + + + private void clearDirectory(String path) { + FileUtil.deleteContents(new File(path)); + } + + + private void checkFileMatch(List list, String[] names) { + Set found = new HashSet(); + for (Iterator iter = list.iterator(); iter.hasNext();) { + EclipseUnwovenClassFile file = (EclipseUnwovenClassFile) iter.next(); + found.add(file.getFile().getFullPath().toString()); + } + + TestUtil.assertSetEquals(Arrays.asList(names), found); + } + + private void createFile(ClassFileCache cache, String path) throws CoreException { + IFile file = cache.getFile(new Path(path)); + InputStream source = new ByteArrayInputStream(new byte[] {0,1,2,3,4,5,6,7,8,9}); + file.create(source, true, null); + } + + private void deleteFile(ClassFileCache cache, String path) throws CoreException { + IFile file = cache.getFile(new Path(path)); + file.delete(true, null); + } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/ClasspathContainerTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/ClasspathContainerTestCase.java new file mode 100644 index 000000000..cc06fa901 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/ClasspathContainerTestCase.java @@ -0,0 +1,66 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.core.builder; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.aspectj.util.FileUtil; +import org.aspectj.workbench.resources.FilesystemFolder; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.core.builder.ClasspathLocation; + +public class ClasspathContainerTestCase extends TestCase { + + public ClasspathContainerTestCase(String name) { + super(name); + } + + // XXX add some inner cases + public void testFindClass() throws IOException { + FileUtil.extractJar("testdata/testclasses.jar", "out/testclasses"); + + + IContainer container = new FilesystemFolder(new Path("out/testclasses")); + ClasspathLocation classpathLocation = new ClasspathContainer(container); + // put back in for sanity check + //classpathLocation = ClasspathContainer.forBinaryFolder("testdata/testclasses"); + + NameEnvironmentAnswer answer = classpathLocation.findClass("Hello.class", "", "Hello.class"); + assertTrue("" + answer, answer != null); + + NameEnvironmentAnswer answer2 = classpathLocation.findClass("Foo.class", "p1", "p1/Foo.class"); + assertTrue("" + answer2, answer2 != null); + + NameEnvironmentAnswer answer3 = classpathLocation.findClass("DoesNotExist.class", "", "DoesNotExist.class"); + assertTrue("" + answer3, answer3 == null); + + NameEnvironmentAnswer answer4 = classpathLocation.findClass("DoesNotExist.class", "p1", "DoesNotExist.class"); + assertTrue("" + answer4, answer4 == null); + + + } + + public void testIsPackage() { + IContainer container = new FilesystemFolder(new Path("testdata/testclasses")); + ClasspathLocation classpathLocation = new ClasspathContainer(container); + + assertTrue("is a package", classpathLocation.isPackage("p1")); + assertTrue("is not a package", !classpathLocation.isPackage("mumble")); + assertTrue("is not a package", !classpathLocation.isPackage("Hello.class")); + } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/FilesystemFileTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/FilesystemFileTest.java new file mode 100644 index 000000000..a320cceec --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/FilesystemFileTest.java @@ -0,0 +1,112 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.workbench.resources; + +import java.io.*; +import java.io.FileInputStream; + +import junit.framework.TestCase; +import org.aspectj.util.FileUtil; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.IProgressMonitor; + +//XXX this *has* to be tested on Linux +public class FilesystemFileTest extends TestCase { + + private static final String PATH = "testdata" + File.separator + "resources" + File.separator; + + private static final String TEST = PATH + "test.txt"; + private static final String SOURCE = PATH + "file.txt"; + private static final String EMPTY = PATH + "empty.txt"; + private IProgressMonitor monitor = new NullProgressMonitor(); + private FilesystemFile file; + private File javaFile; + + protected void setUp() throws Exception { + super.setUp(); + file = new FilesystemFile(TEST); + javaFile = new File(TEST); + } + + protected void tearDown() throws Exception { + super.tearDown(); + if (file.exists()) file.delete(true, monitor); + } + + public FilesystemFileTest(String name) { + super(name); + } + + public void testCreateExistsContentsDelete() throws FileNotFoundException, CoreException, InterruptedException, IOException { + if (file.exists()) file.delete(true, monitor); + assertTrue(!file.exists()); + FileInputStream fis = new FileInputStream(SOURCE); + + file.create(fis, 0, monitor); + fis.close(); + assertTrue(file.exists()); + + String expected = FileUtil.readAsString(new File(SOURCE)); + String contents = FileUtil.readAsString(file.getContents()); + assertEquals(expected, contents); + + file.setContents(new FileInputStream(EMPTY), 0, monitor); + assertEquals("", FileUtil.readAsString(file.getContents())); + + file.delete(true, monitor); + assertTrue(!file.exists()); + } + + public void testGetFileExtension() { + assertEquals(file.getFileExtension(), "txt"); + } + + public void testGetFullPath() { + assertEquals(file.getFullPath().toString(), javaFile.getPath().replace('\\', '/')); + } + + public void testGetLocation() { + assertEquals(file.getLocation().toString(), javaFile.getAbsolutePath().replace('\\', '/')); + } + + public void testGetName() { + assertEquals(file.getName(), javaFile.getName()); + } + + public void testGetModificationStamp() throws IOException, CoreException { + FileInputStream fis = new FileInputStream(SOURCE); + file.create(fis, 0, monitor); + assertEquals(file.getModificationStamp(), javaFile.lastModified()); + } + + public void testGetParent() { + assertEquals(file.getParent().getFullPath().toString(), javaFile.getParentFile().getPath().replace('\\', '/')); + } + + public void testReadOnly() throws CoreException, IOException { + FileInputStream fis = new FileInputStream(SOURCE); + file.create(fis, 0, monitor); + + assertTrue(!file.isReadOnly()); + file.setReadOnly(true); + assertTrue(file.isReadOnly()); + } + + //XXX not implemented + public void testCopy() { } + + //XXX not implemented + public void testTouch() { } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/FilesystemFolderTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/FilesystemFolderTest.java new file mode 100644 index 000000000..a958808f2 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/FilesystemFolderTest.java @@ -0,0 +1,128 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.workbench.resources; + +import java.io.*; +import junit.framework.TestCase; +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.IProgressMonitor; + +public class FilesystemFolderTest extends TestCase { + + private static final String PATH = "testdata" + File.separator + "resources" + File.separator; + private static final String DIR = PATH + "dir"; + private IProgressMonitor monitor = new NullProgressMonitor(); + private FilesystemFolder dir; + private File javaDir; + + public FilesystemFolderTest(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + dir = new FilesystemFolder(DIR); + javaDir = new File(DIR); + } + + protected void tearDown() throws Exception { + super.tearDown(); + dir.delete(true, monitor); + } + + public void testCreateExistsDelete() throws CoreException { + dir.delete(true, monitor); + assertTrue(!dir.exists()); + + dir.create(true, true, monitor); + assertTrue(dir.exists()); + assertTrue(javaDir.exists()); + + dir.delete(true, monitor); + assertTrue(!dir.exists()); + assertTrue(!javaDir.exists()); + } + + public void testGetFullPath() { + assertEquals(dir.getFullPath().toString(), javaDir.getPath().replace('\\', '/')); + } + + public void testGetLocation() { + assertEquals(dir.getLocation().toString(), javaDir.getAbsolutePath().replace('\\', '/')); + } + + public void testGetName() { + assertEquals(dir.getName(), javaDir.getName()); + } + + public void testGetModificationStamp() throws CoreException { + dir.create(true, true, monitor); + assertEquals(dir.getModificationStamp(), javaDir.lastModified()); + } + + public void testReadOnly() throws CoreException, IOException { + dir.create(true, true, monitor); + + assertTrue(!dir.isReadOnly()); + assertTrue(javaDir.canWrite()); + dir.setReadOnly(true); + assertTrue(dir.isReadOnly()); + assertTrue(!javaDir.canWrite()); + } + + public void testGetParent() { + assertEquals(dir.getParent().getFullPath().toString(), javaDir.getParentFile().getPath().replace('\\', '/')); + } + + public void testExistsAbsoluteAndRelativeIPath() throws CoreException { + final String CHILD_PATH = DIR + File.separator + "child"; + IPath childIPath = new Path(CHILD_PATH); + FilesystemFolder child = new FilesystemFolder(CHILD_PATH); + + child.create(true, true, monitor); + assertTrue("relative", dir.exists(childIPath)); + + IPath absoluteChildIPath = new Path(new File(CHILD_PATH).getAbsolutePath()); + assertTrue("absolute", dir.exists(absoluteChildIPath)); + } + + public void testGetFileIPath() { + final String DIRFILE = "dirfile.txt"; + IFile dirfile = dir.getFile(DIRFILE); + assertEquals( + dirfile.getLocation().toString(), + new File(DIR + File.separator + DIRFILE).getAbsolutePath().replace('\\', '/')); + } + + public void testGetFolderIPath() { + final String DIRFOLDER = "dirfolder"; + IFolder dirfile = dir.getFolder(DIRFOLDER); + assertEquals( + dirfile.getLocation().toString(), + new File(DIR + File.separator + DIRFOLDER).getAbsolutePath().replace('\\', '/')); + } + + //XXX not implemented + public void testCopy() { } + + //XXX not implemented + public void testTouch() { } + + //XXX not implemented + public void testFindMemberIPath() { } + + //XXX not implemented + public void testMembers() { } +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/WorkspaceResourcesTests.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/WorkspaceResourcesTests.java new file mode 100644 index 000000000..bba3f0c01 --- /dev/null +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/workbench/resources/WorkspaceResourcesTests.java @@ -0,0 +1,31 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.workbench.resources; + +import junit.framework.*; + +public class WorkspaceResourcesTests { + + public static void main(String[] args) { + } + + public static Test suite() { + TestSuite suite = + new TestSuite("Test for org.aspectj.workbench.resources"); + //$JUnit-BEGIN$ + suite.addTest(new TestSuite(FilesystemFileTest.class)); + suite.addTest(new TestSuite(FilesystemFolderTest.class)); + //$JUnit-END$ + return suite; + } +} |