]> source.dussan.org Git - aspectj.git/commitdiff
big refactoring
authoraclement <aclement>
Thu, 8 May 2008 23:54:32 +0000 (23:54 +0000)
committeraclement <aclement>
Thu, 8 May 2008 23:54:32 +0000 (23:54 +0000)
16 files changed:
org.aspectj.ajdt.core/.classpath
org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java [new file with mode: 0644]
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjPipeliningCompilerAdapter.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ClassFileBasedByteCodeProvider.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/InterimCompilationResult.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseAnnotationConvertor.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseResolvedMember.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java
org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java
org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/StreamPrintWriter.java [new file with mode: 0644]
org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/AjdtCommandTestCase.java
org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java

index 7699c178151fd4d7c9552d8489109ac87f3af415..b4daf86c187c88a4e2202062c8b7b8168a751d75 100644 (file)
@@ -2,18 +2,19 @@
 <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>
index 9db0feb3d4561c8c4d2016b3c609d178e42d9aad..4d8330af620e9de1272b1c4cda27c413dba41398 100644 (file)
@@ -33,7 +33,8 @@ public class BuildArgParser extends Main {
     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;
                }
@@ -49,12 +50,12 @@ public class BuildArgParser extends Main {
     }
 
     /** @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)});
     }
     
     /** 
@@ -230,11 +231,16 @@ public class BuildArgParser extends Main {
                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() {
@@ -653,15 +659,21 @@ public class BuildArgParser extends Main {
                        } 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");
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java
new file mode 100644 (file)
index 0000000..f113d25
--- /dev/null
@@ -0,0 +1,311 @@
+/* *******************************************************************
+ * 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();
+        }
+    }
+}
index f5c87e7d4bc9d5e1a903bed4dfe6b5c085040dd3..9ca8b00ff1feb59fda5e0cc4ec15dbc5e79dfb4b 100644 (file)
@@ -23,6 +23,7 @@ import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
 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;
@@ -33,10 +34,9 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
 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;
@@ -190,8 +190,8 @@ public class AjPipeliningCompilerAdapter extends AbstractCompilerAdapter {
                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) {
@@ -443,7 +443,7 @@ public class AjPipeliningCompilerAdapter extends AbstractCompilerAdapter {
        
        /** 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++) {
@@ -504,7 +504,6 @@ public class AjPipeliningCompilerAdapter extends AbstractCompilerAdapter {
                try {
                  weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
                } finally {
-                       CflowPointcut.clearCaches();
                        weaver.tidyUp();
                        IMessageHandler imh = weaver.getWorld().getMessageHandler();
                        if (imh instanceof WeaverMessageHandler)
@@ -516,7 +515,6 @@ public class AjPipeliningCompilerAdapter extends AbstractCompilerAdapter {
        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();
index 415a1456b37d8c1422d91d73ff52368fd6053884..19d2d1ad92fda09e9041eacda987d83d70d5aeb0 100644 (file)
  *******************************************************************************/
 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;
 
@@ -38,12 +41,24 @@ public class ClassFileBasedByteCodeProvider
        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;
        }
                
index 0319a240c5b0bd2c265bb789aee0b448834f9bc6..8111238c77a598211c78e3d0d7a080acf0dcb3d8 100644 (file)
@@ -40,7 +40,7 @@ public class InterimCompilationResult {
                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); 
                }               
index 34c70fda3be4054333f45af9e70d16d5a439b4a2..6d1e267d6d41438a5627ef14cbd1fce13c1553e4 100644 (file)
@@ -13,6 +13,8 @@ package org.aspectj.ajdt.internal.compiler;
 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;
@@ -139,7 +141,7 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera
                
                // 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() {
@@ -148,7 +150,7 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera
                // 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;
        }
        
@@ -170,6 +172,7 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera
                if ((lastReturnedResult != null) && (!lastReturnedResult.result().hasBeenAccepted)) {
                        finishedWith(lastReturnedResult);
                }
+               lastReturnedResult=null;
        }
        
 
@@ -178,27 +181,29 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera
         * @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...
