Main.java revision 9967de5fe4b0240e9b5169020aec35fb29cdfb83
110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipackage annotator; 210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 3f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.io.File; 4f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.io.FileNotFoundException; 5f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.io.FileOutputStream; 6f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.io.IOException; 7f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.io.OutputStream; 8f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.ArrayList; 904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport java.util.Collection; 10f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.Collections; 11adc47d693f66c43acddf4956515c0c94db3e6cb4Dan Brownimport java.util.Comparator; 1204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport java.util.HashMap; 13f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.LinkedHashSet; 14f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.List; 15e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brownimport java.util.Map; 16f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.Set; 17f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.TreeSet; 18f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.regex.Matcher; 19f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.regex.Pattern; 2010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 21f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport plume.FileIOException; 22f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport plume.Option; 23b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernstimport plume.OptionGroup; 24f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport plume.Options; 25f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport plume.Pair; 26f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport plume.UtilMDE; 2704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport type.Type; 2804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.Annotation; 2904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ABlock; 3004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AClass; 3104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ADeclaration; 3204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AElement; 3304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AExpression; 3404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AField; 3504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AMethod; 3604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AScene; 3704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ATypeElement; 3804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ATypeElementWithType; 3904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AnnotationDef; 4004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.DefException; 4104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ElementVisitor; 4204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.LocalLocation; 4304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.io.ASTIndex; 4404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.io.ASTPath; 45d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport annotations.io.ASTRecord; 468819fd6c8f50083311182795717e23e88cd04ac5Dan Brownimport annotations.io.DebugWriter; 47e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brownimport annotations.io.IndexFileParser; 4804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.io.IndexFileWriter; 4904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.util.coll.VivifyingMap; 50afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brownimport annotator.find.AnnotationInsertion; 515491118a39a8545a38eb1a94bbc5f5a00a0b9beeDan Brownimport annotator.find.CastInsertion; 520b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brownimport annotator.find.ConstructorInsertion; 53e13e8963268c825e80bb92e310135617d7275656Eric Spishakimport annotator.find.Criteria; 5404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotator.find.GenericArrayLocationCriterion; 5510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport annotator.find.Insertion; 56290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport annotator.find.Insertions; 5784a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brownimport annotator.find.NewInsertion; 58c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brownimport annotator.find.ReceiverInsertion; 5910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport annotator.find.TreeFinder; 6004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotator.find.TypedInsertion; 6104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotator.scanner.LocalVariableScanner; 6210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport annotator.specification.IndexFileSpecification; 6310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 6404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport com.google.common.collect.LinkedHashMultimap; 6504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport com.google.common.collect.Multimap; 66f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport com.google.common.collect.SetMultimap; 67f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport com.sun.source.tree.CompilationUnitTree; 6876f3628361358abc328f92c107a7e11733dad1d7Dan Brownimport com.sun.source.tree.ExpressionTree; 69f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport com.sun.source.tree.Tree; 705534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernstimport com.sun.source.util.TreePath; 7104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; 72de7d64fbe7b6eb28b7ec1a2393b91b8e9c6afea6Dan Brownimport com.sun.tools.javac.main.CommandLine; 73b7158c74813fa9eed49afea2189aee0cf51cfb73Dan Brownimport com.sun.tools.javac.tree.JCTree; 7410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 7510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali/** 7610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * This is the main class for the annotator, which inserts annotations in 77c15d52e959f2b3052978e40552159de77c403428Michael Ernst * Java source code. You can call it as <tt>java annotator.Main</tt> or by 78c15d52e959f2b3052978e40552159de77c403428Michael Ernst * using the shell script <tt>insert-annotations-to-source</tt>. 79c15d52e959f2b3052978e40552159de77c403428Michael Ernst * <p> 80c15d52e959f2b3052978e40552159de77c403428Michael Ernst * 81c15d52e959f2b3052978e40552159de77c403428Michael Ernst * It takes as input 8210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <ul> 8376be24f6310e0f8e8120e223e14bc0b4690408d4Werner Dietl * <li>annotation (index) files, which indicate the annotations to insert</li> 8410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>Java source files, into which the annotator inserts annotations</li> 8510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * </ul> 86b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * Annotations that are not for the specified Java files are ignored. 8710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <p> 8810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * 89b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * The <a name="command-line-options">command-line options</a> are as follows: 90b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <!-- start options doc (DO NOT EDIT BY HAND) --> 91b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <ul> 92b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="optiongroup:General-options">General options 93b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <ul> 94b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:outdir"><b>-d</b> <b>--outdir=</b><i>directory</i>. Directory in which output files are written. [default annotated/]</li> 95b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:in-place"><b>-i</b> <b>--in-place=</b><i>boolean</i>. If true, overwrite original source files (making a backup first). 96b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * Furthermore, if the backup files already exist, they are used instead 97b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * of the .java files. This behavior permits a user to tweak the .jaif 98b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * file and re-run the annotator. 99b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <p> 100b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * 101b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * Note that if the user runs the annotator with --in-place, makes edits, 102b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * and then re-runs the annotator with this --in-place option, those 103b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * edits are lost. Similarly, if the user runs the annotator twice in a 104b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * row with --in-place, only the last set of annotations will appear in 105b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * the codebase at the end. 106b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <p> 107b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * 108b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * To preserve changes when using the --in-place option, first remove the 109b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * backup files. Or, use the <tt>-d .</tt> option, which makes (and 110b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * reads) no backup, instead of --in-place. [default false]</li> 111b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:abbreviate"><b>-a</b> <b>--abbreviate=</b><i>boolean</i>. Abbreviate annotation names [default true]</li> 112b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:comments"><b>-c</b> <b>--comments=</b><i>boolean</i>. Insert annotations in comments [default false]</li> 113b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:omit-annotation"><b>-o</b> <b>--omit-annotation=</b><i>string</i>. Omit given annotation</li> 114b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:nowarn"><b>--nowarn=</b><i>boolean</i>. Suppress warnings about disallowed insertions [default false]</li> 115b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:convert-jaifs"><b>--convert-jaifs=</b><i>boolean</i>. Convert JAIFs to new format [default false]</li> 116b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:help"><b>-h</b> <b>--help=</b><i>boolean</i>. Print usage information and exit [default false]</li> 117b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </ul> 118b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </li> 119b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="optiongroup:Debugging-options">Debugging options 120b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <ul> 121b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:verbose"><b>-v</b> <b>--verbose=</b><i>boolean</i>. Verbose (print progress information) [default false]</li> 122b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:debug"><b>--debug=</b><i>boolean</i>. Debug (print debug information) [default false]</li> 123b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:print-error-stack"><b>--print-error-stack=</b><i>boolean</i>. Print error stack [default false]</li> 124b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </ul> 125b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </li> 126b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </ul> 127b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <!-- end options doc --> 12810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 12910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipublic class Main { 13010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 13110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** Directory in which output files are written. */ 132b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst @OptionGroup("General options") 13310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-d <directory> Directory in which output files are written") 13410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static String outdir = "annotated/"; 13510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 136fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst /** 137fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * If true, overwrite original source files (making a backup first). 138fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * Furthermore, if the backup files already exist, they are used instead 139fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * of the .java files. This behavior permits a user to tweak the .jaif 140fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * file and re-run the annotator. 141fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * <p> 142fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * 143fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * Note that if the user runs the annotator with --in-place, makes edits, 144fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * and then re-runs the annotator with this --in-place option, those 145fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * edits are lost. Similarly, if the user runs the annotator twice in a 146fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * row with --in-place, only the last set of annotations will appear in 147fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * the codebase at the end. 148fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * <p> 149fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * 150fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * To preserve changes when using the --in-place option, first remove the 151fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * backup files. Or, use the <tt>-d .</tt> option, which makes (and 152fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * reads) no backup, instead of --in-place. 153fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst */ 154f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst @Option("-i Overwrite original source files") 155f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst public static boolean in_place = false; 156f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 15710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-a Abbreviate annotation names") 15810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean abbreviate = true; 15910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 16010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-c Insert annotations in comments") 16110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean comments = false; 16210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 163bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst @Option("-o Omit given annotation") 164bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst public static String omit_annotation; 165bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst 1667a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst @Option("Suppress warnings about disallowed insertions") 1677a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst public static boolean nowarn; 1687a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst 16940cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown // Instead of doing insertions, create new JAIFs using AST paths 17040cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown // extracted from existing JAIFs and source files they match 17140cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown @Option("Convert JAIFs to AST Path format") 1727a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst public static boolean convert_jaifs = false; 1737a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst 17438326fd68e58af05a0368708acf0099d4c3d0ac1Michael Ernst @Option("-h Print usage information and exit") 17538326fd68e58af05a0368708acf0099d4c3d0ac1Michael Ernst public static boolean help = false; 17638326fd68e58af05a0368708acf0099d4c3d0ac1Michael Ernst 1777a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst // Debugging options go below here. 1787a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst 179b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst @OptionGroup("Debugging options") 18010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-v Verbose (print progress information)") 18110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean verbose; 18210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 18310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("Debug (print debug information)") 18410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean debug = false; 18510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 1868b8c76e4860528031809204af427c71f6ee81fc2Eric Spishak @Option("Print error stack") 1878b8c76e4860528031809204af427c71f6ee81fc2Eric Spishak public static boolean print_error_stack = false; 1888b8c76e4860528031809204af427c71f6ee81fc2Eric Spishak 18904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown private static ElementVisitor<Void, AElement> classFilter = 19004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown new ElementVisitor<Void, AElement>() { 19104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown <K, V extends AElement> 19204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Void filter(VivifyingMap<K, V> vm0, VivifyingMap<K, V> vm1) { 19304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<K, V> entry : vm0.entrySet()) { 19404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry.getValue().accept(this, vm1.vivify(entry.getKey())); 19504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 19604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 19704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 19804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 19904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 20004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitAnnotationDef(AnnotationDef def, AElement el) { 20104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // not used, since package declarations not handled here 20204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 20304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 20404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 20504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 20604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitBlock(ABlock el0, AElement el) { 20704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ABlock el1 = (ABlock) el; 20804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.locals, el1.locals); 20904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitExpression(el0, el); 21004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 21104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 21204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 21304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitClass(AClass el0, AElement el) { 21404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AClass el1 = (AClass) el; 21504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.methods, el1.methods); 21604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.fields, el1.fields); 21704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.fieldInits, el1.fieldInits); 21804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.staticInits, el1.staticInits); 21904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.instanceInits, el1.instanceInits); 22004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitDeclaration(el0, el); 22104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 22204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 22304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 22404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitDeclaration(ADeclaration el0, AElement el) { 22504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ADeclaration el1 = (ADeclaration) el; 22604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown VivifyingMap<ASTPath, ATypeElement> insertAnnotations = 22704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el1.insertAnnotations; 22804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown VivifyingMap<ASTPath, ATypeElementWithType> insertTypecasts = 22904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el1.insertTypecasts; 23004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<ASTPath, ATypeElement> entry : 23104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.insertAnnotations.entrySet()) { 23204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p = entry.getKey(); 23304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElement e = entry.getValue(); 23404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertAnnotations.put(p, e); 23504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown //visitTypeElement(e, insertAnnotations.vivify(p)); 23604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 23704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<ASTPath, ATypeElementWithType> entry : 23804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.insertTypecasts.entrySet()) { 23904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p = entry.getKey(); 24004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElementWithType e = entry.getValue(); 24104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown type.Type type = e.getType(); 24204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (type instanceof type.DeclaredType 24304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown && ((type.DeclaredType) type).getName().isEmpty()) { 24404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertAnnotations.put(p, e); 24504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown //visitTypeElement(e, insertAnnotations.vivify(p)); 24604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } else { 24704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertTypecasts.put(p, e); 24804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown //visitTypeElementWithType(e, insertTypecasts.vivify(p)); 24904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 25004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 25104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 25204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 25304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 25404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 25504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitExpression(AExpression el0, AElement el) { 25604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AExpression el1 = (AExpression) el; 25704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.typecasts, el1.typecasts); 25804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.instanceofs, el1.instanceofs); 25904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.news, el1.news); 26004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 26104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 26204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 26304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 26404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitField(AField el0, AElement el) { 26504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitDeclaration(el0, el); 26604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 26704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 26804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 26904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitMethod(AMethod el0, AElement el) { 27004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AMethod el1 = (AMethod) el; 27104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.bounds, el1.bounds); 27204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.parameters, el1.parameters); 27304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.throwsException, el1.throwsException); 27404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.returnType.accept(this, el1.returnType); 27504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.receiver.accept(this, el1.receiver); 27604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.body.accept(this, el1.body); 27704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitDeclaration(el0, el); 27804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 27904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 28004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 28104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitTypeElement(ATypeElement el0, AElement el) { 28204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElement el1 = (ATypeElement) el; 28304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.innerTypes, el1.innerTypes); 28404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 28504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 28604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 28704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 28804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitTypeElementWithType(ATypeElementWithType el0, 28904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AElement el) { 29004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElementWithType el1 = (ATypeElementWithType) el; 29104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el1.setType(el0.getType()); 29204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitTypeElement(el0, el); 29304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 29404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 29504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 29604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitElement(AElement el, AElement arg) { 29704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 29804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 29904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown }; 30004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 30104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown private static AScene filteredScene(final AScene scene) { 30204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown final AScene filtered = new AScene(); 30304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filtered.packages.putAll(scene.packages); 30404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filtered.imports.putAll(scene.imports); 30504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<String, AClass> entry : scene.classes.entrySet()) { 30604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown String key = entry.getKey(); 30704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AClass clazz0 = entry.getValue(); 30804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AClass clazz1 = filtered.classes.vivify(key); 30904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown clazz0.accept(classFilter, clazz1); 31004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 31104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filtered.prune(); 31204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return filtered; 31304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 31404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 31504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown private static ATypeElement findInnerTypeElement(Tree t, 316d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown ASTRecord rec, ADeclaration decl, Type type, Insertion ins) { 31704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath astPath = rec.astPath; 31804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown GenericArrayLocationCriterion galc = 31904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ins.getCriteria().getGenericArrayLocation(); 32004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown assert astPath != null && galc != null; 32104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown List<TypePathEntry> tpes = galc.getLocation(); 32204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.ASTEntry entry; 32304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (TypePathEntry tpe : tpes) { 32404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown switch (tpe.tag) { 32504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case ARRAY: 32604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (!astPath.isEmpty()) { 32704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = astPath.get(-1); 32804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (entry.getTreeKind() == Tree.Kind.NEW_ARRAY 32904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown && entry.childSelectorIs(ASTPath.TYPE)) { 33004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.NEW_ARRAY, 33104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.TYPE, entry.getArgument() + 1); 33204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 33304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 33404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 33504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.ARRAY_TYPE, 33604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.TYPE); 33704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 33804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case INNER_TYPE: 33904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.MEMBER_SELECT, 34004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.EXPRESSION); 34104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 34204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case TYPE_ARGUMENT: 34304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.PARAMETERIZED_TYPE, 34404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.TYPE_ARGUMENT, tpe.arg); 34504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 34604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case WILDCARD: 34704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.UNBOUNDED_WILDCARD, 34804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.BOUND); 34904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 35004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown default: 35104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown throw new IllegalArgumentException("unknown type tag " + tpe.tag); 35204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 353d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown astPath = astPath.extend(entry); 35404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 35504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 35604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return decl.insertAnnotations.vivify(astPath); 35704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 35804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 3592a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown private static void convertInsertion(String pkg, 3602a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCCompilationUnit tree, ASTRecord rec, Insertion ins, 3612a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AScene scene, Multimap<Insertion, Annotation> insertionSources) { 3622a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Collection<Annotation> annos = insertionSources.get(ins); 3632a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec == null) { 3642a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ins.getCriteria().isOnPackage()) { 3652a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Annotation anno : annos) { 3662a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown scene.packages.get(pkg).tlAnnotationsHere.add(anno); 3672a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3682a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3692a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else if (scene != null && rec.className != null) { 3702a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AClass clazz = scene.classes.vivify(rec.className); 3712a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ADeclaration decl = null; // insertion target 3722a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ins.getCriteria().onBoundZero()) { 3732a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int n = rec.astPath.size(); 3742a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (!rec.astPath.get(n-1).childSelectorIs(ASTPath.BOUND)) { 3752a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ASTPath astPath = ASTPath.empty(); 3762a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (int i = 0; i < n; i++) { 3772a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown astPath = astPath.extend(rec.astPath.get(i)); 3782a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3792a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown astPath = astPath.extend( 3802a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown new ASTPath.ASTEntry(Tree.Kind.TYPE_PARAMETER, 3812a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ASTPath.BOUND, 0)); 3822a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown rec = rec.replacePath(astPath); 3832a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3842a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3852a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec.methodName == null) { 3862a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = rec.varName == null ? clazz 3872a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown : clazz.fields.vivify(rec.varName); 3882a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else { 3892a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AMethod meth = clazz.methods.vivify(rec.methodName); 3902a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec.varName == null) { 3912a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = meth; // ? 3922a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else { 3932a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown try { 3942a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int i = Integer.parseInt(rec.varName); 3952a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = i < 0 ? meth.receiver 3962a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown : meth.parameters.vivify(i); 3972a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } catch (NumberFormatException e) { 3982a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown TreePath path = ASTIndex.getTreePath(tree, rec); 3992a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCVariableDecl varTree = null; 4002a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCMethodDecl methTree = null; 4012a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCClassDecl classTree = null; 4022a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown loop: 4032a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown while (path != null) { 4042a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree leaf = path.getLeaf(); 4052a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown switch (leaf.getKind()) { 4062a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case VARIABLE: 4072a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown varTree = (JCTree.JCVariableDecl) leaf; 4082a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4092a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case METHOD: 4102a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown methTree = (JCTree.JCMethodDecl) leaf; 4112a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4122a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case ANNOTATION: 4132a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case CLASS: 4142a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case ENUM: 4152a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case INTERFACE: 4162a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break loop; 4172a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown default: 4182a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown path = path.getParentPath(); 4192a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4202a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4212a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown while (path != null) { 4222a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree leaf = path.getLeaf(); 4232a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree.Kind kind = leaf.getKind(); 4242a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (kind == Tree.Kind.METHOD) { 4252a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown methTree = (JCTree.JCMethodDecl) leaf; 4262a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int i = LocalVariableScanner.indexOfVarTree(path, 4272a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown varTree, rec.varName); 4282a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int m = methTree.getStartPosition(); 4292a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int a = varTree.getStartPosition(); 4302a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int b = varTree.getEndPosition(tree.endPositions); 4312a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown LocalLocation loc = new LocalLocation(i, a-m, b-a); 4322a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = meth.body.locals.vivify(loc); 4332a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4342a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4352a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ASTPath.isClassEquiv(kind)) { 4362a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown classTree = (JCTree.JCClassDecl) leaf; 4372a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown // ??? 4382a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4392a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4402a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown path = path.getParentPath(); 4412a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4422a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4432a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4442a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4452a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (decl != null) { 4462a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AElement el; 4472a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec.astPath.isEmpty()) { 4482a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el = decl; 4492a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else if (ins.getKind() == Insertion.Kind.CAST) { 4502a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown annotations.el.ATypeElementWithType elem = 4512a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl.insertTypecasts.vivify(rec.astPath); 4522a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown elem.setType(((CastInsertion) ins).getType()); 4532a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el = elem; 4542a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else { 4552a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el = decl.insertAnnotations.vivify(rec.astPath); 4562a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4572a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Annotation anno : annos) { 4582a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el.tlAnnotationsHere.add(anno); 4592a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4602a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ins instanceof TypedInsertion) { 4612a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown TypedInsertion ti = (TypedInsertion) ins; 4622a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (!rec.astPath.isEmpty()) { 4632a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown //addInnerTypePaths(decl, rec, ti, insertionSources); 4642a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4652a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Insertion inner : ti.getInnerTypeInsertions()) { 4662a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree t = ASTIndex.getNode(tree, rec); 4672a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (t != null) { 4682a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ATypeElement elem = findInnerTypeElement(t, 4692a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown rec, decl, ti.getType(), inner); 4702a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Annotation a : insertionSources.get(inner)) { 4712a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown elem.tlAnnotationsHere.add(a); 4722a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4732a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4742a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4752a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4762a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4772a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4782a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4792a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown 4802a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown 48110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Implementation details: 48210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // 1. The annotator partially compiles source 48310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // files using the compiler API (JSR-199), obtaining an AST. 48410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // 2. The annotator reads the specification file, producing a set of 48510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // annotator.find.Insertions. Insertions completely specify what to 48610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // write (as a String, which is ultimately translated according to the 48710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // keyword file) and how to write it (as annotator.find.Criteria). 48810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // 3. It then traverses the tree, looking for nodes that satisfy the 48910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Insertion Criteria, translating the Insertion text against the 49010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // keyword file, and inserting the annotations into the source file. 49110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 49210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 49310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Runs the annotator, parsing the source and spec files and applying 49410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * the annotations. 49510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 496de7d64fbe7b6eb28b7ec1a2393b91b8e9c6afea6Dan Brown public static void main(String[] args) throws IOException { 49710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 49810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (verbose) { 49967693622be4bed63a07df6f0ce34f7c8bd52baf5Michael Ernst System.out.printf("insert-annotations-to-source (%s)", 50067693622be4bed63a07df6f0ce34f7c8bd52baf5Michael Ernst annotations.io.classfile.ClassFileReader.INDEX_UTILS_VERSION); 50110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 50210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 503e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown Options options = new Options( 504e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown "Main [options] { ann-file | java-file | @arg-file } ...\n" 505e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown + "(Contents of argfiles are expanded into the argument list.)", 506e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown Main.class); 5070ab9de82370c7e2890fd532eca754342a962b452Dan Brown String[] file_args; 508de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown try { 509de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown String[] cl_args = CommandLine.parse(args); 510de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown file_args = options.parse_or_usage(cl_args); 511de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown } catch (IOException ex) { 512de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.err.println(ex); 513e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown System.err.println("(For non-argfile beginning with \"@\", use \"@@\" for initial \"@\"."); 514de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.err.println("Alternative for filenames: indicate directory, e.g. as './@file'."); 515de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.err.println("Alternative for flags: use '=', as in '-o=@Deprecated'.)"); 5160ab9de82370c7e2890fd532eca754342a962b452Dan Brown file_args = null; // Eclipse compiler issue workaround 517de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.exit(1); 518de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown } 519f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 5208819fd6c8f50083311182795717e23e88cd04ac5Dan Brown DebugWriter dbug = new DebugWriter(); 5218819fd6c8f50083311182795717e23e88cd04ac5Dan Brown DebugWriter verb = new DebugWriter(); 5228819fd6c8f50083311182795717e23e88cd04ac5Dan Brown DebugWriter both = dbug.or(verb); 5238819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.setEnabled(debug); 5248819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.setEnabled(verbose); 5259849f43e0d770ee036b568dbba96d4e6a2a2b270Dan Brown TreeFinder.warn.setEnabled(!nowarn); 5268819fd6c8f50083311182795717e23e88cd04ac5Dan Brown TreeFinder.stak.setEnabled(print_error_stack); 5278819fd6c8f50083311182795717e23e88cd04ac5Dan Brown TreeFinder.dbug.setEnabled(debug); 5288819fd6c8f50083311182795717e23e88cd04ac5Dan Brown Criteria.dbug.setEnabled(debug); 5291220f0e5dd7642f90aab557b3bda8e177ce06316Michael Ernst 53010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (help) { 53110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali options.print_usage(); 53210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(0); 53310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 53410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 535f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (in_place && outdir != "annotated/") { // interned 536f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst options.print_usage("The --outdir and --in-place options are mutually exclusive."); 537f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst System.exit(1); 538f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 539f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 54010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (file_args.length < 2) { 541f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst options.print_usage("Supplied %d arguments, at least 2 needed%n", file_args.length); 54210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(1); 54310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 54410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 54510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // The insertions specified by the annotation files. 546290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown Insertions insertions = new Insertions(); 54710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // The Java files into which to insert. 54810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali List<String> javafiles = new ArrayList<String>(); 549d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown // Imports required to resolve annotations (when abbreviate==true). 550e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown Set<String> imports = new LinkedHashSet<String>(); 551d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown 552d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown // Indices to maintain insertion source traces. 55304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Map<String, Multimap<Insertion, Annotation>> insertionIndex = 55404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown new HashMap<String, Multimap<Insertion, Annotation>>(); 55504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Map<Insertion, String> insertionOrigins = new HashMap<Insertion, String>(); 55604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Map<String, AScene> scenes = new HashMap<String, AScene>(); 557e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown 558e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown IndexFileParser.setAbbreviate(abbreviate); 55910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (String arg : file_args) { 56010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (arg.endsWith(".java")) { 56110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali javafiles.add(arg); 5628ef7819881d25642b26b60a274f9c148d4356e3dWerner Dietl } else if (arg.endsWith(".jaif") || 5638ef7819881d25642b26b60a274f9c148d4356e3dWerner Dietl arg.endsWith(".jann")) { 56404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown IndexFileSpecification spec = new IndexFileSpecification(arg); 56510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali try { 56610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali List<Insertion> parsedSpec = spec.parse(); 56704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AScene scene = spec.getScene(); 56870918686c71c2030c56e623a9427f05b99338a5eDan Brown Collections.sort(parsedSpec, new Comparator<Insertion>() { 56904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 57004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public int compare(Insertion i1, Insertion i2) { 57104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p1 = i1.getCriteria().getASTPath(); 57204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p2 = i2.getCriteria().getASTPath(); 57304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return p1 == null 57404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ? p2 == null ? 0 : -1 57504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown : p2 == null ? 1 : p1.compareTo(p2); 57604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 57704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown }); 57840cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown if (convert_jaifs) { 5799967de5fe4b0240e9b5169020aec35fb29cdfb83Dan Brown scenes.put(arg, filteredScene(scene)); 58040cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown for (Insertion ins : parsedSpec) { 58140cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown insertionOrigins.put(ins, arg); 58240cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown } 58340cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown if (!insertionIndex.containsKey(arg)) { 58440cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown insertionIndex.put(arg, 58540cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown LinkedHashMultimap.<Insertion, Annotation>create()); 58640cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown } 58740cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown insertionIndex.get(arg).putAll(spec.insertionSources()); 58804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 589e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown if (abbreviate) { 590e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown Map<String, Set<String>> annotationImports = 59104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown spec.annotationImports(); 592e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown for (Set<String> set : annotationImports.values()) { 593e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown imports.addAll(set); 594e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown } 595e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown } 5968819fd6c8f50083311182795717e23e88cd04ac5Dan Brown both.debug("Read %d annotations from %s%n", parsedSpec.size(), arg); 597bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst if (omit_annotation != null) { 5988819fd6c8f50083311182795717e23e88cd04ac5Dan Brown List<Insertion> filtered = 5998819fd6c8f50083311182795717e23e88cd04ac5Dan Brown new ArrayList<Insertion>(parsedSpec.size()); 600bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst for (Insertion insertion : parsedSpec) { 6012441c4b66f26bf96ea7a8749645a933aa09a2d62Eric Spishak // TODO: this won't omit annotations if the insertion is more than 6022441c4b66f26bf96ea7a8749645a933aa09a2d62Eric Spishak // just the annotation (such as if the insertion is a cast 6032441c4b66f26bf96ea7a8749645a933aa09a2d62Eric Spishak // insertion or a 'this' parameter in a method declaration). 604bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst if (! omit_annotation.equals(insertion.getText())) { 605bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst filtered.add(insertion); 606bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst } 607bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst } 608bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst parsedSpec = filtered; 6098819fd6c8f50083311182795717e23e88cd04ac5Dan Brown both.debug("After filtering: %d annotations from %s%n", 6108819fd6c8f50083311182795717e23e88cd04ac5Dan Brown parsedSpec.size(), arg); 611bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst } 612bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst insertions.addAll(parsedSpec); 6132c4067b440b23911687e4a353584b088eccf17fbMichael Ernst } catch (RuntimeException e) { 6142c4067b440b23911687e4a353584b088eccf17fbMichael Ernst if (e.getCause() != null 6152c4067b440b23911687e4a353584b088eccf17fbMichael Ernst && e.getCause() instanceof FileNotFoundException) { 6162c4067b440b23911687e4a353584b088eccf17fbMichael Ernst System.err.println("File not found: " + arg); 6172c4067b440b23911687e4a353584b088eccf17fbMichael Ernst System.exit(1); 6182c4067b440b23911687e4a353584b088eccf17fbMichael Ernst } else { 6192c4067b440b23911687e4a353584b088eccf17fbMichael Ernst throw e; 6202c4067b440b23911687e4a353584b088eccf17fbMichael Ernst } 62110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } catch (FileIOException e) { 622bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak // Add 1 to the line number since line numbers in text editors are usually one-based. 623bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak System.err.println("Error while parsing annotation file " + arg + " at line " 624bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak + (e.lineNumber + 1) + ":"); 62510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (e.getMessage() != null) { 626bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak System.err.println('\t' + e.getMessage()); 627bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak } 628bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak if (e.getCause() != null && e.getCause().getMessage() != null) { 629bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak System.err.println('\t' + e.getCause().getMessage()); 630bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak } 6318819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (print_error_stack) { 632bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak e.printStackTrace(); 63310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 63410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(1); 63510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 63610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } else { 63710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali throw new Error("Unrecognized file extension: " + arg); 63810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 63910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 64010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 6418819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (dbug.isEnabled()) { 6428819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("%d insertions, %d .java files%n", 6438819fd6c8f50083311182795717e23e88cd04ac5Dan Brown insertions.size(), javafiles.size()); 6448819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("Insertions:%n"); 64510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (Insertion insertion : insertions) { 6468819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug(" %s%n", insertion); 64710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 64810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 64910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 65010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (String javafilename : javafiles) { 6518819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.debug("Processing %s%n", javafilename); 65210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 653f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst File javafile = new File(javafilename); 654f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst File unannotated = new File(javafilename + ".unannotated"); 655f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (in_place) { 656f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // It doesn't make sense to check timestamps; 657f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // if the .java.unannotated file exists, then just use it. 658f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // A user can rename that file back to just .java to cause the 659f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // .java file to be read. 660f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (unannotated.exists()) { 6618819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.debug("Renaming %s to %s%n", unannotated, javafile); 662f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst boolean success = unannotated.renameTo(javafile); 663f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (! success) { 664f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst throw new Error(String.format("Failed renaming %s to %s", 665f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst unannotated, javafile)); 666f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 667f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 668f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 669f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 67076f3628361358abc328f92c107a7e11733dad1d7Dan Brown String fileSep = System.getProperty("file.separator"); 67110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali String fileLineSep = System.getProperty("line.separator"); 67210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali Source src; 67310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Get the source file, and use it to obtain parse trees. 67410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali try { 67510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // fileLineSep is set here so that exceptions can be caught 67610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali fileLineSep = UtilMDE.inferLineSeparator(javafilename); 67710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali src = new Source(javafilename); 6788819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.debug("Parsed %s%n", javafilename); 67904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } catch (Source.CompilerException e) { 68010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali e.printStackTrace(); 68110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return; 68210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } catch (IOException e) { 68310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali e.printStackTrace(); 68410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return; 68510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 68610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 687c15d52e959f2b3052978e40552159de77c403428Michael Ernst int num_insertions = 0; 68876f3628361358abc328f92c107a7e11733dad1d7Dan Brown String pkg = ""; 689c15d52e959f2b3052978e40552159de77c403428Michael Ernst 690b7158c74813fa9eed49afea2189aee0cf51cfb73Dan Brown for (CompilationUnitTree cut : src.parse()) { 691b7158c74813fa9eed49afea2189aee0cf51cfb73Dan Brown JCTree.JCCompilationUnit tree = (JCTree.JCCompilationUnit) cut; 69276f3628361358abc328f92c107a7e11733dad1d7Dan Brown ExpressionTree pkgExp = cut.getPackageName(); 69376f3628361358abc328f92c107a7e11733dad1d7Dan Brown pkg = pkgExp == null ? "" : pkgExp.toString(); 69410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 69510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Create a finder, and use it to get positions. 69610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali TreeFinder finder = new TreeFinder(tree); 69752dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown SetMultimap<Pair<Integer, ASTPath>, Insertion> positions = 6988819fd6c8f50083311182795717e23e88cd04ac5Dan Brown finder.getPositions(tree, insertions); 69910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 70004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (convert_jaifs) { 70104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // program used only for JAIF conversion; execute following 70204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // block and then skip remainder of loop 703d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown Multimap<ASTRecord, Insertion> astInsertions = 70404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown finder.getPaths(); 705d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown for (Map.Entry<ASTRecord, Collection<Insertion>> entry : 70604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown astInsertions.asMap().entrySet()) { 707d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown ASTRecord rec = entry.getKey(); 70804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Insertion ins : entry.getValue()) { 70904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (ins.getCriteria().getASTPath() != null) { continue; } 71004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown String arg = insertionOrigins.get(ins); 71104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AScene scene = scenes.get(arg); 71204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Multimap<Insertion, Annotation> insertionSources = 71304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertionIndex.get(arg); 71404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown //String text = 71504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // ins.getText(comments, abbreviate, false, 0, '\0'); 71604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 71704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // TODO: adjust for missing end of path (?) 71804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 71904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (insertionSources.containsKey(ins)) { 7202a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown convertInsertion(pkg, tree, rec, ins, scene, insertionSources); 72104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 72204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 72304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 72404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown continue; 72504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 72604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 72710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Apply the positions to the source file. 7288819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (both.isEnabled()) { 7298819fd6c8f50083311182795717e23e88cd04ac5Dan Brown System.err.printf( 7308819fd6c8f50083311182795717e23e88cd04ac5Dan Brown "getPositions returned %d positions in tree for %s%n", 7318819fd6c8f50083311182795717e23e88cd04ac5Dan Brown positions.size(), javafilename); 73210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 73310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 73452dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Set<Pair<Integer, ASTPath>> positionKeysUnsorted = 73552dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown positions.keySet(); 73652dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Set<Pair<Integer, ASTPath>> positionKeysSorted = 73752dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown new TreeSet<Pair<Integer, ASTPath>>( 73852dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown new Comparator<Pair<Integer, ASTPath>>() { 73952dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown @Override 74052dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown public int compare(Pair<Integer, ASTPath> p1, 74152dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Pair<Integer, ASTPath> p2) { 74252dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown int c = Integer.compare(p2.a, p1.a); 74352dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown if (c == 0) { 74452dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown c = p2.b == null ? p1.b == null ? 0 : -1 74552dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown : p1.b == null ? 1 : p2.b.compareTo(p1.b); 74652dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown } 74752dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown return c; 74852dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown } 74952dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown }); 75057ea23519ad96aca616e5fe41b4a1db896b91096Michael Ernst positionKeysSorted.addAll(positionKeysUnsorted); 75152dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown for (Pair<Integer, ASTPath> pair : positionKeysSorted) { 752c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown boolean receiverInserted = false; 75384a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown boolean newInserted = false; 7540b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown boolean constructorInserted = false; 75552dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Set<String> seen = new TreeSet<String>(); 75652dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown List<Insertion> toInsertList = new ArrayList<Insertion>(positions.get(pair)); 757ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst Collections.reverse(toInsertList); 758553a9a9a17ce582f701841b59edfadb491ed54adDan Brown dbug.debug("insertion pos: %d%n", pair.a); 759553a9a9a17ce582f701841b59edfadb491ed54adDan Brown assert pair.a >= 0 760553a9a9a17ce582f701841b59edfadb491ed54adDan Brown : "pos is negative: " + pair.a + " " + toInsertList.get(0) + " " + javafilename; 761ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst for (Insertion iToInsert : toInsertList) { 762ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // Possibly add whitespace after the insertion 7633d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak String trailingWhitespace = ""; 764ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst boolean gotSeparateLine = false; 765553a9a9a17ce582f701841b59edfadb491ed54adDan Brown int pos = pair.a; // reset each iteration in case of dyn adjustment 766ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst if (iToInsert.getSeparateLine()) { 767a1b0d6cb20867adf4fad0359336510469353ad29Michael Ernst // System.out.printf("getSeparateLine=true for insertion at pos %d: %s%n", pos, iToInsert); 768ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst int indentation = 0; 769ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst while ((pos - indentation != 0) 770ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // horizontal whitespace 771ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst && (src.charAt(pos-indentation-1) == ' ' 772ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || src.charAt(pos-indentation-1) == '\t')) { 773a1b0d6cb20867adf4fad0359336510469353ad29Michael Ernst // System.out.printf("src.charAt(pos-indentation-1 == %d-%d-1)='%s'%n", 774a1b0d6cb20867adf4fad0359336510469353ad29Michael Ernst // pos, indentation, src.charAt(pos-indentation-1)); 775ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst indentation++; 776ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst } 777ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst if ((pos - indentation == 0) 778ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // horizontal whitespace 779ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || (src.charAt(pos-indentation-1) == '\f' 780ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || src.charAt(pos-indentation-1) == '\n' 781ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || src.charAt(pos-indentation-1) == '\r')) { 7823d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak trailingWhitespace = fileLineSep + src.substring(pos-indentation, pos); 783ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst gotSeparateLine = true; 784ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst } 785ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst } 786c71d4e21017f8f4412a2d399676e358858999623Michael Ernst 7873d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak char precedingChar; 7883d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak if (pos != 0) { 7893d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak precedingChar = src.charAt(pos - 1); 7903d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak } else { 7913d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak precedingChar = '\0'; 7923d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak } 793afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown 794afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown if (iToInsert.getKind() == Insertion.Kind.ANNOTATION) { 795afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown AnnotationInsertion ai = (AnnotationInsertion) iToInsert; 796dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown if (ai.isGenerateBound()) { // avoid multiple ampersands 797dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown try { 798dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown String s = src.substring(pos, pos+9); 799dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown if ("Object & ".equals(s)) { 800dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown ai.setGenerateBound(false); 801dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown precedingChar = '.'; // suppress leading space 802dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown } 803dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown } catch (StringIndexOutOfBoundsException e) {} 804dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown } 805afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown if (ai.isGenerateExtends()) { // avoid multiple "extends" 806afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown try { 807dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown String s = src.substring(pos, pos+9); 808dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown if (" extends ".equals(s)) { 809afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown ai.setGenerateExtends(false); 810553a9a9a17ce582f701841b59edfadb491ed54adDan Brown pos += 8; 811afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } 812afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } catch (StringIndexOutOfBoundsException e) {} 813afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } 814afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } else if (iToInsert.getKind() == Insertion.Kind.CAST) { 8155491118a39a8545a38eb1a94bbc5f5a00a0b9beeDan Brown ((CastInsertion) iToInsert) 8165491118a39a8545a38eb1a94bbc5f5a00a0b9beeDan Brown .setOnArrayLiteral(src.charAt(pos) == '{'); 817afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } else if (iToInsert.getKind() == Insertion.Kind.RECEIVER) { 818c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown ReceiverInsertion ri = (ReceiverInsertion) iToInsert; 819c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown ri.setAnnotationsOnly(receiverInserted); 820c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown receiverInserted = true; 82184a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown } else if (iToInsert.getKind() == Insertion.Kind.NEW) { 82284a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown NewInsertion ni = (NewInsertion) iToInsert; 82384a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown ni.setAnnotationsOnly(newInserted); 82484a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown newInserted = true; 8250b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown } else if (iToInsert.getKind() == Insertion.Kind.CONSTRUCTOR) { 8260b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown ConstructorInsertion ci = (ConstructorInsertion) iToInsert; 8270b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown if (constructorInserted) { ci.setAnnotationsOnly(true); } 8280b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown constructorInserted = true; 829c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown } 830c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown 8313d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak String toInsert = iToInsert.getText(comments, abbreviate, 8328819fd6c8f50083311182795717e23e88cd04ac5Dan Brown gotSeparateLine, pos, precedingChar) + trailingWhitespace; 8339967de5fe4b0240e9b5169020aec35fb29cdfb83Dan Brown Set<String> packageNames = iToInsert.getPackageNames(); 83452dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown if (seen.contains(toInsert)) { continue; } // eliminate duplicates 83552dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown seen.add(toInsert); 8369967de5fe4b0240e9b5169020aec35fb29cdfb83Dan Brown if (!packageNames.isEmpty()) { 8378819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("Need import %s%n due to insertion %s%n", 8388819fd6c8f50083311182795717e23e88cd04ac5Dan Brown packageNames, toInsert); 8393d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak imports.addAll(packageNames); 8404735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst } 841ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst 842ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // If it's already there, don't re-insert. This is a hack! 843ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // Also, I think this is already checked when constructing the 84476be24f6310e0f8e8120e223e14bc0b4690408d4Werner Dietl // insertions. 845ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst int precedingTextPos = pos-toInsert.length()-1; 846ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst if (precedingTextPos >= 0) { 847ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst String precedingTextPlusChar 848ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst = src.getString().substring(precedingTextPos, pos); 8498819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (toInsert.equals( 8508819fd6c8f50083311182795717e23e88cd04ac5Dan Brown precedingTextPlusChar.substring(0, toInsert.length())) 851ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || toInsert.equals(precedingTextPlusChar.substring(1))) { 8528819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug( 8538819fd6c8f50083311182795717e23e88cd04ac5Dan Brown "Inserting %s at %d in code of length %d with preceding text '%s'%n", 8548819fd6c8f50083311182795717e23e88cd04ac5Dan Brown toInsert, pos, src.getString().length(), 8558819fd6c8f50083311182795717e23e88cd04ac5Dan Brown precedingTextPlusChar); 8568819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("Already present, skipping%n"); 857ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst continue; 8584735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst } 85910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 8603d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak 86184a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown // TODO: Neither the above hack nor this check should be 86284a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown // necessary. Find out why re-insertions still occur and 86384a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown // fix properly. 86484a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown if (iToInsert.getInserted()) { continue; } 865ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst src.insert(pos, toInsert); 8668920570aa95ef0072bafd2cccff03d194c478bf1Dan Brown if (verbose && !debug) { 867c15d52e959f2b3052978e40552159de77c403428Michael Ernst System.out.print("."); 868c15d52e959f2b3052978e40552159de77c403428Michael Ernst num_insertions++; 869c15d52e959f2b3052978e40552159de77c403428Michael Ernst if ((num_insertions % 50) == 0) { 870c15d52e959f2b3052978e40552159de77c403428Michael Ernst System.out.println(); // terminate the line that contains dots 871c15d52e959f2b3052978e40552159de77c403428Michael Ernst } 872c15d52e959f2b3052978e40552159de77c403428Michael Ernst } 8738819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("Post-insertion source: %n" + src.getString()); 87410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 87510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 87610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 87704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 87804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (convert_jaifs) { 87904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<String, AScene> entry : scenes.entrySet()) { 88004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown String filename = entry.getKey(); 88104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AScene scene = entry.getValue(); 88204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown try { 88304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown IndexFileWriter.write(scene, filename + ".converted"); 88404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } catch (DefException e) { 88504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown System.err.println(filename + ": " + " format error in conversion"); 88604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (print_error_stack) { 88704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown e.printStackTrace(); 88804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 88904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 89004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 89104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return; // done with conversion 89204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 89304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 894c15d52e959f2b3052978e40552159de77c403428Michael Ernst if (verbose) { 895c15d52e959f2b3052978e40552159de77c403428Michael Ernst if ((num_insertions % 50) != 0) { 896c15d52e959f2b3052978e40552159de77c403428Michael Ernst System.out.println(); // terminate the line that contains dots 897c15d52e959f2b3052978e40552159de77c403428Michael Ernst } 898c15d52e959f2b3052978e40552159de77c403428Michael Ernst } 89910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 9008819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (dbug.isEnabled()) { 9018819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("%d imports to insert%n", imports.size()); 90204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (String classname : imports) { 9038819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug(" %s%n", classname); 90404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 90504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 90604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 90710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // insert import statements 90810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali { 90910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali Pattern importPattern = Pattern.compile("(?m)^import\\b"); 91010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali Pattern packagePattern = Pattern.compile("(?m)^package\\b.*;(\\n|\\r\\n?)"); 91110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali int importIndex = 0; // default: beginning of file 91210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali String srcString = src.getString(); 91304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Matcher m = importPattern.matcher(srcString); 91410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (m.find()) { 91510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali importIndex = m.start(); 91610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } else { 9178819fd6c8f50083311182795717e23e88cd04ac5Dan Brown // Debug.info("Didn't find import in " + srcString); 91810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali m = packagePattern.matcher(srcString); 91910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (m.find()) { 92010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali importIndex = m.end(); 92110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 92210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 92310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (String classname : imports) { 92410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali String toInsert = "import " + classname + ";" + fileLineSep; 92510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali src.insert(importIndex, toInsert); 92610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali importIndex += toInsert.length(); 92710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 92810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 92910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 93010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Write the source file. 93176f3628361358abc328f92c107a7e11733dad1d7Dan Brown File outfile = null; 93210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali try { 933f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (in_place) { 93476f3628361358abc328f92c107a7e11733dad1d7Dan Brown outfile = javafile; 935f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (verbose) { 936f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst System.out.printf("Renaming %s to %s%n", javafile, unannotated); 937f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 938f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst boolean success = javafile.renameTo(unannotated); 939f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (! success) { 940f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst throw new Error(String.format("Failed renaming %s to %s", 941f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst javafile, unannotated)); 942f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 943f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } else { 94476f3628361358abc328f92c107a7e11733dad1d7Dan Brown if (pkg.isEmpty()) { 94576f3628361358abc328f92c107a7e11733dad1d7Dan Brown outfile = new File(outdir, javafile.getName()); 94676f3628361358abc328f92c107a7e11733dad1d7Dan Brown } else { 94776f3628361358abc328f92c107a7e11733dad1d7Dan Brown String[] pkgPath = pkg.split("\\."); 94876f3628361358abc328f92c107a7e11733dad1d7Dan Brown StringBuilder sb = new StringBuilder(outdir); 94976f3628361358abc328f92c107a7e11733dad1d7Dan Brown for (int i = 0 ; i < pkgPath.length ; i++) { 95076f3628361358abc328f92c107a7e11733dad1d7Dan Brown sb.append(fileSep).append(pkgPath[i]); 95176f3628361358abc328f92c107a7e11733dad1d7Dan Brown } 95276f3628361358abc328f92c107a7e11733dad1d7Dan Brown outfile = new File(sb.toString(), javafile.getName()); 95376f3628361358abc328f92c107a7e11733dad1d7Dan Brown } 954f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst outfile.getParentFile().mkdirs(); 955f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 95610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali OutputStream output = new FileOutputStream(outfile); 957f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (verbose) { 958f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst System.out.printf("Writing %s%n", outfile); 959f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 96010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali src.write(output); 961f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst output.close(); 96210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } catch (IOException e) { 96310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.err.println("Problem while writing file " + outfile); 96410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali e.printStackTrace(); 96510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(1); 96610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 96710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 96810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 96910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 9705534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst public static String pathToString(TreePath path) { 9715534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst if (path == null) 9725534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return "null"; 973f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst return treeToString(path.getLeaf()); 974f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst } 975f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst 976f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst public static String treeToString(Tree node) { 977f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst String asString = node.toString(); 9785534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst String oneLine = firstLine(asString); 9795534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return "\"" + oneLine + "\""; 9805534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 9815534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst 9825534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst /** 9835534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst * Return the first non-empty line of the string, adding an ellipsis 9845534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst * (...) if the string was truncated. 9855534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst */ 9865534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst public static String firstLine(String s) { 9875534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst while (s.startsWith("\n")) { 9885534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst s = s.substring(1); 9895534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 9905534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst int newlineIndex = s.indexOf('\n'); 9915534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst if (newlineIndex == -1) { 9925534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return s; 9935534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } else { 9945534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return s.substring(0, newlineIndex) + "..."; 9955534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 9965534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 9975534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst 998aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb /** 999aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb * Separates the annotation class from its arguments. 1000aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb * 1001aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb * @return given <code>@foo(bar)</code> it returns the pair <code>{ @foo, (bar) }</code>. 1002aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb */ 1003aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb public static Pair<String,String> removeArgs(String s) { 1004aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb int pidx = s.indexOf("("); 1005aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb return (pidx == -1) ? 1006615ec652dc360e33296fd763a4fa56e59c35b23cMichael Ernst Pair.of(s, (String)null) : 1007aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb Pair.of(s.substring(0, pidx), s.substring(pidx)); 1008aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb } 100910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali} 1010