JDK-4996963 : apt could accept class files and java files on the command line
  • Type: Enhancement
  • Component: tools
  • Sub-Component: apt
  • Affected Version: 5.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2004-02-19
  • Updated: 2017-05-16
  • Resolved: 2004-09-24
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u1 01Fixed 6Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Like javac, at the moment apt is restricted to being given *.java files on the command line.  However, it may be convenient to process *.class files directly.
 

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.5.0_01 mustang FIXED IN: 1.5.0_01 mustang INTEGRATED IN: 1.5.0_01 mustang
26-09-2004

SUGGESTED FIX src/share/classes/com/sun/tools/apt/main> -r1.16 Main.java < ------- Main.java ------- 41c41,42 < /** This class provides a commandline interface to the GJC compiler. --- > /** This class provides a commandline interface to the apt build-time > * tool. 43,46c44,47 < * <p><b>This is NOT part of any API suppored by Sun Microsystems. If < * you write code that depends on this, you do so at your own risk. < * This code and its internal interfaces are subject to change or < * deletion without notice.</b> --- > * <p><b>This is NOT part of any API supported by Sun Microsystems. > * If you write code that depends on this, you do so at your own > * risk. This code and its internal interfaces are subject to change > * or deletion without notice.</b> 449c450,457 < --- > > /* > * Option to treat both classes and source files as > * declarations that can be given on the command line and > * processed as the result of an apt round. > */ > new AptXOption("-XclassesAsDecls", "optXclassesAsDecls"), > 530,540c538,553 < String s; < boolean matches(String s) { < this.s = s; < return s.endsWith(".java"); < } < boolean process(String option) { < if (!filenames.contains(s)) < filenames.add(s); < return false; < } < }, --- > String s; > boolean matches(String s) { > this.s = s; > return s.endsWith(".java") || > (options.get("-XclassesAsDecls") != null); > } > boolean process(String option) { > if (s.endsWith(".java")) { > if (!sourceFileNames.contains(s)) > sourceFileNames.add(s); > } else if (options.get("-XclassesAsDecls") != null) { > classFileNames.add(s); > } > return false; > } > }, 561c574 < /** The list of files to process --- > /** The list of source files to process 563c576 < java.util.List<String> filenames = new java.util.LinkedList<String>(); --- > java.util.List<String> sourceFileNames = new java.util.LinkedList<String>(); 564a578,581 > /** The list of class files to process > */ > java.util.List<String> classFileNames = new java.util.LinkedList<String>(); > 643c660,661 < if (recognizedOptions[j].matches(flag)) break; --- > if (recognizedOptions[j].matches(flag)) > break; 696c714 < return filenames; --- > return sourceFileNames; 768a787 > boolean classesAsDecls = options.get("-XclassesAsDecls") != null; 895c914 < filenames.addAll(genSourceFileNames); --- > sourceFileNames.addAll(genSourceFileNames); 905a925 > classFileNames.addAll(genClassFileNames); 906a927 > 911c932,934 < out.println("filenames: " + filenames); --- > out.println("filenames: " + sourceFileNames); > if (classesAsDecls) > out.println("classnames: " + classFileNames); 920c943,945 < } while(genSourceFileNames.size() != 0 && bark.nerrors == 0); --- > } while(((genSourceFileNames.size() != 0 ) || > (classesAsDecls && genClassFileNames.size() != 0)) && > bark.nerrors == 0); 929c954 < * test would also fail for syntax errors caught be javac. --- > * test would also fail for syntax errors caught by javac. 1024,1025c1049,1054 < < List<Symbol.ClassSymbol> cs = comp.compile(List.make(filenames.toArray(new String[0])), --- > java.util.List<String> nameList = new java.util.LinkedList<String>(); > nameList.addAll(sourceFileNames); > if (options.get("-XclassesAsDecls") != null) > nameList.addAll(classFileNames); > > List<Symbol.ClassSymbol> cs = comp.compile(List.make(nameList.toArray(new String[0])), 1074c1103,1104 < filenames = new java.util.LinkedList<String>(); --- > sourceFileNames = new java.util.LinkedList<String>(); > classFileNames = new java.util.LinkedList<String>(); src/share/classes/com/sun/tools/apt/main>sccs sccsdiff -r1.10 -r1.11 JavaCompiler.java ------- JavaCompiler.java ------- 30,38c30,34 < /** This class could be the main entry point for GJC when GJC is used as a < * component in a larger software system. It provides operations to < * construct a new compiler, and to run a new compiler on a set of source < * files. < * < * <p><b>This is NOT part of any API suppored by Sun Microsystems. If < * you write code that depends on this, you do so at your own risk. < * This code and its internal interfaces are subject to change or < * deletion without notice.</b> --- > /** > * <p><b>This is NOT part of any API supported by Sun Microsystems. > * If you write code that depends on this, you do so at your own > * risk. This code and its internal interfaces are subject to change > * or deletion without notice.</b> 159c155 < reader = ClassReader.instance(context); --- > reader = AptClassReader.instance0(context); 198a195 > classesAsDecls= options.get("-XclassesAsDecls") != null; 259a257,260 > /** Are class files being treated as declarations > */ > public boolean classesAsDecls; > 426a428 > 431c433,447 < for (List<String> l = filenames; l.nonEmpty(); l = l.tail) --- > for (List<String> l = filenames; l.nonEmpty(); l = l.tail) { > if (classesAsDecls) { > if (! l.head.endsWith(".java") ) { // process as class file > ClassSymbol cs = reader.enterClass(names.fromString(l.head)); > try { > cs.complete(); > } catch(Symbol.CompletionFailure cf) { > bark.error(Position.NOPOS, "CantFindClass", l); > continue; > } > > classes.append(cs); // add to list of classes > continue; > } > } 432a449 > } 441c458,460 < apt.main(roots, origOptions, aptCL, --- > apt.main(roots, > classes, > origOptions, aptCL, 568a588,616 > > static class AptClassReader extends com.sun.tools.javac.jvm.ClassReader { > public static AptClassReader instance0(Context context) { > ClassReader instance = context.get(classReaderKey); > if (instance == null) > instance = new AptClassReader(context); > return (AptClassReader)instance; > } > > public static void preRegister(final Context context) { > context.put(classReaderKey, new Context.Factory<ClassReader>() { > public ClassReader make() { > return new AptClassReader(context); > } > }); > } > > private AptClassReader(Context context) { > super(context, true); > } > > protected FileEntry preferredFileEntry(FileEntry sourceEntry, > FileEntry classEntry) { > // apt always prefers source over class files so that > // annotations with source retention level are maximally > // available. > return sourceEntry; > } > } src/share/classes/com/sun/tools/apt/comp>sccs sccsdiff -r1.16 -r1.17 Apt.java ------- Apt.java ------- 9a10 > import com.sun.tools.javac.code.*; 44,47c45,48 < * <p><b>This is NOT part of any API suppored by Sun Microsystems. If < * you write code that depends on this, you do so at your own risk. < * This code and its internal interfaces are subject to change or < * deletion without notice.</b> --- > * <p><b>This is NOT part of any API supported by Sun Microsystems. > * If you write code that depends on this, you do so at your own > * risk. This code and its internal interfaces are subject to change > * or deletion without notice.</b> 116c117 < public AptTreeScanner(){ --- > public AptTreeScanner() { 120d120 < 164a165,190 > Set<String> computeAnnotationSet(Collection<ClassSymbol> classSymbols) { > Set<String> annotationSet = new HashSet<String>(); > > for(ClassSymbol classSymbol: classSymbols) { > computeAnnotationSet(classSymbol, annotationSet); > } > return annotationSet; > } > > void computeAnnotationSet(Symbol symbol, Set<String> annotationSet) { > if (symbol != null ) { > if (symbol.attributes() != null) > for(Attribute.Compound compound: symbol.attributes()) > annotationSet.add(compound.type.tsym.toString()); // should fullName be used instead of toString? > > if (symbol instanceof Symbol.MethodSymbol) // add parameter annotations > for(Symbol param: ((MethodSymbol) symbol).params()) > computeAnnotationSet(param, annotationSet); > > if (symbol.members() != null) { > for(Scope.Entry e: symbol.members().table) > computeAnnotationSet(e.sym, annotationSet); > } > } > } > 165a192 > ListBuffer<ClassSymbol> classes, 171a199 > Options options = Options.instance(context); 172a201,210 > Collection<TypeDeclaration> spectypedecls = new LinkedHashSet<TypeDeclaration>(); > Collection<TypeDeclaration> typedecls = new LinkedHashSet<TypeDeclaration>(); > Set<String> unmatchedAnnotations = new LinkedHashSet<String>(); > Set<AnnotationTypeDeclaration> emptyATDS = Collections.emptySet(); > Set<Class<? extends AnnotationProcessorFactory> > currentRoundFactories = > new LinkedHashSet<Class<? extends AnnotationProcessorFactory> >(); > > // Determine what annotations are present on the input source > // files, create collections of specified type declarations, > // and type declarations. 179,181d216 < < Collection<TypeDeclaration> spectypedecls = new LinkedHashSet<TypeDeclaration>(); < 187,191c222,226 < Set<AnnotationTypeDeclaration> emptyATDS = Collections.emptySet(); < Set<Class<? extends AnnotationProcessorFactory> > currentRoundFactories = < new LinkedHashSet<Class<? extends AnnotationProcessorFactory> >(); < Collection<TypeDeclaration> typedecls = new LinkedHashSet<TypeDeclaration>(); < Set<String> unmatchedAnnotations = (new LinkedHashSet<String>()); --- > for (ClassSymbol cs : ats.declCollection) { > TypeDeclaration decl = aptenv.declMaker.getTypeDeclaration(cs); > typedecls.add(decl); > } > 194c229,230 < for (ClassSymbol cs : ats.declCollection) { --- > // Process input class files > for(ClassSymbol cs : classes) { 195a232,233 > // System.out.println("Adding a class to spectypedecls"); > spectypedecls.add(decl); 196a235 > computeAnnotationSet(cs, unmatchedAnnotations); 199,200d237 < Options options = Options.instance(context); < 203c240 < (new TreeSet<String>(ats.getAnnotationSet())).toString()); --- > (new TreeSet<String>(unmatchedAnnotations)).toString()); 218c255 < if (treeList.size() == 0 ) --- > if (spectypedecls.size() == 0 ) 271c308 < if (treeList.size() == 0) --- > if (spectypedecls.size() == 0) 390c427 < if (treeList.size() == 0 && --- > if (spectypedecls.size() == 0 && src/share/classes/com/sun/tools/apt/comp>sccs sccsdiff -r1.8 -r1.9 PrintAP.java ------- PrintAP.java ------- 321,322c321 < printFormalTypeParameterSet(e.getFormalTypeParameters()); < System.out.print(" "); --- > printFormalTypeParameterSet(e.getFormalTypeParameters(), true); 326c325 < printFormalTypeParameterSet(d.getFormalTypeParameters()); --- > printFormalTypeParameterSet(d.getFormalTypeParameters(), false); 329c328 < private void printFormalTypeParameterSet(Collection<TypeParameterDeclaration> typeParams) { --- > private void printFormalTypeParameterSet(Collection<TypeParameterDeclaration> typeParams, boolean pad) { 340a340,342 > if (pad) > System.out.print(" "); > src/share/classes/com/sun/tools/apt/mirror/apt>sccs sccsdiff -r1.6 -r1.7 FilerImpl.java ------- FilerImpl.java ------- 31a32,65 > /* > * The Filer class must maintain a number of constraints. First, > * multiple attempts to open the same path within the same > * invocation of apt results in an IOException being thrown. For > * example, trying to open the same source file twice: > * > * createSourceFile("foo.Bar") > * ... > * createSourceFile("foo.Bar") > * > * is disallowed as is opening a text file that happens to have > * the same name as a source file: > * > * createSourceFile("foo.Bar") > * ... > * createTextFile(SOURCE_TREE, "foo", new File("Bar"), null) > * > * Additionally, creating a source file that corresponds to an > * already created class file (or vice versa) generates at least a > * warning. This is an error if -XclassesAsDecls is being used > * since you can't create the same type twice. However, if the > * Filer is used to create a text file named *.java that happens > * to correspond to an existing class file, a warning is *not* > * generated. Similarly, a warning is not generated for a binary > * file named *.class and an existing source file. > * > * The reason for this difference is that source files and class > * files are registered with apt and can get passed on as > * declarations to the next round of processing. Files that are > * just named *.java and *.class are not processed in that manner; > * although having extra source files and class files on the > * source path and class path can alter the behavior of the tool > * and any final compile. > */ 32a67,102 > private enum FileKind { > SOURCE { > void register(File file, String name, FilerImpl that) throws IOException { > // Check for corresponding class file > if (that.filesCreated.contains(new File(that.locations.get(CLASS_TREE), > that.nameToPath(name, ".class")))) { > > that.bark.warning(Position.NOPOS, "CorrespondingClassFile", name); > if (that.opts.get("-XclassesAsDecls") !
26-09-2004

SUGGESTED FIX = null) > throw new IOException(); > } > that.sourceFileNames.add(file.getPath()); > } > }, > > CLASS { > void register(File file, String name, FilerImpl that) throws IOException { > if (that.filesCreated.contains(new File(that.locations.get(SOURCE_TREE), > that.nameToPath(name, ".java")))) { > that.bark.warning(Position.NOPOS, "CorrespondingSourceFile", name); > if (that.opts.get("-XclassesAsDecls") != null) > throw new IOException(); > } > // Track the binary name instead of the filesystem location > that.classFileNames.add(name); > } > }, > > OTHER { > // Nothing special to do > void register(File file, String name, FilerImpl that) throws IOException {} > }; > > abstract void register(File file, String name, FilerImpl that) throws IOException; > } > 111a182 > String pathname = nameToPath(name, ".java"); 113,115c184,185 < nameToPath(name, ".java")); < PrintWriter pw = getPrintWriter(file, encoding); < sourceFileNames.add(file.getPath()); --- > pathname); > PrintWriter pw = getPrintWriter(file, encoding, name, FileKind.SOURCE); 124,125c194,196 < OutputStream os = getOutputStream(CLASS_TREE, pathname); < classFileNames.add(pathname); --- > File file = new File(locations.get(CLASS_TREE), > pathname); > OutputStream os = getOutputStream(file, name, FileKind.CLASS); 142c213 < return getPrintWriter(loc, file.getPath(), charsetName); --- > return getPrintWriter(loc, file.getPath(), charsetName, null, FileKind.OTHER); 154c225 < return getOutputStream(loc, file.getPath()); --- > return getOutputStream(loc, file.getPath(), null, FileKind.OTHER); 179c250 < String encoding) throws IOException { --- > String encoding, String name, FileKind kind) throws IOException { 181c252 < return getPrintWriter(file, encoding); --- > return getPrintWriter(file, encoding, name, kind); 188,189c259,260 < String encoding) throws IOException { < prepareFile(file); --- > String encoding, String name, FileKind kind) throws IOException { > prepareFile(file, name, kind); 203c274 < private OutputStream getOutputStream(Location loc, String pathname) --- > private OutputStream getOutputStream(Location loc, String pathname, String name, FileKind kind) 206c277,281 < prepareFile(file); --- > return getOutputStream(file, name, kind); > } > > private OutputStream getOutputStream(File file, String name, FileKind kind) throws IOException { > prepareFile(file, name, kind); 209a285 > 229c305 < private void prepareFile(File file) throws IOException { --- > private void prepareFile(File file, String name, FileKind kind) throws IOException { 234c310,311 < if (!filesCreated.add(file)) { --- > > if (filesCreated.contains(file)) { 237,239d313 < } < if (file.exists()) { < file.delete(); 241,243c315,324 < File parent = file.getParentFile(); < if (parent != null && !parent.exists()) { < parent.mkdirs(); --- > if (file.exists()) { > file.delete(); > } else { > File parent = file.getParentFile(); > if (parent != null && !parent.exists()) { > if(!parent.mkdirs()) { > bark.warning(Position.NOPOS, "BadParentDirectory", file.toString()); > throw new IOException(); > } > } 244a326,328 > > kind.register(file, name, this); > filesCreated.add(file); src/share/classes/com/sun/tools/javac/code>sccs sccsdiff -r1.75 -r1.76 Symbol.java ------- Symbol.java ------- 894c894 < name.table.fromString("arg" + i), --- > name.table.fromString("arg" + i++), src/share/classes/com/sun/tools/apt/resources>sccs sccsdiff -r1.6 -r1.7 apt.properties ------- apt.properties ------- 19a20,25 > apt.msg.bug=> An exception has occurred in apt ({0}). > Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) > after checking the Bug Parade for duplicates. > Include your program and the following diagnostic in your report. Thank you. > 55a62,63 > apt.opt.XClassesAsDecls=> Treat both class and source files as declarations to process 69a78,80 > apt.err.CantFindClass=> Could not find class file for {0} > 104a116,118 > apt.warn.BadParentDirectory=> Failed to create some parent directory of {0} > 134a149,154 > > apt.warn.CorrespondingClassFile=> A class file corresponding to source file ''{0}'' has already been created. > > apt.warn.CorrespondingSourceFile=> A source file corresponding to class file ''{0}'' has already been created. ###@###.### 2004-09-16
16-09-2004

EVALUATION Probably a useful feature; need to investigate impact on incorporating this into javac infrastructure. ###@###.### 2004-02-18 Requested by JAX* users; should be included in Tiger. ###@###.### 2004-04-25 Evaluating options to provide this functionality post Tiger Beta3. ###@###.### 2004-07-27
25-04-2004