@@ -208,21 +213,28 @@ public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Itera
                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) {
index 7bf79afe9ca0f06ddaeab8ed0cf0a310484802e4..dac05522c695ff2d721b0aeb7a80c420ef75ed34 100644 (file)
@@ -11,6 +11,7 @@
  * ******************************************************************/
 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;
@@ -19,7 +20,9 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
 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;
@@ -31,6 +34,7 @@ import org.aspectj.weaver.AnnotationX;
 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...
@@ -119,6 +123,10 @@ public class EclipseAnnotationConvertor {
                                }
                        } 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());
@@ -130,6 +138,20 @@ public class EclipseAnnotationConvertor {
                }
        }
        
+       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()) {
index 0d1bb1baf7b13958d346402209c88a753b794f88..f00b0b27712201b5c82a01a3c14dbe7ffbbfc8de 100644 (file)
@@ -38,7 +38,6 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Wildcard;
 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;
@@ -49,6 +48,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
 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;
@@ -56,6 +56,7 @@ import org.aspectj.weaver.BoundedReferenceType;
 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;
@@ -72,6 +73,7 @@ import org.aspectj.weaver.UnresolvedType;
 import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
 import org.aspectj.weaver.World;
 import org.aspectj.weaver.UnresolvedType.TypeKind;
+
  
 /**
  * @author Jim Hugunin
@@ -459,7 +461,7 @@ public class EclipseFactory {
        }
 
        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);
        }
@@ -502,7 +504,7 @@ public class EclipseFactory {
                                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
@@ -527,7 +529,7 @@ public class EclipseFactory {
                        fromBinding(binding.returnType),
                        new String(binding.selector),
                        fromBindings(binding.parameters),
-                       fromBindings(binding.thrownExceptions)
+                       fromBindings(binding.thrownExceptions),this
                        );
                if (binding.isVarargs()) {
                        ret.setVarargsMethod();
@@ -567,7 +569,7 @@ public class EclipseFactory {
                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 {
@@ -592,6 +594,19 @@ public class EclipseFactory {
                }
                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;
@@ -599,15 +614,15 @@ public class EclipseFactory {
        
        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;
@@ -708,6 +723,21 @@ public class EclipseFactory {
                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
@@ -731,11 +761,21 @@ public class EclipseFactory {
                }
                
                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;
                
@@ -793,7 +833,7 @@ public class EclipseFactory {
 
                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?
@@ -806,6 +846,9 @@ public class EclipseFactory {
                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++]);
@@ -879,12 +922,14 @@ public class EclipseFactory {
 //               } 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];
@@ -916,7 +961,7 @@ public class EclipseFactory {
                  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];
index 1e7a36e355dba25886536505cb8dc66fb3cf50ab..c0eaaf4a5f36a95915dde0991df7230e7194b0dc 100644 (file)
@@ -13,14 +13,18 @@ package org.aspectj.ajdt.internal.compiler.lookup;
 
 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;
@@ -31,7 +35,7 @@ import org.aspectj.weaver.World;
  * 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[]{};
@@ -40,14 +44,16 @@ public class EclipseResolvedMember extends ResolvedMemberImpl {
        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();
@@ -72,6 +78,47 @@ public class EclipseResolvedMember extends ResolvedMemberImpl {
                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) {
index 103a3b89957ae8424b7967003fa6b325079ee673..3522848d9f19426733d9d624e3adfda1fd89978d 100644 (file)
@@ -17,6 +17,9 @@ import java.io.File;
 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;
@@ -41,7 +44,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFormatExcepti
 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;
@@ -54,19 +57,35 @@ import org.aspectj.weaver.bcel.UnwovenClassFile;
 
 
 /**
- * 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();
        
@@ -165,14 +184,15 @@ public class AjState {
         */
        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;
@@ -227,6 +247,8 @@ public class AjState {
                        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)) {
@@ -242,8 +264,14 @@ public class AjState {
                    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());
@@ -303,7 +331,7 @@ public class AjState {
        }
 
        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();
@@ -316,6 +344,7 @@ public class AjState {
                                ret.add(file);
                        } 
                }
+               ret.addAll(affectedFiles);
                return ret;
        }
 
