<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="java5-testsrc"/>
- <classpathentry sourcepath="JRE_SRC" kind="var" path="JRE_LIB"/>
+ <classpathentry kind="var" path="JRE_LIB" sourcepath="JRE_SRC"/>
<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 sourcepath="/lib/bcel/bcel-src.zip" kind="lib" path="/lib/bcel/bcel.jar"/>
- <classpathentry sourcepath="/lib/junit/junit-src.jar" kind="lib" path="/lib/junit/junit.jar"/>
+ <classpathentry kind="lib" path="/lib/bcel/bcel.jar" sourcepath="/lib/bcel/bcel-src.zip"/>
+ <classpathentry kind="lib" path="/lib/junit/junit.jar" sourcepath="/lib/junit/junit-src.jar"/>
<classpathentry kind="src" path="/testing-util"/>
<classpathentry kind="src" path="/testing-client"/>
<classpathentry kind="src" path="/org.eclipse.jdt.core"/>
<classpathentry combineaccessrules="false" kind="src" path="/loadtime"/>
+ <classpathentry kind="lib" path="/lib/bcel/bcel-verifier.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
private static boolean LOADED_BUNDLE = false;
static {
- bundle = ResourceBundle.getBundle(BUNDLE_NAME);
+ Main.bundleName = BUNDLE_NAME;
+ ResourceBundleFactory.getBundle(Locale.getDefault());
if (!LOADED_BUNDLE) {
LOADED_BUNDLE = true;
}
}
/** @return multi-line String usage for the compiler */
- public static String getUsage() {
- return Main.bind("misc.usage",Main.bind("compiler.name"));
+ public static String getUsage() {
+ return _bind("misc.usage",new String[]{_bind("compiler.name",(String[])null)});
}
public static String getXOptionUsage() {
- return Main.bind("xoption.usage",Main.bind("compiler.name"));
+ return _bind("xoption.usage",new String[]{_bind("compiler.name",(String[])null)});
}
/**
return buildConfig;
}
-
- // from super...
public void printVersion() {
- System.err.println("AspectJ Compiler " + Version.text + " built on " + Version.time_text); //$NON-NLS-1$
- System.err.flush();
+ final String version = bind("misc.version", //$NON-NLS-1$
+ new String[] {
+ bind("compiler.name"), //$NON-NLS-1$
+ Version.text+" - Built: "+Version.time_text,
+ bind("compiler.version"), //$NON-NLS-1$
+ bind("compiler.copyright") //$NON-NLS-1$
+ }
+ );
+ System.out.println(version);
}
public void printUsage() {
} else {
showError("-Xajruntimetarget:<level> only supports a target level of 1.2 or 1.5");
}
+ } else if (arg.equals("-timers")) {
+ // swallow - it is dealt with in Main.runMain()
} else if (arg.equals("-1.5")) {
buildConfig.setBehaveInJava5Way(true);
unparsedArgs.add("-1.5");
// this would enable the '-source 1.5' to do the same as '-1.5' but doesnt sound quite right as
// as an option right now as it doesnt mean we support 1.5 source code - people will get confused...
+ } else if (arg.equals("-1.6")) {
+ buildConfig.setBehaveInJava5Way(true);
+ unparsedArgs.add("-1.6");
} else if (arg.equals("-source")) {
if (args.size() > nextArgIndex) {
String level = ((ConfigParser.Arg)args.get(nextArgIndex)).getValue();
- if (level.equals("1.5") || level.equals("5")) {
+ if (level.equals("1.5") || level.equals("5") ||
+ level.equals("1.6") || level.equals("6")) {
buildConfig.setBehaveInJava5Way(true);
}
unparsedArgs.add("-source");
--- /dev/null
+/* *******************************************************************
+ * 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 Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+
+package org.aspectj.ajdt.ajc;
+
+import java.util.*;
+import java.io.*;
+
+public class ConfigParser {
+ Location location;
+ protected File relativeDirectory = null;
+ protected List files = new LinkedList();
+ private boolean fileParsed = false;
+ protected static String CONFIG_MSG = "build config error: ";
+
+ public List getFiles() { return files; }
+
+ public void parseCommandLine(String[] argsArray) throws ParseException {
+ location = new CommandLineLocation();
+ LinkedList args = new LinkedList();
+ for (int i = 0; i < argsArray.length; i++) {
+ args.add(new Arg(argsArray[i], location));
+ }
+ parseArgs(args);
+ }
+
+ public void parseConfigFile(File configFile) throws ParseException {
+ if (fileParsed == true) {
+ throw new ParseException(CONFIG_MSG + "The file has already been parsed.", null);
+ } else {
+ parseConfigFileHelper(configFile);
+ }
+ }
+
+ /**
+ * @throws ParseException if the config file has already been prased.
+ */
+ private void parseConfigFileHelper(File configFile) {
+ if (!configFile.exists()) {
+ showError("file does not exist: " + configFile.getPath());
+ return;
+ }
+
+ LinkedList args = new LinkedList();
+ int lineNum = 0;
+
+ try {
+ BufferedReader stream =
+ new BufferedReader(new FileReader(configFile));
+ String line = null;
+ while ( (line = stream.readLine()) != null) {
+ lineNum += 1;
+ line = stripWhitespaceAndComments(line);
+ if (line.length() == 0) continue;
+ args.add(new Arg(line, new CPSourceLocation(configFile, lineNum)));
+ }
+ stream.close();
+ } catch (IOException e) {
+ location = new CPSourceLocation(configFile, lineNum);
+ showError("error reading config file: " + e.toString());
+ }
+ File oldRelativeDirectory = relativeDirectory; // for nested arg files;
+ relativeDirectory = configFile.getParentFile();
+ parseArgs(args);
+ relativeDirectory = oldRelativeDirectory;
+ fileParsed = true;
+ }
+
+ File getCurrentDir() {
+ return location.getDirectory();
+ }
+
+ String stripSingleLineComment(String s, String commentString) {
+ int commentStart = s.indexOf(commentString);
+ if (commentStart == -1) return s;
+ else return s.substring(0, commentStart);
+ }
+
+ String stripWhitespaceAndComments(String s) {
+ s = stripSingleLineComment(s, "//");
+ s = stripSingleLineComment(s, "#");
+ s = s.trim();
+ if (s.startsWith("\"") && s.endsWith("\"")) {
+ s = s.substring(1, s.length()-1);
+ }
+ return s;
+ }
+
+
+ /** ??? We would like to call a showNonFatalError method here
+ * to show all errors in config files before aborting the compilation
+ */
+ protected void addFile(File sourceFile) {
+ if (!sourceFile.isFile()) {
+ showError("source file does not exist: " + sourceFile.getPath());
+ }
+
+ files.add(sourceFile);
+ }
+
+ void addFileOrPattern(File sourceFile) {
+ if (sourceFile.getName().equals("*.java")) {
+ addFiles(sourceFile.getParentFile(), new FileFilter() {
+ public boolean accept(File f) {
+ return f != null && f.getName().endsWith(".java");
+ }});
+ } else if (sourceFile.getName().equals("*.aj")) {
+ addFiles(sourceFile.getParentFile(), new FileFilter() {
+ public boolean accept(File f) {
+ return f != null && f.getName().endsWith(".aj");
+ }});
+ } else {
+ addFile(sourceFile);
+ }
+ }
+
+ void addFiles(File dir, FileFilter filter) {
+ if (dir == null) dir = new File(System.getProperty("user.dir"));
+
+ if (!dir.isDirectory()) {
+ showError("can't find " + dir.getPath());
+ } else {
+
+ File[] files = dir.listFiles(filter);
+ if (files.length == 0) {
+ showWarning("no matching files found in: " + dir);
+ }
+
+ for (int i = 0; i < files.length; i++) {
+ addFile(files[i]);
+ }
+ }
+ }
+
+ protected void parseOption(String arg, LinkedList args) {
+ showWarning("unrecognized option: " + arg);
+ }
+
+ protected void showWarning(String message) {
+ if (location != null) {
+ message += " at " + location.toString();
+ }
+ System.err.println(CONFIG_MSG + message);
+ }
+
+ protected void showError(String message) {
+ throw new ParseException(CONFIG_MSG + message, location);
+ }
+
+ void parseArgs(LinkedList args) {
+ while (args.size() > 0) parseOneArg(args);
+ }
+
+ protected Arg removeArg(LinkedList args) {
+ if (args.size() == 0) {
+ showError("value missing");
+ return null;
+ } else {
+ return (Arg)args.removeFirst();
+ }
+ }
+
+ protected String removeStringArg(LinkedList args) {
+ Arg arg = removeArg(args);
+ if (arg == null) return null;
+ return arg.getValue();
+ }
+
+ boolean isSourceFileName(String s) {
+ if (s.endsWith(".java")) return true;
+ if (s.endsWith(".aj")) return true;
+ if (s.endsWith(".ajava")) {
+ showWarning(".ajava is deprecated, replace with .aj or .java: " + s);
+ return true;
+ }
+ return false;
+ }
+
+ void parseOneArg(LinkedList args) {
+ Arg arg = removeArg(args);
+ String v = arg.getValue();
+ location = arg.getLocation();
+ if (v.startsWith("@")) {
+ parseImportedConfigFile(v.substring(1));
+ } else if (v.equals("-argfile")) {
+ parseConfigFileHelper(makeFile(removeArg(args).getValue()));
+ } else if (isSourceFileName(v)) {
+ addFileOrPattern(makeFile(v));
+ } else {
+ parseOption(arg.getValue(), args);
+ }
+ }
+
+ protected void parseImportedConfigFile(String relativeFilePath) {
+ parseConfigFileHelper(makeFile(relativeFilePath));
+ }
+
+ public File makeFile(String name) {
+ if (relativeDirectory != null) {
+ return makeFile(relativeDirectory,name);
+ } else {
+ return makeFile(getCurrentDir(), name);
+ }
+ }
+
+ private File makeFile(File dir, String name) {
+ name = name.replace('/', File.separatorChar);
+ File ret = new File(name);
+ boolean isAbsolute = ret.isAbsolute()
+ || (ret.exists() && ret.getPath().startsWith(File.separator));
+ if (!isAbsolute && (dir != null)) {
+ ret = new File(dir, name);
+ }
+ try {
+ ret = ret.getCanonicalFile();
+ } catch (IOException ioEx) {
+ // proceed without canonicalization
+ // so nothing to do here
+ }
+ return ret;
+ }
+
+
+ protected static class Arg {
+ private Location location;
+ private String value;
+ public Arg(String value, Location location) {
+ this.value = value;
+ this.location = location;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public void setLocation(Location location) {
+ this.location = location;
+ }
+
+ public String getValue() { return value; }
+ public Location getLocation() { return location; }
+ }
+
+ static abstract class Location {
+ public abstract File getFile();
+ public abstract File getDirectory();
+ public abstract int getLine();
+ public abstract String toString();
+ }
+
+ static class CPSourceLocation extends Location {
+ private int line;
+ private File file;
+ public CPSourceLocation(File file, int line) {
+ this.line = line;
+ this.file = file;
+ }
+
+ public File getFile() { return file; }
+ public File getDirectory() { return file.getParentFile(); }
+ public int getLine() { return line; }
+
+ public String toString() {
+ return file.getPath()+":"+line;
+ }
+ }
+
+ static class CommandLineLocation extends Location {
+ public File getFile() {
+ return new File(System.getProperty("user.dir"));
+ }
+
+ public File getDirectory() {
+ return new File(System.getProperty("user.dir"));
+ }
+ public int getLine() { return -1; }
+ public String toString() {
+ return "command-line";
+ }
+ }
+
+ public static class ParseException extends RuntimeException {
+ private Location location;
+
+ public ParseException(String message, Location location) {
+ super(message);
+ this.location = location;
+ }
+
+ public int getLine() {
+ if (location == null) return -1;
+ return location.getLine();
+ }
+ public File getFile() {
+ if (location == null) return null;
+ return location.getFile();
+ }
+ }
+}
import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.core.builder.AjState;
+import org.aspectj.asm.internal.CharOperation;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.IProgressListener;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.aspectj.util.CharOperation;
import org.aspectj.weaver.bcel.BcelWeaver;
import org.aspectj.weaver.bcel.BcelWorld;
import org.aspectj.weaver.patterns.CflowPointcut;
this.inJava5Mode = false;
this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
this.incrementalCompilationState = incrementalCompilationState;
-
- if (compiler.options.complianceLevel == CompilerOptions.JDK1_5) inJava5Mode = true;
+
+ if (compiler.options.complianceLevel >= ClassFileConstants.JDK1_5) inJava5Mode = true;
IMessageHandler msgHandler = world.getMessageHandler();
// Do we need to reset the message handler or create a new one? (This saves a ton of memory lost on incremental compiles...)
if (msgHandler instanceof WeaverMessageHandler) {
/** Return true if we've decided to drop back to a full build (too much has changed) */
private boolean weaveQueuedEntries() throws IOException {
- if (debugPipeline)System.err.println(">.weaveQueuedEntries()");
+ if (debugPipeline) System.err.println(">.weaveQueuedEntries()");
for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
try {
weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
} finally {
- CflowPointcut.clearCaches();
weaver.tidyUp();
IMessageHandler imh = weaver.getWorld().getMessageHandler();
if (imh instanceof WeaverMessageHandler)
private void postWeave() {
if (debugPipeline)System.err.println("> postWeave()");
IMessageHandler imh = weaver.getWorld().getMessageHandler();
- CflowPointcut.clearCaches();
if (imh instanceof WeaverMessageHandler)
((WeaverMessageHandler)imh).setCurrentResult(null);
if (!droppingBackToFullBuild) weaver.allWeavingComplete();
*******************************************************************************/
package org.aspectj.ajdt.internal.compiler;
+import java.util.Iterator;
+
import org.aspectj.weaver.bcel.UnwovenClassFile;
import org.aspectj.weaver.bcel.UnwovenClassFileWithThirdPartyManagedBytecode;
+import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
public static UnwovenClassFile[] unwovenClassFilesFor(CompilationResult result,
IOutputClassFileNameProvider nameProvider) {
ClassFile[] cfs = result.getClassFiles();
- UnwovenClassFile[] ret = new UnwovenClassFile[cfs.length];
- for (int i = 0; i < ret.length; i++) {
- ClassFileBasedByteCodeProvider p = new ClassFileBasedByteCodeProvider(cfs[i]);
- String fileName = nameProvider.getOutputClassFileName(cfs[i].fileName(), result);
- ret[i] = new UnwovenClassFileWithThirdPartyManagedBytecode(fileName,p);
+ UnwovenClassFile[] ret = new UnwovenClassFile[result.compiledTypes.size()];
+ int i=0;
+ for (Iterator iterator = result.compiledTypes.keySet().iterator(); iterator.hasNext();) {
+ char[] className = (char[])iterator.next();
+ ClassFile cf = (ClassFile)result.compiledTypes.get(className);
+ // OPTIMIZE use char[] for classname
+ ClassFileBasedByteCodeProvider p = new ClassFileBasedByteCodeProvider(cf);
+ String fileName = nameProvider.getOutputClassFileName(cf.fileName(), result);
+ ret[i++] = new UnwovenClassFileWithThirdPartyManagedBytecode(fileName,new String(className).replace('/','.'),p);
}
+//
+// UnwovenClassFile[] ret = new UnwovenClassFile[cfs.length];
+// for (int i = 0; i < ret.length; i++) { result.compiledTypes;
+// ClassFileBasedByteCodeProvider p = new ClassFileBasedByteCodeProvider(cfs[i]);
+// String fileName = nameProvider.getOutputClassFileName(cfs[i].fileName(), result);
+// // APR29
+// ret[i] = new UnwovenClassFileWithThirdPartyManagedBytecode(fileName,CharOperation.toString(cfs[i].getCompoundName()),p);
+// }
return ret;
}
for (int i=0; i < ucfList.size(); i++) {
UnwovenClassFile element = (UnwovenClassFile) ucfList.get(i);
unwovenClassFiles[i] = element;
- AjClassFile ajcf = new AjClassFile(element.getClassName().replace('.', '/').toCharArray(),
+ AjClassFile ajcf = new AjClassFile(element.getClassNameAsChars(),
element.getBytes());
result.record(ajcf.fileName(),ajcf);
}
import java.util.Iterator;
import java.util.Map;
+import org.aspectj.asm.internal.CharOperation;
+import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IProgressListener;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
// progress reporting logic
fromPercent = 50.0; // Assume weaving takes 50% of the progress bar...
- recordProgress("processing reweavable state");
+ // recordProgress("processing reweavable state");
}
public void addingTypeMungers() {
// At this point we have completed one iteration through all the classes/aspects
// we'll be dealing with, so let us remember this max value for localIteratorCounter
// (for accurate progress reporting)
- recordProgress("adding type mungers");
+ // recordProgress("adding type mungers");
progressMaxTypes = localIteratorCounter;
}
if ((lastReturnedResult != null) && (!lastReturnedResult.result().hasBeenAccepted)) {
finishedWith(lastReturnedResult);
}
+ lastReturnedResult=null;
}
* @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile)
*/
public void acceptResult(UnwovenClassFile result) {
- char[] key = result.getClassName().replace('.','/').toCharArray();
- removeFromMap(lastReturnedResult.result().compiledTypes,key);
- String className = result.getClassName().replace('.', '/');
- AjClassFile ajcf = new AjClassFile(className.toCharArray(),
- result.getBytes());
+ char[] key = result.getClassNameAsChars();
+ removeFromMap(lastReturnedResult.result().compiledTypes, key);
+ AjClassFile ajcf = new AjClassFile(key, result.getBytes());
lastReturnedResult.result().record(ajcf.fileName(),ajcf);
- //System.err.println(progressPhasePrefix+result.getClassName()+" (from "+nowProcessing.fileName()+")");
- weaverMessageHandler.handleMessage(MessageUtil.info(progressPhasePrefix+result.getClassName()+" (from "+nowProcessing.fileName()+")"));
- if (progressListener != null) {
- progressCompletionCount++;
-
- // Smoothly take progress from 'fromPercent' to 'toPercent'
- recordProgress(
- fromPercent
- +((progressCompletionCount/(double)progressMaxTypes)*(toPercent-fromPercent)),
- progressPhasePrefix+result.getClassName()+" (from "+nowProcessing.fileName()+")");
-
- if (progressListener.isCancelledRequested()) {
- throw new AbortCompilation(true,new OperationCanceledException("Weaving cancelled as requested"));
+ if (!weaverMessageHandler.isIgnoring(IMessage.INFO) || progressListener!=null) {
+ StringBuffer msg = new StringBuffer();
+ msg.append(progressPhasePrefix).append(result.getClassName()).append(" (from ").append(nowProcessing.fileName()).append(")");
+ weaverMessageHandler.handleMessage(MessageUtil.info(msg.toString()));
+ if (progressListener != null) {
+ progressCompletionCount++;
+
+ // Smoothly take progress from 'fromPercent' to 'toPercent'
+ recordProgress(
+ fromPercent
+ +((progressCompletionCount/(double)progressMaxTypes)*(toPercent-fromPercent)),
+ msg.toString());
+ // progressPhasePrefix+result.getClassName()+" (from "+nowProcessing.fileName()+")");
+
+ if (progressListener.isCancelledRequested()) {
+ throw new AbortCompilation(true,new OperationCanceledException("Weaving cancelled as requested"));
+ }
}
- }
+ }
}
// helpers...
compilerAdapter.acceptResult(result.result());
}
- private void removeFromMap(Map aMap, char[] key) {
+ private boolean removeFromMap(Map aMap, char[] key) {
// jdt uses char[] as a key in the hashtable, which is not very useful as equality is based on being
// the same array, not having the same content.
- String skey = new String(key);
+// String skey = new String(key);
+ // OPTIMIZE what is this code for?
+ if (aMap.remove(key)!=null) {
+ return true;
+ }
char[] victim = null;
for (Iterator iter = aMap.keySet().iterator(); iter.hasNext();) {
char[] thisKey = (char[]) iter.next();
- if (skey.equals(new String(thisKey))) {
+ if (CharOperation.equals(thisKey,key)) {
+// if (skey.equals(new String(thisKey))) {
victim = thisKey;
break;
}
}
if (victim != null) {
aMap.remove(victim);
+ return true;
}
+ return false;
}
private void recordProgress(String message) {
* ******************************************************************/
package org.aspectj.ajdt.internal.compiler.lookup;
+import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.IntConstant;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.aspectj.weaver.ArrayAnnotationValue;
import org.aspectj.weaver.EnumAnnotationValue;
import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.SimpleAnnotationValue;
import org.aspectj.weaver.World;
// not yet used...
}
} else {
if (constant != null && constant != Constant.NotAConstant) {
+ if (constant instanceof IntConstant || constant instanceof BooleanConstant) {
+ AnnotationValue av = generateElementValueForConstantExpression(defaultValue, defaultValueBinding);
+ return av;
+ }
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["+defaultValue+"]");
// generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
}
}
+ private static AnnotationValue generateElementValueForConstantExpression(Expression defaultValue, TypeBinding defaultValueBinding) {
+ if (defaultValueBinding != null) {
+ Constant c = defaultValue.constant;
+ if (c instanceof IntConstant) {
+ IntConstant iConstant = (IntConstant)c;
+ return new SimpleAnnotationValue(ElementValueGen.PRIMITIVE_INT,new Integer(iConstant.intValue()));
+ } else if (c instanceof BooleanConstant) {
+ BooleanConstant iConstant = (BooleanConstant)c;
+ return new SimpleAnnotationValue(ElementValueGen.PRIMITIVE_BOOLEAN,new Boolean(iConstant.booleanValue()));
+ }
+ }
+ return null;
+ }
+
private static AnnotationValue generateElementValueForNonConstantExpression(Expression defaultValue, TypeBinding defaultValueBinding) {
if (defaultValueBinding != null) {
if (defaultValueBinding.isEnum()) {
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticFieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.IHasPosition;
import org.aspectj.weaver.Member;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewFieldTypeMunger;
import org.aspectj.weaver.NewMethodTypeMunger;
import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.UnresolvedType.TypeKind;
+
/**
* @author Jim Hugunin
}
public ResolvedMember makeResolvedMember(MethodBinding binding, Shadow.Kind shadowKind) {
- Member.Kind memberKind = binding.isConstructor() ? Member.CONSTRUCTOR : Member.METHOD;
+ MemberKind memberKind = binding.isConstructor() ? Member.CONSTRUCTOR : Member.METHOD;
if (shadowKind == Shadow.AdviceExecution) memberKind = Member.ADVICE;
return makeResolvedMember(binding,binding.declaringClass,memberKind);
}
binding.isConstructor() ? Member.CONSTRUCTOR : Member.METHOD);
}
- public ResolvedMember makeResolvedMember(MethodBinding binding, TypeBinding declaringType, Member.Kind memberKind) {
+ public ResolvedMember makeResolvedMember(MethodBinding binding, TypeBinding declaringType, MemberKind memberKind) {
//System.err.println("member for: " + binding + ", " + new String(binding.declaringClass.sourceName));
// Convert the type variables and store them
fromBinding(binding.returnType),
new String(binding.selector),
fromBindings(binding.parameters),
- fromBindings(binding.thrownExceptions)
+ fromBindings(binding.thrownExceptions),this
);
if (binding.isVarargs()) {
ret.setVarargsMethod();
TypeBinding ret = null;
// looking up type variables can get us into trouble
- if (!typeX.isTypeVariableReference()) {
+ if (!typeX.isTypeVariableReference() && !isParameterizedWithTypeVariables(typeX)) {
if (typeX.isRawType()) {
ret = (TypeBinding)rawTypeXToBinding.get(typeX);
} else {
}
return ret;
}
+
+ // return true if this is type variables are in the type arguments
+ private boolean isParameterizedWithTypeVariables(UnresolvedType typeX) {
+ if (!typeX.isParameterizedType()) return false;
+ UnresolvedType[] typeArguments = typeX.getTypeParameters();
+ if (typeArguments!=null) {
+ for (int i = 0; i < typeArguments.length; i++) {
+ if (typeArguments[i].isTypeVariableReference()) return true;
+ }
+ }
+ return false;
+ }
+
// When converting a parameterized type from our world to the eclipse world, these get set so that
// resolution of the type parameters may known in what context it is occurring (pr114744)
private ReferenceBinding baseTypeForParameterizedType;
private TypeBinding makeTypeBinding1(UnresolvedType typeX) {
if (typeX.isPrimitiveType()) {
- if (typeX == ResolvedType.BOOLEAN) return BaseTypes.BooleanBinding;
- if (typeX == ResolvedType.BYTE) return BaseTypes.ByteBinding;
- if (typeX == ResolvedType.CHAR) return BaseTypes.CharBinding;
- if (typeX == ResolvedType.DOUBLE) return BaseTypes.DoubleBinding;
- if (typeX == ResolvedType.FLOAT) return BaseTypes.FloatBinding;
- if (typeX == ResolvedType.INT) return BaseTypes.IntBinding;
- if (typeX == ResolvedType.LONG) return BaseTypes.LongBinding;
- if (typeX == ResolvedType.SHORT) return BaseTypes.ShortBinding;
- if (typeX == ResolvedType.VOID) return BaseTypes.VoidBinding;
+ if (typeX == ResolvedType.BOOLEAN) return TypeBinding.BOOLEAN;
+ if (typeX == ResolvedType.BYTE) return TypeBinding.BYTE;
+ if (typeX == ResolvedType.CHAR) return TypeBinding.CHAR;
+ if (typeX == ResolvedType.DOUBLE) return TypeBinding.DOUBLE;
+ if (typeX == ResolvedType.FLOAT) return TypeBinding.FLOAT;
+ if (typeX == ResolvedType.INT) return TypeBinding.INT;
+ if (typeX == ResolvedType.LONG) return TypeBinding.LONG;
+ if (typeX == ResolvedType.SHORT) return TypeBinding.SHORT;
+ if (typeX == ResolvedType.VOID) return TypeBinding.VOID;
throw new RuntimeException("weird primitive type " + typeX);
} else if (typeX.isArray()) {
int dim = 0;
return internalMakeFieldBinding(member,null);
}
+ // OPTIMIZE tidy this up, must be able to optimize for the synthetic case, if we passed in the binding for the declaring type, that would make things easier
+ /**
+ * Build a new Eclipse SyntheticFieldBinding for an AspectJ ResolvedMember.
+ */
+ public SyntheticFieldBinding createSyntheticFieldBinding(SourceTypeBinding owningType,ResolvedMember member) {
+ SyntheticFieldBinding sfb = new SyntheticFieldBinding(member.getName().toCharArray(),
+ makeTypeBinding(member.getReturnType()),
+ member.getModifiers() | Flags.AccSynthetic,
+ owningType,
+ Constant.NotAConstant,
+ -1); // index filled in later
+ owningType.addSyntheticField(sfb);
+ return sfb;
+ }
+
/**
* Take a normal AJ member and convert it into an eclipse fieldBinding.
* Taking into account any aliases that it may include due to being
}
currentType = declaringType;
- FieldBinding fb = new FieldBinding(member.getName().toCharArray(),
+
+ FieldBinding fb = null;
+ if (member.getName().startsWith(NameMangler.PREFIX)) {
+ fb = new SyntheticFieldBinding(member.getName().toCharArray(),
+ makeTypeBinding(member.getReturnType()),
+ member.getModifiers() | Flags.AccSynthetic,
+ currentType,
+ Constant.NotAConstant,-1); // index filled in later
+ } else {
+ fb = new FieldBinding(member.getName().toCharArray(),
makeTypeBinding(member.getReturnType()),
member.getModifiers(),
currentType,
Constant.NotAConstant);
+ }
typeVariableToTypeBinding.clear();
currentType = null;
if (member.getTypeVariables()!=null) {
if (member.getTypeVariables().length==0) {
- tvbs = MethodBinding.NoTypeVariables;
+ tvbs = Binding.NO_TYPE_VARIABLES;
} else {
tvbs = makeTypeVariableBindingsFromAJTypeVariables(member.getTypeVariables());
// QQQ do we need to bother fixing up the declaring element here?
if (aliases!=null && aliases.size()!=0) {
int i=0;
ReferenceBinding aliasTarget = (ReferenceBinding)makeTypeBinding(aliasTargetType);
+ if (aliasTarget.isRawType()) {
+ aliasTarget = ((RawTypeBinding) aliasTarget).genericType();
+ }
for (Iterator iter = aliases.iterator(); iter.hasNext();) {
String element = (String) iter.next();
typeVariableToTypeBinding.put(element,aliasTarget.typeVariables()[i++]);
// } else {
// declaringElement = makeTypeBinding((UnresolvedType)tVar.getDeclaringElement());
// }
- tvBinding = new TypeVariableBinding(tv.getName().toCharArray(),declaringElement,tv.getRank());
+
+ tvBinding = new TypeVariableBinding(tv.getName().toCharArray(),null,tv.getRank());
+
typeVariableToTypeBinding.put(tv.getName(),tvBinding);
tvBinding.superclass=(ReferenceBinding)makeTypeBinding(tv.getUpperBound());
tvBinding.firstBound=(ReferenceBinding)makeTypeBinding(tv.getFirstBound());
if (tv.getAdditionalInterfaceBounds()==null) {
- tvBinding.superInterfaces=TypeVariableBinding.NoSuperInterfaces;
+ tvBinding.superInterfaces=TypeVariableBinding.NO_SUPERINTERFACES;
} else {
TypeBinding tbs[] = makeTypeBindings(tv.getAdditionalInterfaceBounds());
ReferenceBinding[] rbs= new ReferenceBinding[tbs.length];
tvBinding.superclass=(ReferenceBinding)makeTypeBinding(tv.getUpperBound());
tvBinding.firstBound=(ReferenceBinding)makeTypeBinding(tv.getFirstBound());
if (tv.getAdditionalInterfaceBounds()==null) {
- tvBinding.superInterfaces=TypeVariableBinding.NoSuperInterfaces;
+ tvBinding.superInterfaces=TypeVariableBinding.NO_SUPERINTERFACES;
} else {
TypeBinding tbs[] = makeTypeBindings(tv.getAdditionalInterfaceBounds());
ReferenceBinding[] rbs= new ReferenceBinding[tbs.length];
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.weaver.AnnotationX;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
* In some cases this means the weaver will want to ask questions of eclipse types and this
* subtype of ResolvedMemberImpl is here to answer some of those questions - it is backed by
* the real eclipse MethodBinding object and can translate from Eclipse -> Weaver information.
- */
+ */
public class EclipseResolvedMember extends ResolvedMemberImpl {
private static String[] NO_ARGS = new String[]{};
private String[] argumentNames;
private World w;
private ResolvedType[] cachedAnnotationTypes;
+ private EclipseFactory eclipseFactory;
- public EclipseResolvedMember(MethodBinding binding, Kind memberKind, ResolvedType realDeclaringType, int modifiers, UnresolvedType type, String string, UnresolvedType[] types, UnresolvedType[] types2) {
+ public EclipseResolvedMember(MethodBinding binding, MemberKind memberKind, ResolvedType realDeclaringType, int modifiers, UnresolvedType type, String string, UnresolvedType[] types, UnresolvedType[] types2, EclipseFactory eclipseFactory) {
super(memberKind,realDeclaringType,modifiers,type,string,types,types2);
this.realBinding = binding;
+ this.eclipseFactory = eclipseFactory;
this.w = realDeclaringType.getWorld();
}
- public EclipseResolvedMember(FieldBinding binding, Kind field, ResolvedType realDeclaringType, int modifiers, ResolvedType type, String string, UnresolvedType[] none) {
+ public EclipseResolvedMember(FieldBinding binding, MemberKind field, ResolvedType realDeclaringType, int modifiers, ResolvedType type, String string, UnresolvedType[] none) {
super(field,realDeclaringType,modifiers,type,string,none);
this.realBinding = binding;
this.w = realDeclaringType.getWorld();
throw new RuntimeException("not yet implemented - please raise an AJ bug");
// return super.getAnnotations();
}
+
+
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType) {
+ long abits = realBinding.getAnnotationTagBits(); // ensure resolved
+ Annotation[] annos = getEclipseAnnotations();
+ if (annos==null) return null;
+ for (int i = 0; i < annos.length; i++) {
+ Annotation anno = annos[i];
+ UnresolvedType ut = UnresolvedType.forSignature(new String(anno.resolvedType.signature()));
+ if (w.resolve(ut).equals(ofType)) {
+ // Found the one
+ return EclipseAnnotationConvertor.convertEclipseAnnotation(anno,w,eclipseFactory);
+ }
+ }
+ return null;
+ }
+
+ public String getAnnotationDefaultValue() {
+ if (realBinding instanceof MethodBinding) {
+ AbstractMethodDeclaration methodDecl = getTypeDeclaration().declarationOf((MethodBinding)realBinding);
+ if (methodDecl instanceof AnnotationMethodDeclaration) {
+ AnnotationMethodDeclaration annoMethodDecl = (AnnotationMethodDeclaration)methodDecl;
+ Expression e = annoMethodDecl.defaultValue;
+ if (e.resolvedType==null)
+ e.resolve(methodDecl.scope);
+ // TODO does not cope with many cases...
+ if (e instanceof QualifiedNameReference) {
+
+ QualifiedNameReference qnr = (QualifiedNameReference)e;
+ if (qnr.binding instanceof FieldBinding) {
+ FieldBinding fb = (FieldBinding)qnr.binding;
+ StringBuffer sb = new StringBuffer();
+ sb.append(fb.declaringClass.signature());
+ sb.append(fb.name);
+ return sb.toString();
+ }
+ }
+ }
+ }
+ return null;
+ }
public ResolvedType[] getAnnotationTypes() {
if (cachedAnnotationTypes == null) {
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.aspectj.org.eclipse.jdt.internal.core.builder.ReferenceCollection;
import org.aspectj.org.eclipse.jdt.internal.core.builder.StringSet;
import org.aspectj.util.FileUtil;
/**
- * Holds state needed for incremental compilation
+ * Maintains state needed for incremental compilation
+ *
+ * tests: two ajdt projects, aspect is changed in dependent, does dependee do a full build? (could just do it if on
+ * aspect path but lets just do it for all now)
+ *
*/
public class AjState {
- private AjBuildManager buildManager;
+
+ // SECRETAPI static so beware of multi-threading bugs...
+ public static IStateListener stateListener = null;
+
+ public static boolean FORCE_INCREMENTAL_DURING_TESTING = false;
+
+ // if set to true we will not do a full build if we see a type changed on our classpath
+ // but no type in this state instance references it
+ public static boolean IGNORE_NON_REFERENCED_TYPES = true;
+
+ private AjBuildManager buildManager;
private boolean couldBeSubsequentIncrementalBuild = false;
- // SECRETAPI static so beware of multi-threading bugs...
- public static IStateListener stateListener = null;
- public static boolean FORCE_INCREMENTAL_DURING_TESTING = false;
-
private IHierarchy structureModel;
private IRelationshipMap relmap;
+ /**
+ * When looking at changes on the classpath, this set accumulates files in our state instance that affected by those
+ * changes. Then if we can do an incremental build - these must be compiled.
+ */
+ private Set affectedFiles = new HashSet();
+
private long lastSuccessfulFullBuildTime = -1;
private Hashtable /* File, long */ structuralChangesSinceLastFullBuild = new Hashtable();
*/
private Map /*<String, char[]>*/ aspectsFromFileNames;
- private List/*File*/ compiledSourceFiles = new ArrayList();
+ private Set/* File */compiledSourceFiles = new HashSet();
private List/*String*/ resources = new ArrayList();
// these are references created on a particular compile run - when looping round in
// addAffectedSourceFiles(), if some have been created then we look at which source files
// touch upon those and get them recompiled.
- private ArrayList/*<String>*/ qualifiedStrings;
- private ArrayList/*<String>*/ simpleStrings;
+ private StringSet qualifiedStrings = new StringSet(3);
+
+ private StringSet simpleStrings = new StringSet(3);
private Set addedFiles;
private Set deletedFiles;
return false;
}
+ affectedFiles.clear();
+
// we can't do an incremental build if one of our paths
// has changed, or a jar on a path has been modified
if (pathChange(buildConfig,newBuildConfig)) {
return false;
}
- simpleStrings = new ArrayList();
- qualifiedStrings = new ArrayList();
+ if (simpleStrings.elementSize > 20)
+ simpleStrings = new StringSet(3);
+ else
+ simpleStrings.clear();
+ if (qualifiedStrings.elementSize > 20)
+ qualifiedStrings = new StringSet(3);
+ else
+ qualifiedStrings.clear();
Set oldFiles = new HashSet(buildConfig.getFiles());
Set newFiles = new HashSet(newBuildConfig.getFiles());
}
Collection getModifiedFiles(long lastBuildTime) {
- List ret = new ArrayList();
+ Set ret = new HashSet();
//not our job to account for new and deleted files
for (Iterator i = buildConfig.getFiles().iterator(); i.hasNext(); ) {
File file = (File)i.next();
ret.add(file);
}
}
+ ret.addAll(affectedFiles);
return ret;
}
return ret;
}
- private boolean classFileChangedInDirSinceLastBuild(File dir) {
- // Is another process building into that directory?
+
+ private static int CLASS_FILE_NO_CHANGES = 0;
+
+ private static int CLASS_FILE_CHANGED_THAT_NEEDS_INCREMENTAL_BUILD = 1;
+
+ private static int CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD = 2;
+
+ private static int MAX_AFFECTED_FILES_BEFORE_FULL_BUILD = 30;
+
+ /**
+ * Analyse .class files in the directory specified, if they have changed since the last successful build then see if
+ * we can determine which source files in our project depend on the change. If we can then we can still do an
+ * incremental build, if we can't then we have to do a full build.
+ *
+ */
+ private int classFileChangedInDirSinceLastBuildRequiringFullBuild(File dir) {
+ int defaultReply = (IGNORE_NON_REFERENCED_TYPES ? CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD : CLASS_FILE_CHANGED_THAT_NEEDS_INCREMENTAL_BUILD);
+ // Is another AspectJ project building into that directory?
AjState state = IncrementalStateManager.findStateManagingOutputLocation(dir);
+ if (listenerDefined()) {
+ if (state != null) {
+ getListener().recordDecision("Found state instance managing output location : " + dir);
+ } else {
+ getListener().recordDecision("Failed to find a state instance managing output location : " + dir);
+ }
+ }
File[] classFiles = FileUtil.listFiles(dir, new FileFilter() {
public boolean accept(File pathname) {
if ((modTime+1000)>=lastSuccessfulBuildTime) {
// so the class on disk has changed since our last successful build
+
// To work out if it is a real change we should ask any state
// object managing this output location whether the file has
// structurally changed or not
if (state!=null) {
- boolean realChange = state.hasStructuralChangedSince(classFiles[i],lastSuccessfulBuildTime);
- if (realChange) return true;
- } else {
- // FIXME asc you should ask Eclipse project state here...
- return true; // no state object to ask so it must have changed
- }
+ if (state.isAspect(classFiles[i])) {
+ return CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD;
+ }
+ if (state.hasStructuralChangedSince(classFiles[i], lastSuccessfulBuildTime)) {
+ if (listenerDefined())
+ getListener().recordDecision("Structural change detected in : " + classFiles[i]);
+
+ if (!IGNORE_NON_REFERENCED_TYPES || isTypeWeReferTo(classFiles[i])) {
+ if (affectedFiles.size() > MAX_AFFECTED_FILES_BEFORE_FULL_BUILD)
+ return CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD;
+ }
+ } else {
+ if (listenerDefined())
+ getListener().recordDecision("Change detected in " + classFiles[i] + " but it is not structural");
+ }
+ // Is the change in a type that any of our source files care about? and if it is, is it
+ // a structural change?
+ // if (!IGNORE_NON_REFERENCED_TYPES || isTypeWeReferTo(classFiles[i])) {
+ // if (affectedFiles.size() > MAX_AFFECTED_FILES_BEFORE_FULL_BUILD)
+ // return CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD;
+ // if (state.hasStructuralChangedSince(classFiles[i], lastSuccessfulBuildTime))
+ // return defaultReply;
+ // }
+ } else {
+ // No state object to ask, so it only matters if we know which type depends on this file
+ if (!IGNORE_NON_REFERENCED_TYPES) {
+ return CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD;
+ } else {
+ if (isTypeWeReferTo(classFiles[i])) {
+ if (affectedFiles.size() > MAX_AFFECTED_FILES_BEFORE_FULL_BUILD)
+ return CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD;
+ return CLASS_FILE_CHANGED_THAT_NEEDS_INCREMENTAL_BUILD;
+ } else {
+ return CLASS_FILE_NO_CHANGES;
+ }
+ }
+ }
}
}
- return false;
+ return CLASS_FILE_NO_CHANGES;
}
+ private boolean isAspect(File file) {
+ if (aspectsFromFileNames == null)
+ return false;
+ return aspectsFromFileNames.containsKey(file);
+ }
+
+ public static class SoftHashMap extends AbstractMap {
+
+ private Map map;
+
+ private ReferenceQueue rq = new ReferenceQueue();
+
+ public SoftHashMap(Map map) {
+ this.map = map;
+ }
+
+ public SoftHashMap() {
+ this(new HashMap());
+ }
+
+ public SoftHashMap(Map map, boolean b) {
+ this(map);
+ }
+
+ class SoftReferenceKnownKey extends SoftReference {
+
+ private final Object key;
+
+ SoftReferenceKnownKey(Object k, Object v) {
+ super(v, rq);
+ this.key = k;
+ }
+ }
+
+ private void processQueue() {
+ SoftReferenceKnownKey sv = null;
+ while ((sv = (SoftReferenceKnownKey) rq.poll()) != null) {
+ map.remove(sv.key);
+ }
+ }
+
+ public Object get(Object key) {
+ SoftReferenceKnownKey value = (SoftReferenceKnownKey) map.get(key);
+ if (value == null)
+ return null;
+ if (value.get() == null) {
+ // it got GC'd
+ map.remove(value.key);
+ return null;
+ } else {
+ return value.get();
+ }
+ }
+
+ public Object put(Object k, Object v) {
+ processQueue();
+ return map.put(k, new SoftReferenceKnownKey(k, v));
+ }
+
+ public Set entrySet() {
+ return map.entrySet();
+ }
+
+ public void clear() {
+ processQueue();
+ map.clear();
+ }
+
+ public int size() {
+ processQueue();
+ return map.size();
+ }
+
+ public Object remove(Object k) {
+ processQueue();
+ SoftReferenceKnownKey value = (SoftReferenceKnownKey) map.remove(k);
+ if (value == null)
+ return null;
+ if (value.get() != null) {
+ return value.get();
+ }
+ return null;
+ }
+ }
+
+ SoftHashMap/* <baseDir,SoftHashMap<theFile,className>> */fileToClassNameMap = new SoftHashMap();
+
/**
- * Determine if a file has changed since a given time, using the local information
- * recorded in the structural changes data structure.
- *
- * file is the file we are wondering about
- * lastSBT is the last build time for the state asking the question
- */
+ * If a class file has changed in a path on our classpath, it may not be for a type that any of our source files
+ * care about. This method checks if any of our source files have a dependency on the class in question and if not,
+ * we don't consider it an interesting change.
+ */
+ private boolean isTypeWeReferTo(File file) {
+ String fpath = file.getAbsolutePath();
+ int finalSeparator = fpath.lastIndexOf(File.separator);
+ String baseDir = fpath.substring(0, finalSeparator);
+ String theFile = fpath.substring(finalSeparator + 1);
+ SoftHashMap classNames = (SoftHashMap) fileToClassNameMap.get(baseDir);
+ if (classNames == null) {
+ classNames = new SoftHashMap();
+ fileToClassNameMap.put(baseDir, classNames);
+ }
+ char[] className = (char[]) classNames.get(theFile);
+ if (className == null) {
+// if (listenerDefined())
+// getListener().recordDecision("Cache miss, looking up classname for : " + fpath);
+
+ ClassFileReader cfr;
+ try {
+ cfr = ClassFileReader.read(file);
+ } catch (ClassFormatException e) {
+ return true;
+ } catch (IOException e) {
+ return true;
+ }
+ className = cfr.getName();
+ classNames.put(theFile, className);
+// } else {
+// if (listenerDefined())
+// getListener().recordDecision("Cache hit, looking up classname for : " + fpath);
+ }
+
+ char[][][] qualifiedNames = null;
+ char[][] simpleNames = null;
+ if (CharOperation.indexOf('/', className) != -1) {
+ qualifiedNames = new char[1][][];
+ qualifiedNames[0] = CharOperation.splitOn('/', className);
+ qualifiedNames = ReferenceCollection.internQualifiedNames(qualifiedNames);
+ } else {
+ simpleNames = new char[1][];
+ simpleNames[0] = className;
+ simpleNames = ReferenceCollection.internSimpleNames(simpleNames, true);
+ }
+
+ for (Iterator i = references.entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ ReferenceCollection refs = (ReferenceCollection) entry.getValue();
+ if (refs != null && refs.includes(qualifiedNames, simpleNames)) {
+ if (listenerDefined()) {
+ getListener().recordDecision(
+ toString() + ": type " + new String(className) + " is depended upon by '" + entry.getKey() + "'");
+ }
+ affectedFiles.add(entry.getKey());
+ if (affectedFiles.size() > MAX_AFFECTED_FILES_BEFORE_FULL_BUILD)
+ return true;
+ // return true;
+ }
+ }
+ if (affectedFiles.size() > 0)
+ return true;
+ if (listenerDefined())
+ getListener().recordDecision(
+ toString() + ": type " + new String(className) + " is not depended upon by this state");
+
+ return false;
+ }
+
+ /**
+ * For a given class file, determine which source file it came from. This will only succeed if the class file is
+ * from a source file within this project.
+ */
+ private File getSourceFileForClassFile(File classfile) {
+ Set sourceFiles = fullyQualifiedTypeNamesResultingFromCompilationUnit.keySet();
+ for (Iterator sourceFileIterator = sourceFiles.iterator(); sourceFileIterator.hasNext();) {
+ File sourceFile = (File) sourceFileIterator.next();
+ List/* ClassFile */ classesFromSourceFile = (List/* ClassFile */) fullyQualifiedTypeNamesResultingFromCompilationUnit.get(sourceFile);
+ for (int i=0;i<classesFromSourceFile.size();i++) {
+ if (((ClassFile)classesFromSourceFile.get(i)).locationOnDisk.equals(classfile)) return sourceFile;
+ }
+ }
+ return null;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ // null config means failed build i think as it is only set on successful full build?
+ sb.append("AjState(").append((buildConfig == null ? "NULLCONFIG" : buildConfig.getConfigFile().toString())).append(")");
+ return sb.toString();
+ }
+
+ /**
+ * Determine if a file has changed since a given time, using the local information recorded in the structural
+ * changes data structure.
+ *
+ * file is the file we are wondering about lastSBT is the last build time for the state asking the question
+ */
private boolean hasStructuralChangedSince(File file,long lastSuccessfulBuildTime) {
//long lastModTime = file.lastModified();
Long l = (Long)structuralChangesSinceLastFullBuild.get(file.getAbsolutePath());
List oldClasspath = oldConfig.getClasspath();
List newClasspath = newConfig.getClasspath();
if (stateListener!=null) stateListener.aboutToCompareClasspaths(oldClasspath,newClasspath);
- if (changed(oldClasspath,newClasspath,true,oldOutputLocs)) return true;
+ if (changedAndNeedsFullBuild(oldClasspath,newClasspath,true,oldOutputLocs)) return true;
List oldAspectpath = oldConfig.getAspectpath();
List newAspectpath = newConfig.getAspectpath();
- if (changed(oldAspectpath,newAspectpath,true,oldOutputLocs)) return true;
+ if (changedAndNeedsFullBuild(oldAspectpath,newAspectpath,true,oldOutputLocs)) return true;
List oldInJars = oldConfig.getInJars();
List newInJars = newConfig.getInJars();
- if (changed(oldInJars,newInJars,false,oldOutputLocs)) return true;
+ if (changedAndNeedsFullBuild(oldInJars,newInJars,false,oldOutputLocs)) return true;
List oldInPath = oldConfig.getInpath();
List newInPath = newConfig.getInpath();
- if (changed(oldInPath, newInPath,false,oldOutputLocs)) return true;
+ if (changedAndNeedsFullBuild(oldInPath, newInPath,false,oldOutputLocs)) return true;
return changed;
}
return outputLocs;
}
- private boolean changed(List oldPath, List newPath, boolean checkClassFiles, List outputLocs) {
+ private boolean changedAndNeedsFullBuild(List oldPath, List newPath, boolean checkClassFiles, List outputLocs) {
if (oldPath == null) oldPath = new ArrayList();
if (newPath == null) newPath = new ArrayList();
if (oldPath.size() != newPath.size()) {
return true;
}
+ Set analysedPaths = new HashSet();
for (int i = 0; i < oldPath.size(); i++) {
if (!oldPath.get(i).equals(newPath.get(i))) {
return true;
}
}
if (!foundMatch) {
- boolean b= classFileChangedInDirSinceLastBuild(f);
- if (b && stateListener!=null) stateListener.detectedClassChangeInThisDir(f);
- if (b) return true;
+ if (!analysedPaths.contains(f.getAbsolutePath())) { // Do not check paths more than once
+ analysedPaths.add(f.getAbsolutePath());
+ int classFileChanges = classFileChangedInDirSinceLastBuildRequiringFullBuild(f);
+ if (classFileChanges == CLASS_FILE_CHANGED_THAT_NEEDS_FULL_BUILD)
+ return true;
+ // if (b && stateListener!=null) stateListener.detectedClassChangeInThisDir(f);
+ }
}
}
}
return false;
}
- public List getFilesToCompile(boolean firstPass) {
- List thisTime = new ArrayList();
+ public Set getFilesToCompile(boolean firstPass) {
+ Set thisTime = new HashSet();
if (firstPass) {
- compiledSourceFiles = new ArrayList();
+ compiledSourceFiles = new HashSet();
Collection modifiedFiles = getModifiedFiles();
//System.out.println("modified: " + modifiedFiles);
thisTime.addAll(modifiedFiles);
// }
if(addedFiles != null) {
- thisTime.addAll(addedFiles);
- }
+ for (Iterator fIter = addedFiles.iterator(); fIter.hasNext();) {
+ Object o = (Object) fIter.next();
+ if (!thisTime.contains(o))
+ thisTime.add(o);
+ }
+ // thisTime.addAll(addedFiles);
+ }
deleteClassFiles();
deleteResources();
addAffectedSourceFiles(thisTime,thisTime);
} else {
-
addAffectedSourceFiles(thisTime,compiledSourceFiles);
}
compiledSourceFiles = thisTime;
if (ucf == null) continue;
List ucfs = new ArrayList();
ucfs.add(ucf);
- addDependentsOf(ucf.getClassName());
+ recordTypeChanged(ucf.getClassName());
binarySourceFiles.put(bsf.binSrc.getPath(),ucfs);
List cfs = new ArrayList(1);
cfs.add(getClassFileFor(ucf));
for (Iterator i = buildConfig.getInpath().iterator(); i.hasNext(); ) {
File inPathElement = (File)i.next();
if (inPathElement.isDirectory() && AjBuildManager.COPY_INPATH_DIR_RESOURCES) {
- deleteResourcesFromDirectory(inPathElement,oldResources);
+ deleteResourcesFromDirectory(inPathElement,oldResources);
}
}
for (int i = 0; i < files.length; i++) {
// ASSERT: files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath()
// or we are in trouble...
- String filename = files[i].getAbsolutePath().substring(
+ String filename=null;
+ try {
+ filename = files[i].getCanonicalPath().substring(
+ dir.getCanonicalPath().length()+1);
+ } catch (IOException e) {
+ // we are in trouble if this happens...
+ IMessage msg = new Message("call to getCanonicalPath() failed for file " + files[i]+" with: "+e.getMessage(),
+ new SourceLocation(files[i],0),false);
+ buildManager.handler.handleMessage(msg);
+ filename = files[i].getAbsolutePath().substring(
dir.getAbsolutePath().length()+1);
+ }
+
maybeDeleteResource(filename, oldResources);
}
}
recordFQNsResultingFromCompilationUnit(sourceFile,result);
}
- /**
- * Currently unused, if we ditch classesFromName, we might need this.... (in noteResult)
- * @param file
- * @return
- */
- private UnwovenClassFile maybeGetExistingClassFileFor(UnwovenClassFile classFile) {
- File existing = new File(classFile.getFilename());
- if (!existing.exists()) {
- return null;
- }
- else {
- try {
- return new UnwovenClassFile(classFile.getFilename(),FileUtil.readAsByteArray(existing));
- }
- catch (IOException ex) {
- throw new IllegalStateException("Unable to read contents of '" + classFile.getFilename() + "' " +
- "from last compile cycle");
- }
- }
- }
-
/**
* @param sourceFile
* @param unwovenClassFiles
}
if (lastTime == null) {
- addDependentsOf(thisTime.getClassName());
+ recordTypeChanged(thisTime.getClassName());
return;
}
if (world.forDEBUG_structuralChangesCode)
System.err.println("Detected a structural change in "+thisTime.getFilename());
structuralChangesSinceLastFullBuild.put(thisTime.getFilename(),new Long(currentBuildTime));
- addDependentsOf(new String(reader.getName()).replace('/','.'));
+ recordTypeChanged(new String(reader.getName()).replace('/','.'));
}
}
} catch (ClassFormatException e) {
- addDependentsOf(thisTime.getClassName());
+ recordTypeChanged(thisTime.getClassName());
}
}
private boolean modifiersEqual(int eclipseModifiers, int resolvedTypeModifiers) {
- resolvedTypeModifiers = resolvedTypeModifiers & CompilerModifiers.AccJustFlag;
- eclipseModifiers = eclipseModifiers & CompilerModifiers.AccJustFlag;
+ resolvedTypeModifiers = resolvedTypeModifiers & ExtraCompilerModifiers.AccJustFlag;
+ eclipseModifiers = eclipseModifiers & ExtraCompilerModifiers.AccJustFlag;
// if ((eclipseModifiers & CompilerModifiers.AccSuper) != 0) {
// eclipseModifiers -= CompilerModifiers.AccSuper;
// }
}
- private String stringifyList(List l) {
+ private String stringifyList(Set l) {
StringBuffer sb = new StringBuffer();
sb.append("{");
for (Iterator iter = l.iterator(); iter.hasNext();) {
return sb.toString();
}
- protected void addAffectedSourceFiles(List addTo, List lastTimeSources) {
- if (qualifiedStrings == null || simpleStrings == null ||
- (qualifiedStrings.isEmpty() && simpleStrings.isEmpty())) return;
- if (listenerDefined()) getListener().recordDecision("Examining whether any other files now need compilation based just compiling: '"+stringifyList(lastTimeSources)+"'");
+ protected void addAffectedSourceFiles(Set addTo, Set lastTimeSources) {
+ if (qualifiedStrings.elementSize == 0 && simpleStrings.elementSize == 0)
+ return;
+ if (listenerDefined())
+ getListener().recordDecision(
+ "Examining whether any other files now need compilation based on just compiling: '" + stringifyList(lastTimeSources) + "'");
// the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X'
- char[][][] qualifiedNames = ReferenceCollection.internQualifiedNames(makeStringSet(qualifiedStrings));
+ char[][][] qualifiedNames = ReferenceCollection.internQualifiedNames(qualifiedStrings);
// if a well known qualified name was found then we can skip over these
- if (qualifiedNames.length < qualifiedStrings.size())
+ if (qualifiedNames.length < qualifiedStrings.elementSize)
qualifiedNames = null;
- char[][] simpleNames = ReferenceCollection.internSimpleNames(makeStringSet(simpleStrings));
+ char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings);
// if a well known name was found then we can skip over these
- if (simpleNames.length < simpleStrings.size())
+ if (simpleNames.length < simpleStrings.elementSize)
simpleNames = null;
//System.err.println("simple: " + simpleStrings);
// add in the things we compiled previously - I know that seems crap but otherwise we may pull woven
// stuff off disk (since we no longer have UnwovenClassFile objects) in order to satisfy references
// in the new files we are about to compile (see pr133532)
- // XXX Promote addTo to a Set - then we don't need this rubbish? but does it need to be ordered?
- if (addTo.size()>0) {
- for (Iterator iter = lastTimeSources.iterator(); iter.hasNext();) {
- Object element = (Object) iter.next();
- if (!addTo.contains(element)) addTo.add(element);
- }
- }
-
- qualifiedStrings.clear();
+ if (addTo.size() > 0)
+ addTo.addAll(lastTimeSources);
+ // // XXX Promote addTo to a Set - then we don't need this rubbish? but does it need to be ordered?
+ // if (addTo.size()>0) {
+ // for (Iterator iter = lastTimeSources.iterator(); iter.hasNext();) {
+ // Object element = (Object) iter.next();
+ // if (!addTo.contains(element)) addTo.add(element);
+ // }
+ // }
+
+ qualifiedStrings.clear();
simpleStrings.clear();
}
- protected void addDependentsOf(String qualifiedTypeName) {
- int lastDot = qualifiedTypeName.lastIndexOf('.');
+ /**
+ * Record that a particular type has been touched during a compilation run. Information is used to ensure any types
+ * depending upon this one are also recompiled.
+ *
+ * @param typename (possibly qualified) type name
+ */
+ protected void recordTypeChanged(String typename) {
+ int lastDot = typename.lastIndexOf('.');
String typeName;
if (lastDot != -1) {
- String packageName = qualifiedTypeName.substring(0,lastDot).replace('.', '/');
- if (!qualifiedStrings.contains(packageName)) { //??? O(n**2)
- qualifiedStrings.add(packageName);
- }
- typeName = qualifiedTypeName.substring(lastDot+1);
+ String packageName = typename.substring(0, lastDot).replace('.', '/');
+ qualifiedStrings.add(packageName);
+ typeName = typename.substring(lastDot+1);
} else {
qualifiedStrings.add("");
- typeName = qualifiedTypeName;
+ typeName = typename;
}
int memberIndex = typeName.indexOf('$');
if (memberIndex > 0)
typeName = typeName.substring(0, memberIndex);
- if (!simpleStrings.contains(typeName)) { //??? O(n**2)
- simpleStrings.add(typeName);
- }
- //System.err.println("adding: " + qualifiedTypeName);
+ simpleStrings.add(typeName);
}
protected void addDependentsOf(File sourceFile) {
if (cfs != null) {
for (Iterator iter = cfs.iterator(); iter.hasNext();) {
ClassFile cf = (ClassFile) iter.next();
- addDependentsOf(cf.fullyQualifiedTypeName);
+ recordTypeChanged(cf.fullyQualifiedTypeName);
}
}
import java.io.File;
import java.io.IOException;
-import java.util.*;
-
-import org.aspectj.ajdt.internal.compiler.ast.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
-import org.aspectj.asm.*;
+import org.aspectj.asm.AsmManager;
+import org.aspectj.asm.IHierarchy;
+import org.aspectj.asm.IProgramElement;
+import org.aspectj.asm.IRelationship;
+import org.aspectj.asm.internal.CharOperation;
import org.aspectj.asm.internal.ProgramElement;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.*;
-import org.aspectj.org.eclipse.jdt.internal.compiler.env.IGenericType;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
-import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.util.Util;
import org.aspectj.util.LangUtil;
-import org.aspectj.weaver.*;
-import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.AndPointcut;
+import org.aspectj.weaver.patterns.OrPointcut;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.ReferencePointcut;
/**
* At each iteration of <CODE>processCompilationUnit</CODE> the declarations for a
String name = new String(typeDeclaration.name);
IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
if (typeDeclaration instanceof AspectDeclaration) kind = IProgramElement.Kind.ASPECT;
- else if (typeDeclaration.kind() == IGenericType.INTERFACE_DECL) kind = IProgramElement.Kind.INTERFACE;
- else if (typeDeclaration.kind() == IGenericType.ENUM_DECL) kind = IProgramElement.Kind.ENUM;
- else if (typeDeclaration.kind() == IGenericType.ANNOTATION_TYPE_DECL) kind = IProgramElement.Kind.ANNOTATION;
+ else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.INTERFACE_DECL) kind = IProgramElement.Kind.INTERFACE;
+ else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) kind = IProgramElement.Kind.ENUM;
+ else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) kind = IProgramElement.Kind.ANNOTATION;
//@AJ support
if (typeDeclaration.annotations != null) {
String name = new String(memberTypeDeclaration.name);
IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
+ int typeDeclarationKind = TypeDeclaration.kind(memberTypeDeclaration.modifiers);
if (memberTypeDeclaration instanceof AspectDeclaration) kind = IProgramElement.Kind.ASPECT;
- else if (memberTypeDeclaration.kind() == IGenericType.INTERFACE_DECL) kind = IProgramElement.Kind.INTERFACE;
- else if (memberTypeDeclaration.kind() == IGenericType.ENUM_DECL) kind = IProgramElement.Kind.ENUM;
- else if (memberTypeDeclaration.kind() == IGenericType.ANNOTATION_TYPE_DECL) kind = IProgramElement.Kind.ANNOTATION;
+ else if (typeDeclarationKind == TypeDeclaration.INTERFACE_DECL) kind = IProgramElement.Kind.INTERFACE;
+ else if (typeDeclarationKind == TypeDeclaration.ENUM_DECL) kind = IProgramElement.Kind.ENUM;
+ else if (typeDeclarationKind == TypeDeclaration.ANNOTATION_TYPE_DECL) kind = IProgramElement.Kind.ANNOTATION;
//@AJ support
if (memberTypeDeclaration.annotations != null) {
}
IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
- if (memberTypeDeclaration.kind() == IGenericType.INTERFACE_DECL) kind = IProgramElement.Kind.INTERFACE;
- else if (memberTypeDeclaration.kind() == IGenericType.ENUM_DECL) kind = IProgramElement.Kind.ENUM;
- else if (memberTypeDeclaration.kind() == IGenericType.ANNOTATION_TYPE_DECL) kind = IProgramElement.Kind.ANNOTATION;
+ if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.INTERFACE_DECL) kind = IProgramElement.Kind.INTERFACE;
+ else if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) kind = IProgramElement.Kind.ENUM;
+ else if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) kind = IProgramElement.Kind.ANNOTATION;
//@AJ support
if (memberTypeDeclaration.annotations != null) {
protected String generateJavadocComment(ASTNode astNode) {
if (buildConfig != null && !buildConfig.isGenerateJavadocsInModelMode()) return null;
- StringBuffer sb = new StringBuffer(); // !!! specify length?
- boolean completed = false;
+
+ // StringBuffer sb = new StringBuffer(); // !!! specify length?
+ // boolean completed = false;
int startIndex = -1;
if (astNode instanceof MethodDeclaration) {
startIndex = ((MethodDeclaration)astNode).declarationSourceStart;
if (startIndex == -1) {
return null;
- } else if (currCompilationResult.compilationUnit.getContents()[startIndex] == '/' // look for /**
- && currCompilationResult.compilationUnit.getContents()[startIndex+1] == '*'
- && currCompilationResult.compilationUnit.getContents()[startIndex+2] == '*') {
-
- for (int i = startIndex; i < astNode.sourceStart && !completed; i++) {
- char curr = currCompilationResult.compilationUnit.getContents()[i];
- if (curr == '/' && sb.length() > 2 && sb.charAt(sb.length()-1) == '*') completed = true; // found */
- sb.append(currCompilationResult.compilationUnit.getContents()[i]);
- }
- return sb.toString();
- } else {
- return null;
+ } else if (currCompilationResult.compilationUnit.getContents()[startIndex] == '/') {
+ char[] comment = CharOperation.subarray(currCompilationResult.compilationUnit.getContents(), startIndex, astNode.sourceStart);
+ while (comment.length > 2) {
+ int star = CharOperation.indexOf('*', comment);
+ if (star == -1)
+ return null;
+ // looking for '/**' and not '//' or '//*'
+ if (star != 0 && (comment[star - 1] == '/') && (comment[star + 1] == '*') && (star - 2 < 0 || comment[star - 2] != '/')) {
+ boolean completed = false;
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < comment.length && !completed; i++) {
+ char curr = comment[i];
+ if (curr == '/' && sb.length() > 2 && sb.charAt(sb.length() - 1) == '*') {
+ completed = true; // found */
+ }
+ sb.append(comment[i]);
+ }
+ return sb.toString();
+ }
+ comment = CharOperation.subarray(comment, star + 1, comment.length);
+ }
}
-
+ return null;
}
/**
// }
public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
- if (constructorDeclaration.isDefaultConstructor) {
- stack.push(null); // a little wierd but does the job
+ if ((constructorDeclaration.bits & ASTNode.IsDefaultConstructor)!=0) {
+ stack.push(null); // a little weird but does the job
return true;
}
StringBuffer argumentsSignature = new StringBuffer();
// if ( n instanceof AbstractVariableDeclaration ) return getStartLine( (AbstractVariableDeclaration)n);
// if ( n instanceof AbstractMethodDeclaration ) return getStartLine( (AbstractMethodDeclaration)n);
// if ( n instanceof TypeDeclaration ) return getStartLine( (TypeDeclaration)n);
- return ProblemHandler.searchLineNumber(lineseps,
+ return Util.getLineNumber(n.sourceStart,lineseps,0,lineseps.length-1);
+// return ProblemHandler.searchLineNumber(lineseps,
// currCompilationResult.lineSeparatorPositions,
- n.sourceStart);
+// n.sourceStart);
}
// AMC - overloaded set of methods to get start and end lines for
if ( n instanceof AbstractVariableDeclaration ) return getEndLine( (AbstractVariableDeclaration)n);
if ( n instanceof AbstractMethodDeclaration ) return getEndLine( (AbstractMethodDeclaration)n);
if ( n instanceof TypeDeclaration ) return getEndLine( (TypeDeclaration)n);
- return ProblemHandler.searchLineNumber(lineseps,
+ return Util.getLineNumber(n.sourceEnd,lineseps,0,lineseps.length-1);
+// return ProblemHandler.searchLineNumber(lineseps,
// currCompilationResult.lineSeparatorPositions,
- n.sourceEnd);
+// n.sourceEnd);
}
// AMC - overloaded set of methods to get start and end lines for
// various ASTNode types. They have no common ancestor in the
// hierarchy!!
private int getEndLine( AbstractVariableDeclaration avd ){
- return ProblemHandler.searchLineNumber(lineseps,
-// currCompilationResult.lineSeparatorPositions,
- avd.declarationSourceEnd);
+ return Util.getLineNumber(avd.declarationSourceEnd,lineseps,0,lineseps.length-1);
}
// AMC - overloaded set of methods to get start and end lines for
// various ASTNode types. They have no common ancestor in the
// hierarchy!!
private int getEndLine( AbstractMethodDeclaration amd) {
- return ProblemHandler.searchLineNumber(lineseps,
-// currCompilationResult.lineSeparatorPositions,
- amd.declarationSourceEnd);
+ return Util.getLineNumber(amd.declarationSourceEnd,lineseps,0,lineseps.length-1);
}
// AMC - overloaded set of methods to get start and end lines for
// various ASTNode types. They have no common ancestor in the
// hierarchy!!
private int getEndLine( TypeDeclaration td){
- return ProblemHandler.searchLineNumber(lineseps,
-// currCompilationResult.lineSeparatorPositions,
- td.declarationSourceEnd);
+ return Util.getLineNumber(td.declarationSourceEnd,lineseps,0,lineseps.length-1);
}
// Urk - default no check for AJDT, enabled here for Ant, command-line
AjBuildManager.enableRuntimeVersionCheck(this);
final boolean verbose = flagInArgs("-verbose", args);
+ final boolean timers = flagInArgs("-timers", args);
if (null == this.clientHolder) {
this.clientHolder = checkForCustomMessageHolder(args);
}
// try {Thread.sleep(5000); }catch(Exception e) {}
run(args, holder);
long etime = System.currentTimeMillis();
+ if (timers) {
+ System.out.println("Compiler took "+(etime-stime)+"ms");
+ }
holder.handleMessage(MessageUtil.info("Compiler took "+(etime-stime)+"ms"));
// uncomment next line to pause at end (keeps jconsole alive!)
// try { System.in.read(); } catch (Exception e) {}
--- /dev/null
+/* *******************************************************************
+ * 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 Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.ajdt;
+
+import java.io.*;
+
+/**
+ * Used for writing converting text written to an output stream into
+ * a string. Deprecated - use StringWriter:
+ * <pre>
+ * StringWriter sw = new StringWriter();
+ * PrintWriter pw = new PrintWriter(sw, true);
+ * ... write to pw
+ * String result = sw.getBuffer().toString();
+ * </pre>
+ * @deprecated use StringWriter to construct PrintWriter
+ * @author Mik Kersten
+ */
+public class StreamPrintWriter extends PrintWriter {
+ private String contents = "";
+
+ public StreamPrintWriter(Writer out) {
+ super(out);
+ }
+
+ public String getContents() {
+ return contents;
+ }
+
+ public void flushBuffer() {
+ contents = "";
+ super.flush();
+ }
+
+ public void print(char x) {
+ contents += x + "\n";
+ }
+
+ public void print(char[] x) {
+ contents += new String( x );
+ }
+
+ public void print(int x) {
+ contents += x;
+ }
+
+ public void print(String x) {
+ contents += x;
+ }
+
+ public void println(char x) {
+ contents += x + "\n";
+ }
+
+ public void println(char[] x) {
+ contents += new String( x ) + "\n";
+ }
+
+ public void println(int x) {
+ contents += x + "\n";
+ }
+
+ public void println(String x) {
+ contents += x + "\n";
+ }
+
+ public void write( byte[] x ) {
+ contents += new String( x );
+ }
+
+ public void write( byte[] x, int i1, int i2 ) {
+ StringWriter writer = new StringWriter();
+ String s = new String( x );
+ writer.write( s.toCharArray(), i1, i2 );
+ contents += writer.getBuffer().toString();
+ }
+
+ public void write( int c ) {
+ contents += c;
+ }
+
+ public void write( String s ) {
+ contents += s;
+ }
+
+ public void write( String s, int i1, int i2 ) {
+ contents += s;
+ }
+}
package org.aspectj.ajdt.ajc;
//import org.aspectj.ajdt.internal.core.builder.AjBuildConfig;
+import org.aspectj.ajdt.StreamPrintWriter;
import org.aspectj.bridge.*;
import org.aspectj.util.*;
import org.aspectj.org.eclipse.jdt.core.compiler.InvalidInputException;
text.indexOf("Usage") != -1);
}
- public void testVersionOutput() throws InvalidInputException {
+ public void q() throws InvalidInputException {
String[] args = new String[] { "-version" };
- PrintStream saveOut = System.err;
+ PrintStream saveOut = System.out;
+ PrintStream saveErr = System.err;
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
+ ByteArrayOutputStream byteArrayErr = new ByteArrayOutputStream();
PrintStream newOut = new PrintStream(byteArrayOut);
- System.setErr(newOut);
+ PrintStream newErr = new PrintStream(byteArrayErr);
+ System.setOut(newOut);
+ System.setErr(newErr);
try {
try {
counter);
} catch (AbortException ae) { }
} finally {
- System.setErr(saveOut);
+ System.setOut(saveOut);
+ System.setErr(saveErr);
}
String text = byteArrayOut.toString();
-
+ String text2 = byteArrayErr.toString();
assertTrue(
- "version output",
+ "version output does not include 'AspectJ Compiler', output was:\n'"+text+"'",
text.indexOf("AspectJ Compiler") != -1);
}
import junit.framework.TestCase;
+import org.aspectj.ajdt.StreamPrintWriter;
import org.aspectj.ajdt.ajc.*;
import org.aspectj.asm.AsmManager;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageHandler;
import org.aspectj.bridge.MessageWriter;
import org.aspectj.tools.ajc.Ajc;
-import org.aspectj.util.StreamPrintWriter;
-//import org.eclipse.core.runtime.CoreException;
public class AjBuildManagerTest extends TestCase {