@@ -341,9 +370,32 @@ public class AjState {
                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) {
@@ -356,28 +408,239 @@ public class AjState {
                        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());
@@ -397,16 +660,16 @@ public class AjState {
                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;
        }
        
@@ -432,12 +695,13 @@ public class AjState {
                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;
@@ -462,19 +726,23 @@ public class AjState {
                                        }
                                }
                                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);
@@ -485,15 +753,19 @@ public class AjState {
        //              }
                        
                        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;
@@ -520,7 +792,7 @@ public class AjState {
                                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));
@@ -604,7 +876,7 @@ public class AjState {
                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);
                        }                       
                }       
                
@@ -657,8 +929,19 @@ public class AjState {
                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);
                }                               
        }
@@ -715,27 +998,6 @@ public class AjState {
                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
@@ -862,7 +1124,7 @@ public class AjState {
                }
                
                if (lastTime == null) {
-                       addDependentsOf(thisTime.getClassName());
+                       recordTypeChanged(thisTime.getClassName());
                        return;
                }
 
@@ -879,11 +1141,11 @@ public class AjState {
                                        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());
                }                                                       
        }
        
@@ -1062,8 +1324,8 @@ public class AjState {
 
 
        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;
 //             }
@@ -1080,7 +1342,7 @@ public class AjState {
        }
                
 
-    private String stringifyList(List l) {
+    private String stringifyList(Set l) {
          StringBuffer sb = new StringBuffer();
          sb.append("{");
          for (Iterator iter = l.iterator(); iter.hasNext();) {
@@ -1092,18 +1354,20 @@ public class AjState {
          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);
@@ -1127,40 +1391,43 @@ public class AjState {
                // 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) {
@@ -1169,7 +1436,7 @@ public class AjState {
                if (cfs != null) {
                        for (Iterator iter = cfs.iterator(); iter.hasNext();) {
                                ClassFile cf = (ClassFile) iter.next();
-                               addDependentsOf(cf.fullyQualifiedTypeName);
+                               recordTypeChanged(cf.fullyQualifiedTypeName);
                        }
                }
 
index 483f3ba03de800d464549a7068b5033f868fd1aa..4385e2a99cc9707355afeac6c2cf6b2967db4927 100644 (file)
@@ -17,24 +17,58 @@ package org.aspectj.ajdt.internal.core.builder;
 
 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 
@@ -211,9 +245,9 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                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) {
@@ -252,10 +286,11 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                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) {
@@ -305,9 +340,9 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                }
 
                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) {
@@ -633,8 +668,9 @@ public class AsmHierarchyBuilder extends ASTVisitor {
        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;
@@ -646,20 +682,29 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                
                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;
        }
        
        /**
@@ -728,8 +773,8 @@ public class AsmHierarchyBuilder extends ASTVisitor {
 //     }
 
        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();
@@ -865,9 +910,10 @@ public class AsmHierarchyBuilder extends ASTVisitor {
 //             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
@@ -877,9 +923,10 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                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
@@ -895,9 +942,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
        // 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
@@ -913,9 +958,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
        // 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
@@ -931,9 +974,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
        // 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);
        }
 
 
index 9f0c8b9a01929ac3000c4974403a5018235999e2..f2328311c3bfdd11dff1eadefc14d3acf71b613c 100644 (file)
@@ -230,6 +230,7 @@ public class Main {
         // 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);
         }
@@ -252,6 +253,9 @@ public class Main {
 //             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) {}
diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/StreamPrintWriter.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/StreamPrintWriter.java
new file mode 100644 (file)
index 0000000..4ead020
--- /dev/null
@@ -0,0 +1,101 @@
+/* *******************************************************************
+ * 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;
+    }
+}
index f24fb6a8233b034fabb53f169531ab5a973ede1c..fdc14146b9695951d19746afdbcd3a40975cd7fd 100644 (file)
@@ -14,6 +14,7 @@
 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;
@@ -184,13 +185,17 @@ public class AjdtCommandTestCase extends TestCase {
                        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 {
@@ -200,13 +205,14 @@ public class AjdtCommandTestCase extends TestCase {
                                        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);                
        }
        
index 8de9bb93bad512a11b064a5fbcd237c920299257..6cf279f49838c9b918ae17e130f4e7f1edd41988 100644 (file)
@@ -19,14 +19,13 @@ import java.io.PrintWriter;
 
 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 {