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; 13c31338b45a78642c9b21cce154949870ea826abbDan Brownimport java.util.LinkedHashMap; 14f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.LinkedHashSet; 15f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.List; 16e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brownimport java.util.Map; 17f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.Set; 18f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.TreeSet; 19f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.regex.Matcher; 20f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport java.util.regex.Pattern; 2110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 2243367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport plume.FileIOException; 2343367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport plume.Option; 2443367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport plume.OptionGroup; 2543367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport plume.Options; 2643367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport plume.Pair; 2743367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport plume.UtilMDE; 2804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport type.Type; 2904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.Annotation; 3004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ABlock; 3104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AClass; 3204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ADeclaration; 3304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AElement; 3404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AExpression; 3504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AField; 3604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AMethod; 3704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AScene; 3804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ATypeElement; 3904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ATypeElementWithType; 4004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.AnnotationDef; 4104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.DefException; 4204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.ElementVisitor; 4304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.el.LocalLocation; 4404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.io.ASTIndex; 4504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.io.ASTPath; 46d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport annotations.io.ASTRecord; 478819fd6c8f50083311182795717e23e88cd04ac5Dan Brownimport annotations.io.DebugWriter; 48e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brownimport annotations.io.IndexFileParser; 4904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.io.IndexFileWriter; 5004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotations.util.coll.VivifyingMap; 51afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brownimport annotator.find.AnnotationInsertion; 525491118a39a8545a38eb1a94bbc5f5a00a0b9beeDan Brownimport annotator.find.CastInsertion; 530b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brownimport annotator.find.ConstructorInsertion; 54e13e8963268c825e80bb92e310135617d7275656Eric Spishakimport annotator.find.Criteria; 5504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotator.find.GenericArrayLocationCriterion; 5610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport annotator.find.Insertion; 57290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport annotator.find.Insertions; 5884a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brownimport annotator.find.NewInsertion; 59c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brownimport annotator.find.ReceiverInsertion; 6010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport annotator.find.TreeFinder; 6104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotator.find.TypedInsertion; 6204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport annotator.scanner.LocalVariableScanner; 6310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport annotator.specification.IndexFileSpecification; 6410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 6504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport com.google.common.collect.LinkedHashMultimap; 6604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport com.google.common.collect.Multimap; 67f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport com.google.common.collect.SetMultimap; 68f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport com.sun.source.tree.CompilationUnitTree; 6976f3628361358abc328f92c107a7e11733dad1d7Dan Brownimport com.sun.source.tree.ExpressionTree; 70f41c057e252477de867dd3e5bd9d7bd33d6af4ebEric Spishakimport com.sun.source.tree.Tree; 715534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernstimport com.sun.source.util.TreePath; 7204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brownimport com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; 73de7d64fbe7b6eb28b7ec1a2393b91b8e9c6afea6Dan Brownimport com.sun.tools.javac.main.CommandLine; 74b7158c74813fa9eed49afea2189aee0cf51cfb73Dan Brownimport com.sun.tools.javac.tree.JCTree; 7510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 7610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali/** 7710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * This is the main class for the annotator, which inserts annotations in 78c15d52e959f2b3052978e40552159de77c403428Michael Ernst * Java source code. You can call it as <tt>java annotator.Main</tt> or by 79c15d52e959f2b3052978e40552159de77c403428Michael Ernst * using the shell script <tt>insert-annotations-to-source</tt>. 80c15d52e959f2b3052978e40552159de77c403428Michael Ernst * <p> 81c15d52e959f2b3052978e40552159de77c403428Michael Ernst * 82c15d52e959f2b3052978e40552159de77c403428Michael Ernst * It takes as input 8310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <ul> 8476be24f6310e0f8e8120e223e14bc0b4690408d4Werner Dietl * <li>annotation (index) files, which indicate the annotations to insert</li> 8510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>Java source files, into which the annotator inserts annotations</li> 8610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * </ul> 87b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * Annotations that are not for the specified Java files are ignored. 8810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <p> 8910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * 90b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * The <a name="command-line-options">command-line options</a> are as follows: 91b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <!-- start options doc (DO NOT EDIT BY HAND) --> 92b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <ul> 93b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="optiongroup:General-options">General options 94b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <ul> 95b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:outdir"><b>-d</b> <b>--outdir=</b><i>directory</i>. Directory in which output files are written. [default annotated/]</li> 96b890e553cf7b1ab5befaecd852618835aa451c3fMichael 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). 97b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * Furthermore, if the backup files already exist, they are used instead 98b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * of the .java files. This behavior permits a user to tweak the .jaif 99b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * file and re-run the annotator. 100b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <p> 1014ae81f26445bc9397bd3e1edb062e0388ed82a6fMichael Ernst * 102b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * Note that if the user runs the annotator with --in-place, makes edits, 103b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * and then re-runs the annotator with this --in-place option, those 104b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * edits are lost. Similarly, if the user runs the annotator twice in a 105b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * row with --in-place, only the last set of annotations will appear in 106b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * the codebase at the end. 107b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <p> 1084ae81f26445bc9397bd3e1edb062e0388ed82a6fMichael Ernst * 109b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * To preserve changes when using the --in-place option, first remove the 110b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * backup files. Or, use the <tt>-d .</tt> option, which makes (and 111b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * reads) no backup, instead of --in-place. [default false]</li> 112b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:abbreviate"><b>-a</b> <b>--abbreviate=</b><i>boolean</i>. Abbreviate annotation names [default true]</li> 113b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:comments"><b>-c</b> <b>--comments=</b><i>boolean</i>. Insert annotations in comments [default false]</li> 114b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:omit-annotation"><b>-o</b> <b>--omit-annotation=</b><i>string</i>. Omit given annotation</li> 115b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:nowarn"><b>--nowarn=</b><i>boolean</i>. Suppress warnings about disallowed insertions [default false]</li> 116b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:convert-jaifs"><b>--convert-jaifs=</b><i>boolean</i>. Convert JAIFs to new format [default false]</li> 117b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:help"><b>-h</b> <b>--help=</b><i>boolean</i>. Print usage information and exit [default false]</li> 118b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </ul> 119b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </li> 120b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="optiongroup:Debugging-options">Debugging options 121b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <ul> 122b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:verbose"><b>-v</b> <b>--verbose=</b><i>boolean</i>. Verbose (print progress information) [default false]</li> 123b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:debug"><b>--debug=</b><i>boolean</i>. Debug (print debug information) [default false]</li> 124b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <li id="option:print-error-stack"><b>--print-error-stack=</b><i>boolean</i>. Print error stack [default false]</li> 125b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </ul> 126b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </li> 127b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * </ul> 128b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst * <!-- end options doc --> 12910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 13010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipublic class Main { 13110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 13210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** Directory in which output files are written. */ 133b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst @OptionGroup("General options") 13410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-d <directory> Directory in which output files are written") 13510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static String outdir = "annotated/"; 13610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 137fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst /** 138fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * If true, overwrite original source files (making a backup first). 139fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * Furthermore, if the backup files already exist, they are used instead 140fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * of the .java files. This behavior permits a user to tweak the .jaif 141fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * file and re-run the annotator. 142fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * <p> 143fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * 144fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * Note that if the user runs the annotator with --in-place, makes edits, 145fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * and then re-runs the annotator with this --in-place option, those 146fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * edits are lost. Similarly, if the user runs the annotator twice in a 147fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * row with --in-place, only the last set of annotations will appear in 148fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * the codebase at the end. 149fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * <p> 150fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * 151fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * To preserve changes when using the --in-place option, first remove the 152fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * backup files. Or, use the <tt>-d .</tt> option, which makes (and 153fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst * reads) no backup, instead of --in-place. 154fd37e8455f846ac7d34c53ebe1079797599ebd4fMichael Ernst */ 155f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst @Option("-i Overwrite original source files") 156f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst public static boolean in_place = false; 157f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 15810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-a Abbreviate annotation names") 15910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean abbreviate = true; 16010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 16110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-c Insert annotations in comments") 16210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean comments = false; 16310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 164bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst @Option("-o Omit given annotation") 165bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst public static String omit_annotation; 166bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst 1677a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst @Option("Suppress warnings about disallowed insertions") 1687a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst public static boolean nowarn; 1697a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst 17040cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown // Instead of doing insertions, create new JAIFs using AST paths 17140cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown // extracted from existing JAIFs and source files they match 17240cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown @Option("Convert JAIFs to AST Path format") 1737a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst public static boolean convert_jaifs = false; 1747a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst 17538326fd68e58af05a0368708acf0099d4c3d0ac1Michael Ernst @Option("-h Print usage information and exit") 17638326fd68e58af05a0368708acf0099d4c3d0ac1Michael Ernst public static boolean help = false; 17738326fd68e58af05a0368708acf0099d4c3d0ac1Michael Ernst 1787a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst // Debugging options go below here. 1797a0f6324bbb31fa634fd61309ea23011a466ea2bMichael Ernst 180b890e553cf7b1ab5befaecd852618835aa451c3fMichael Ernst @OptionGroup("Debugging options") 18110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("-v Verbose (print progress information)") 18210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean verbose; 18310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 18410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Option("Debug (print debug information)") 18510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public static boolean debug = false; 18610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 1878b8c76e4860528031809204af427c71f6ee81fc2Eric Spishak @Option("Print error stack") 1888b8c76e4860528031809204af427c71f6ee81fc2Eric Spishak public static boolean print_error_stack = false; 1898b8c76e4860528031809204af427c71f6ee81fc2Eric Spishak 19004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown private static ElementVisitor<Void, AElement> classFilter = 19104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown new ElementVisitor<Void, AElement>() { 19204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown <K, V extends AElement> 19304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Void filter(VivifyingMap<K, V> vm0, VivifyingMap<K, V> vm1) { 19404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<K, V> entry : vm0.entrySet()) { 19504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry.getValue().accept(this, vm1.vivify(entry.getKey())); 19604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 19704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 19804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 19904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 20004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 20104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitAnnotationDef(AnnotationDef def, AElement el) { 20204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // not used, since package declarations not handled here 20304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 20404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 20504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 20604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 20704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitBlock(ABlock el0, AElement el) { 20804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ABlock el1 = (ABlock) el; 20904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.locals, el1.locals); 21004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitExpression(el0, el); 21104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 21204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 21304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 21404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitClass(AClass el0, AElement el) { 21504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AClass el1 = (AClass) el; 21604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.methods, el1.methods); 21704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.fields, el1.fields); 21804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.fieldInits, el1.fieldInits); 21904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.staticInits, el1.staticInits); 22004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.instanceInits, el1.instanceInits); 22104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitDeclaration(el0, el); 22204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 22304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 22404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 22504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitDeclaration(ADeclaration el0, AElement el) { 22604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ADeclaration el1 = (ADeclaration) el; 22704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown VivifyingMap<ASTPath, ATypeElement> insertAnnotations = 22804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el1.insertAnnotations; 22904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown VivifyingMap<ASTPath, ATypeElementWithType> insertTypecasts = 23004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el1.insertTypecasts; 23104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<ASTPath, ATypeElement> entry : 23204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.insertAnnotations.entrySet()) { 23304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p = entry.getKey(); 23404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElement e = entry.getValue(); 23504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertAnnotations.put(p, e); 23652e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst // visitTypeElement(e, insertAnnotations.vivify(p)); 23704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 23804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<ASTPath, ATypeElementWithType> entry : 23904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.insertTypecasts.entrySet()) { 24004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p = entry.getKey(); 24104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElementWithType e = entry.getValue(); 24204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown type.Type type = e.getType(); 24304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (type instanceof type.DeclaredType 24404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown && ((type.DeclaredType) type).getName().isEmpty()) { 24504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertAnnotations.put(p, e); 24652e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst // visitTypeElement(e, insertAnnotations.vivify(p)); 24704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } else { 24804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertTypecasts.put(p, e); 24952e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst // visitTypeElementWithType(e, insertTypecasts.vivify(p)); 25004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 25104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 25204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 25304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 25404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 25504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 25604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitExpression(AExpression el0, AElement el) { 25704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AExpression el1 = (AExpression) el; 25804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.typecasts, el1.typecasts); 25904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.instanceofs, el1.instanceofs); 26004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.news, el1.news); 26104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 26204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 26304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 26404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 26504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitField(AField el0, AElement el) { 26604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitDeclaration(el0, el); 26704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 26804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 26904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 27004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitMethod(AMethod el0, AElement el) { 27104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AMethod el1 = (AMethod) el; 27204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.bounds, el1.bounds); 27304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.parameters, el1.parameters); 27404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.throwsException, el1.throwsException); 27504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.returnType.accept(this, el1.returnType); 27604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.receiver.accept(this, el1.receiver); 27704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el0.body.accept(this, el1.body); 27804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitDeclaration(el0, el); 27904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 28004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 28104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 28204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitTypeElement(ATypeElement el0, AElement el) { 28304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElement el1 = (ATypeElement) el; 28404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filter(el0.innerTypes, el1.innerTypes); 28504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 28604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 28704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 28804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 28904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitTypeElementWithType(ATypeElementWithType el0, 29004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AElement el) { 29104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ATypeElementWithType el1 = (ATypeElementWithType) el; 29204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown el1.setType(el0.getType()); 29304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return visitTypeElement(el0, el); 29404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 29504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 29604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 29704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public Void visitElement(AElement el, AElement arg) { 29804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return null; 29904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 30004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown }; 30104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 30204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown private static AScene filteredScene(final AScene scene) { 30304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown final AScene filtered = new AScene(); 30404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filtered.packages.putAll(scene.packages); 30504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filtered.imports.putAll(scene.imports); 30604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<String, AClass> entry : scene.classes.entrySet()) { 30704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown String key = entry.getKey(); 30804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AClass clazz0 = entry.getValue(); 30904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AClass clazz1 = filtered.classes.vivify(key); 31004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown clazz0.accept(classFilter, clazz1); 31104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 31204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown filtered.prune(); 31304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return filtered; 31404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 31504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 31604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown private static ATypeElement findInnerTypeElement(Tree t, 317d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown ASTRecord rec, ADeclaration decl, Type type, Insertion ins) { 31804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath astPath = rec.astPath; 31904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown GenericArrayLocationCriterion galc = 32004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ins.getCriteria().getGenericArrayLocation(); 32104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown assert astPath != null && galc != null; 32204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown List<TypePathEntry> tpes = galc.getLocation(); 32304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.ASTEntry entry; 32404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (TypePathEntry tpe : tpes) { 32504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown switch (tpe.tag) { 32604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case ARRAY: 32704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (!astPath.isEmpty()) { 32804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = astPath.get(-1); 32904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (entry.getTreeKind() == Tree.Kind.NEW_ARRAY 33004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown && entry.childSelectorIs(ASTPath.TYPE)) { 33104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.NEW_ARRAY, 33204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.TYPE, entry.getArgument() + 1); 33304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 33404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 33504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 33604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.ARRAY_TYPE, 33704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.TYPE); 33804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 33904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case INNER_TYPE: 34004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.MEMBER_SELECT, 34104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.EXPRESSION); 34204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 34304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case TYPE_ARGUMENT: 34404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.PARAMETERIZED_TYPE, 34504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.TYPE_ARGUMENT, tpe.arg); 34604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 34704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown case WILDCARD: 34804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown entry = new ASTPath.ASTEntry(Tree.Kind.UNBOUNDED_WILDCARD, 34904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath.BOUND); 35004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown break; 35104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown default: 35204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown throw new IllegalArgumentException("unknown type tag " + tpe.tag); 35304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 354d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown astPath = astPath.extend(entry); 35504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 35604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 35704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return decl.insertAnnotations.vivify(astPath); 35804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 35904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 3602a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown private static void convertInsertion(String pkg, 3612a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCCompilationUnit tree, ASTRecord rec, Insertion ins, 3622a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AScene scene, Multimap<Insertion, Annotation> insertionSources) { 3632a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Collection<Annotation> annos = insertionSources.get(ins); 3642a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec == null) { 3652a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ins.getCriteria().isOnPackage()) { 3662a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Annotation anno : annos) { 3672a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown scene.packages.get(pkg).tlAnnotationsHere.add(anno); 3682a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3692a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3702a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else if (scene != null && rec.className != null) { 3712a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AClass clazz = scene.classes.vivify(rec.className); 3722a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ADeclaration decl = null; // insertion target 3732a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ins.getCriteria().onBoundZero()) { 3742a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int n = rec.astPath.size(); 3752a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (!rec.astPath.get(n-1).childSelectorIs(ASTPath.BOUND)) { 3762a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ASTPath astPath = ASTPath.empty(); 3772a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (int i = 0; i < n; i++) { 3782a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown astPath = astPath.extend(rec.astPath.get(i)); 3792a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3802a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown astPath = astPath.extend( 3812a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown new ASTPath.ASTEntry(Tree.Kind.TYPE_PARAMETER, 3822a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ASTPath.BOUND, 0)); 3832a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown rec = rec.replacePath(astPath); 3842a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3852a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 3862a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec.methodName == null) { 3872a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = rec.varName == null ? clazz 3882a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown : clazz.fields.vivify(rec.varName); 3892a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else { 3902a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AMethod meth = clazz.methods.vivify(rec.methodName); 3912a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec.varName == null) { 3922a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = meth; // ? 3932a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else { 3942a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown try { 3952a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int i = Integer.parseInt(rec.varName); 3962a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = i < 0 ? meth.receiver 3972a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown : meth.parameters.vivify(i); 3982a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } catch (NumberFormatException e) { 3992a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown TreePath path = ASTIndex.getTreePath(tree, rec); 4002a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCVariableDecl varTree = null; 4012a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCMethodDecl methTree = null; 4022a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown JCTree.JCClassDecl classTree = null; 4032a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown loop: 4042a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown while (path != null) { 4052a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree leaf = path.getLeaf(); 4062a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown switch (leaf.getKind()) { 4072a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case VARIABLE: 4082a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown varTree = (JCTree.JCVariableDecl) leaf; 4092a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4102a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case METHOD: 4112a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown methTree = (JCTree.JCMethodDecl) leaf; 4122a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4132a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case ANNOTATION: 4142a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case CLASS: 4152a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case ENUM: 4162a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown case INTERFACE: 4172a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break loop; 4182a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown default: 4192a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown path = path.getParentPath(); 4202a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4212a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4222a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown while (path != null) { 4232a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree leaf = path.getLeaf(); 4242a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree.Kind kind = leaf.getKind(); 4252a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (kind == Tree.Kind.METHOD) { 4262a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown methTree = (JCTree.JCMethodDecl) leaf; 4272a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int i = LocalVariableScanner.indexOfVarTree(path, 4282a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown varTree, rec.varName); 4292a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int m = methTree.getStartPosition(); 4302a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int a = varTree.getStartPosition(); 4312a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown int b = varTree.getEndPosition(tree.endPositions); 4322a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown LocalLocation loc = new LocalLocation(i, a-m, b-a); 4332a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl = meth.body.locals.vivify(loc); 4342a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4352a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4362a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ASTPath.isClassEquiv(kind)) { 4372a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown classTree = (JCTree.JCClassDecl) leaf; 4382a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown // ??? 4392a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown break; 4402a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4412a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown path = path.getParentPath(); 4422a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4432a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4442a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4452a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4462a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (decl != null) { 4472a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown AElement el; 4482a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (rec.astPath.isEmpty()) { 4492a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el = decl; 4502a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else if (ins.getKind() == Insertion.Kind.CAST) { 4512a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown annotations.el.ATypeElementWithType elem = 4522a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown decl.insertTypecasts.vivify(rec.astPath); 4532a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown elem.setType(((CastInsertion) ins).getType()); 4542a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el = elem; 4552a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } else { 4562a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el = decl.insertAnnotations.vivify(rec.astPath); 4572a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4582a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Annotation anno : annos) { 4592a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown el.tlAnnotationsHere.add(anno); 4602a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4612a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (ins instanceof TypedInsertion) { 4622a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown TypedInsertion ti = (TypedInsertion) ins; 4632a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (!rec.astPath.isEmpty()) { 46452e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst // addInnerTypePaths(decl, rec, ti, insertionSources); 4652a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4662a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Insertion inner : ti.getInnerTypeInsertions()) { 4672a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown Tree t = ASTIndex.getNode(tree, rec); 4682a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown if (t != null) { 4692a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown ATypeElement elem = findInnerTypeElement(t, 4702a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown rec, decl, ti.getType(), inner); 4712a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown for (Annotation a : insertionSources.get(inner)) { 4722a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown elem.tlAnnotationsHere.add(a); 4732a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4742a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4752a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4762a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4772a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4782a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4792a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown } 4802a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown 4812a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown 48210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Implementation details: 48310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // 1. The annotator partially compiles source 48410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // files using the compiler API (JSR-199), obtaining an AST. 48510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // 2. The annotator reads the specification file, producing a set of 48610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // annotator.find.Insertions. Insertions completely specify what to 48710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // write (as a String, which is ultimately translated according to the 48810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // keyword file) and how to write it (as annotator.find.Criteria). 48910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // 3. It then traverses the tree, looking for nodes that satisfy the 49010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Insertion Criteria, translating the Insertion text against the 49110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // keyword file, and inserting the annotations into the source file. 49210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 49310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 49410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Runs the annotator, parsing the source and spec files and applying 49510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * the annotations. 49610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 497de7d64fbe7b6eb28b7ec1a2393b91b8e9c6afea6Dan Brown public static void main(String[] args) throws IOException { 49810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 49910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (verbose) { 50067693622be4bed63a07df6f0ce34f7c8bd52baf5Michael Ernst System.out.printf("insert-annotations-to-source (%s)", 50167693622be4bed63a07df6f0ce34f7c8bd52baf5Michael Ernst annotations.io.classfile.ClassFileReader.INDEX_UTILS_VERSION); 50210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 50310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 504e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown Options options = new Options( 505a60ebb590bc5ff3836cc4afd1b85bd930fe72a44Michael Ernst "Main [options] { jaif-file | java-file | @arg-file } ...\n" 506e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown + "(Contents of argfiles are expanded into the argument list.)", 507e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown Main.class); 5080ab9de82370c7e2890fd532eca754342a962b452Dan Brown String[] file_args; 509de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown try { 510de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown String[] cl_args = CommandLine.parse(args); 511de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown file_args = options.parse_or_usage(cl_args); 512de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown } catch (IOException ex) { 513de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.err.println(ex); 514e9c1bfc69b183232d9bb18e0b5614a42a5b7219bDan Brown System.err.println("(For non-argfile beginning with \"@\", use \"@@\" for initial \"@\"."); 515de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.err.println("Alternative for filenames: indicate directory, e.g. as './@file'."); 516de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.err.println("Alternative for flags: use '=', as in '-o=@Deprecated'.)"); 5170ab9de82370c7e2890fd532eca754342a962b452Dan Brown file_args = null; // Eclipse compiler issue workaround 518de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown System.exit(1); 519de19fb4316549d574979acfedac7fe9fa4892f6dDan Brown } 520f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 5218819fd6c8f50083311182795717e23e88cd04ac5Dan Brown DebugWriter dbug = new DebugWriter(); 5228819fd6c8f50083311182795717e23e88cd04ac5Dan Brown DebugWriter verb = new DebugWriter(); 5238819fd6c8f50083311182795717e23e88cd04ac5Dan Brown DebugWriter both = dbug.or(verb); 5248819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.setEnabled(debug); 5258819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.setEnabled(verbose); 5269849f43e0d770ee036b568dbba96d4e6a2a2b270Dan Brown TreeFinder.warn.setEnabled(!nowarn); 5278819fd6c8f50083311182795717e23e88cd04ac5Dan Brown TreeFinder.stak.setEnabled(print_error_stack); 5288819fd6c8f50083311182795717e23e88cd04ac5Dan Brown TreeFinder.dbug.setEnabled(debug); 5298819fd6c8f50083311182795717e23e88cd04ac5Dan Brown Criteria.dbug.setEnabled(debug); 5301220f0e5dd7642f90aab557b3bda8e177ce06316Michael Ernst 53110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (help) { 53210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali options.print_usage(); 53310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(0); 53410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 53510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 536f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (in_place && outdir != "annotated/") { // interned 537f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst options.print_usage("The --outdir and --in-place options are mutually exclusive."); 538f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst System.exit(1); 539f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 540f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 54110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (file_args.length < 2) { 542f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst options.print_usage("Supplied %d arguments, at least 2 needed%n", file_args.length); 54310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(1); 54410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 54510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 54610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // The insertions specified by the annotation files. 547290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown Insertions insertions = new Insertions(); 54810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // The Java files into which to insert. 54910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali List<String> javafiles = new ArrayList<String>(); 550d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown 5514ae81f26445bc9397bd3e1edb062e0388ed82a6fMichael Ernst // Indices to maintain insertion source traces. 55204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Map<String, Multimap<Insertion, Annotation>> insertionIndex = 55304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown new HashMap<String, Multimap<Insertion, Annotation>>(); 55404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Map<Insertion, String> insertionOrigins = new HashMap<Insertion, String>(); 55504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Map<String, AScene> scenes = new HashMap<String, AScene>(); 556e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown 557e4003a2bdd8f2634d19cdac8875a10979f87a0e4Dan Brown IndexFileParser.setAbbreviate(abbreviate); 55810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (String arg : file_args) { 55910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (arg.endsWith(".java")) { 56010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali javafiles.add(arg); 5618ef7819881d25642b26b60a274f9c148d4356e3dWerner Dietl } else if (arg.endsWith(".jaif") || 5628ef7819881d25642b26b60a274f9c148d4356e3dWerner Dietl arg.endsWith(".jann")) { 56304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown IndexFileSpecification spec = new IndexFileSpecification(arg); 56410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali try { 56510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali List<Insertion> parsedSpec = spec.parse(); 56604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AScene scene = spec.getScene(); 56770918686c71c2030c56e623a9427f05b99338a5eDan Brown Collections.sort(parsedSpec, new Comparator<Insertion>() { 56804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown @Override 56904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown public int compare(Insertion i1, Insertion i2) { 57004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p1 = i1.getCriteria().getASTPath(); 57104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ASTPath p2 = i2.getCriteria().getASTPath(); 57204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return p1 == null 57304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown ? p2 == null ? 0 : -1 57404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown : p2 == null ? 1 : p1.compareTo(p2); 57504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 57604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown }); 57740cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown if (convert_jaifs) { 5789967de5fe4b0240e9b5169020aec35fb29cdfb83Dan Brown scenes.put(arg, filteredScene(scene)); 57940cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown for (Insertion ins : parsedSpec) { 58040cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown insertionOrigins.put(ins, arg); 58140cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown } 58240cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown if (!insertionIndex.containsKey(arg)) { 58340cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown insertionIndex.put(arg, 58440cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown LinkedHashMultimap.<Insertion, Annotation>create()); 58540cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown } 58640cd3d4a3b8ae6bd0fe22063def2914f8645a451Dan Brown insertionIndex.get(arg).putAll(spec.insertionSources()); 58704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 5888819fd6c8f50083311182795717e23e88cd04ac5Dan Brown both.debug("Read %d annotations from %s%n", parsedSpec.size(), arg); 589bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst if (omit_annotation != null) { 5908819fd6c8f50083311182795717e23e88cd04ac5Dan Brown List<Insertion> filtered = 5918819fd6c8f50083311182795717e23e88cd04ac5Dan Brown new ArrayList<Insertion>(parsedSpec.size()); 592bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst for (Insertion insertion : parsedSpec) { 5932441c4b66f26bf96ea7a8749645a933aa09a2d62Eric Spishak // TODO: this won't omit annotations if the insertion is more than 5942441c4b66f26bf96ea7a8749645a933aa09a2d62Eric Spishak // just the annotation (such as if the insertion is a cast 5952441c4b66f26bf96ea7a8749645a933aa09a2d62Eric Spishak // insertion or a 'this' parameter in a method declaration). 596bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst if (! omit_annotation.equals(insertion.getText())) { 597bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst filtered.add(insertion); 598bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst } 599bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst } 600bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst parsedSpec = filtered; 6018819fd6c8f50083311182795717e23e88cd04ac5Dan Brown both.debug("After filtering: %d annotations from %s%n", 6028819fd6c8f50083311182795717e23e88cd04ac5Dan Brown parsedSpec.size(), arg); 603bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst } 604bbda219dcbd366aaf1786384a8171e0409fd5a11Michael Ernst insertions.addAll(parsedSpec); 6052c4067b440b23911687e4a353584b088eccf17fbMichael Ernst } catch (RuntimeException e) { 6062c4067b440b23911687e4a353584b088eccf17fbMichael Ernst if (e.getCause() != null 6072c4067b440b23911687e4a353584b088eccf17fbMichael Ernst && e.getCause() instanceof FileNotFoundException) { 6082c4067b440b23911687e4a353584b088eccf17fbMichael Ernst System.err.println("File not found: " + arg); 6092c4067b440b23911687e4a353584b088eccf17fbMichael Ernst System.exit(1); 6102c4067b440b23911687e4a353584b088eccf17fbMichael Ernst } else { 6112c4067b440b23911687e4a353584b088eccf17fbMichael Ernst throw e; 6122c4067b440b23911687e4a353584b088eccf17fbMichael Ernst } 61310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } catch (FileIOException e) { 614bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak // Add 1 to the line number since line numbers in text editors are usually one-based. 615bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak System.err.println("Error while parsing annotation file " + arg + " at line " 616bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak + (e.lineNumber + 1) + ":"); 61710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (e.getMessage() != null) { 618bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak System.err.println('\t' + e.getMessage()); 619bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak } 620bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak if (e.getCause() != null && e.getCause().getMessage() != null) { 621bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak System.err.println('\t' + e.getCause().getMessage()); 622bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak } 6238819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (print_error_stack) { 624bcf0e58623d43433c1c05a2fc954f69411b86759Eric Spishak e.printStackTrace(); 62510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 62610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(1); 62710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 62810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } else { 62910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali throw new Error("Unrecognized file extension: " + arg); 63010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 63110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 63210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 6338819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (dbug.isEnabled()) { 6348819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("%d insertions, %d .java files%n", 6358819fd6c8f50083311182795717e23e88cd04ac5Dan Brown insertions.size(), javafiles.size()); 6368819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("Insertions:%n"); 63710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (Insertion insertion : insertions) { 6388819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug(" %s%n", insertion); 63910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 64010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 64110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 64210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (String javafilename : javafiles) { 6438819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.debug("Processing %s%n", javafilename); 64410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 645f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst File javafile = new File(javafilename); 646f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst File unannotated = new File(javafilename + ".unannotated"); 647f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (in_place) { 648f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // It doesn't make sense to check timestamps; 649f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // if the .java.unannotated file exists, then just use it. 650f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // A user can rename that file back to just .java to cause the 651f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst // .java file to be read. 652f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (unannotated.exists()) { 6538819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.debug("Renaming %s to %s%n", unannotated, javafile); 654f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst boolean success = unannotated.renameTo(javafile); 655f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (! success) { 656f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst throw new Error(String.format("Failed renaming %s to %s", 657f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst unannotated, javafile)); 658f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 659f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 660f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 661f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst 66276f3628361358abc328f92c107a7e11733dad1d7Dan Brown String fileSep = System.getProperty("file.separator"); 66310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali String fileLineSep = System.getProperty("line.separator"); 66410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali Source src; 66510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Get the source file, and use it to obtain parse trees. 66610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali try { 66710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // fileLineSep is set here so that exceptions can be caught 66810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali fileLineSep = UtilMDE.inferLineSeparator(javafilename); 66910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali src = new Source(javafilename); 6708819fd6c8f50083311182795717e23e88cd04ac5Dan Brown verb.debug("Parsed %s%n", javafilename); 67104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } catch (Source.CompilerException e) { 67210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali e.printStackTrace(); 67310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return; 67410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } catch (IOException e) { 67510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali e.printStackTrace(); 67610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return; 67710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 67810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 679c31338b45a78642c9b21cce154949870ea826abbDan Brown // Imports required to resolve annotations (when abbreviate==true). 680c31338b45a78642c9b21cce154949870ea826abbDan Brown LinkedHashSet<String> imports = new LinkedHashSet<String>(); 681c15d52e959f2b3052978e40552159de77c403428Michael Ernst int num_insertions = 0; 68276f3628361358abc328f92c107a7e11733dad1d7Dan Brown String pkg = ""; 683c15d52e959f2b3052978e40552159de77c403428Michael Ernst 684b7158c74813fa9eed49afea2189aee0cf51cfb73Dan Brown for (CompilationUnitTree cut : src.parse()) { 685b7158c74813fa9eed49afea2189aee0cf51cfb73Dan Brown JCTree.JCCompilationUnit tree = (JCTree.JCCompilationUnit) cut; 68676f3628361358abc328f92c107a7e11733dad1d7Dan Brown ExpressionTree pkgExp = cut.getPackageName(); 68776f3628361358abc328f92c107a7e11733dad1d7Dan Brown pkg = pkgExp == null ? "" : pkgExp.toString(); 68810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 68910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Create a finder, and use it to get positions. 69010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali TreeFinder finder = new TreeFinder(tree); 69152dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown SetMultimap<Pair<Integer, ASTPath>, Insertion> positions = 6928819fd6c8f50083311182795717e23e88cd04ac5Dan Brown finder.getPositions(tree, insertions); 69310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 69404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (convert_jaifs) { 69504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // program used only for JAIF conversion; execute following 6964ae81f26445bc9397bd3e1edb062e0388ed82a6fMichael Ernst // block and then skip remainder of loop 697d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown Multimap<ASTRecord, Insertion> astInsertions = 69804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown finder.getPaths(); 699d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown for (Map.Entry<ASTRecord, Collection<Insertion>> entry : 70004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown astInsertions.asMap().entrySet()) { 701d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown ASTRecord rec = entry.getKey(); 70204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Insertion ins : entry.getValue()) { 70304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (ins.getCriteria().getASTPath() != null) { continue; } 70404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown String arg = insertionOrigins.get(ins); 70504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AScene scene = scenes.get(arg); 70604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Multimap<Insertion, Annotation> insertionSources = 70704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown insertionIndex.get(arg); 70852e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst // String text = 70904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // ins.getText(comments, abbreviate, false, 0, '\0'); 71004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 71104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown // TODO: adjust for missing end of path (?) 71204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 71304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (insertionSources.containsKey(ins)) { 7142a5d572aa18c2cfeab9f706eb8796ec1553a6c46Dan Brown convertInsertion(pkg, tree, rec, ins, scene, insertionSources); 71504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 71604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 71704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 71804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown continue; 71904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 72004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 72110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Apply the positions to the source file. 7228819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (both.isEnabled()) { 7238819fd6c8f50083311182795717e23e88cd04ac5Dan Brown System.err.printf( 7248819fd6c8f50083311182795717e23e88cd04ac5Dan Brown "getPositions returned %d positions in tree for %s%n", 7258819fd6c8f50083311182795717e23e88cd04ac5Dan Brown positions.size(), javafilename); 72610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 72710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 72852dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Set<Pair<Integer, ASTPath>> positionKeysUnsorted = 72952dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown positions.keySet(); 73052dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Set<Pair<Integer, ASTPath>> positionKeysSorted = 73152dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown new TreeSet<Pair<Integer, ASTPath>>( 73252dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown new Comparator<Pair<Integer, ASTPath>>() { 73352dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown @Override 73452dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown public int compare(Pair<Integer, ASTPath> p1, 73552dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Pair<Integer, ASTPath> p2) { 73652dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown int c = Integer.compare(p2.a, p1.a); 73752dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown if (c == 0) { 73852dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown c = p2.b == null ? p1.b == null ? 0 : -1 73952dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown : p1.b == null ? 1 : p2.b.compareTo(p1.b); 74052dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown } 74152dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown return c; 74252dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown } 74352dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown }); 74457ea23519ad96aca616e5fe41b4a1db896b91096Michael Ernst positionKeysSorted.addAll(positionKeysUnsorted); 74552dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown for (Pair<Integer, ASTPath> pair : positionKeysSorted) { 746c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown boolean receiverInserted = false; 74784a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown boolean newInserted = false; 7480b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown boolean constructorInserted = false; 74952dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown Set<String> seen = new TreeSet<String>(); 75052dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown List<Insertion> toInsertList = new ArrayList<Insertion>(positions.get(pair)); 751ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst Collections.reverse(toInsertList); 752553a9a9a17ce582f701841b59edfadb491ed54adDan Brown dbug.debug("insertion pos: %d%n", pair.a); 753553a9a9a17ce582f701841b59edfadb491ed54adDan Brown assert pair.a >= 0 754553a9a9a17ce582f701841b59edfadb491ed54adDan Brown : "pos is negative: " + pair.a + " " + toInsertList.get(0) + " " + javafilename; 755ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst for (Insertion iToInsert : toInsertList) { 756ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // Possibly add whitespace after the insertion 7573d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak String trailingWhitespace = ""; 758ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst boolean gotSeparateLine = false; 759553a9a9a17ce582f701841b59edfadb491ed54adDan Brown int pos = pair.a; // reset each iteration in case of dyn adjustment 760ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst if (iToInsert.getSeparateLine()) { 761a1b0d6cb20867adf4fad0359336510469353ad29Michael Ernst // System.out.printf("getSeparateLine=true for insertion at pos %d: %s%n", pos, iToInsert); 762ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst int indentation = 0; 763ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst while ((pos - indentation != 0) 764ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // horizontal whitespace 765ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst && (src.charAt(pos-indentation-1) == ' ' 766ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || src.charAt(pos-indentation-1) == '\t')) { 767a1b0d6cb20867adf4fad0359336510469353ad29Michael Ernst // System.out.printf("src.charAt(pos-indentation-1 == %d-%d-1)='%s'%n", 768a1b0d6cb20867adf4fad0359336510469353ad29Michael Ernst // pos, indentation, src.charAt(pos-indentation-1)); 769ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst indentation++; 770ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst } 771ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst if ((pos - indentation == 0) 772ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // horizontal whitespace 773ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || (src.charAt(pos-indentation-1) == '\f' 774ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || src.charAt(pos-indentation-1) == '\n' 775ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || src.charAt(pos-indentation-1) == '\r')) { 7763d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak trailingWhitespace = fileLineSep + src.substring(pos-indentation, pos); 777ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst gotSeparateLine = true; 778ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst } 779ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst } 780c71d4e21017f8f4412a2d399676e358858999623Michael Ernst 7813d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak char precedingChar; 7823d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak if (pos != 0) { 7833d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak precedingChar = src.charAt(pos - 1); 7843d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak } else { 7853d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak precedingChar = '\0'; 7863d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak } 787afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown 788afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown if (iToInsert.getKind() == Insertion.Kind.ANNOTATION) { 789afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown AnnotationInsertion ai = (AnnotationInsertion) iToInsert; 790dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown if (ai.isGenerateBound()) { // avoid multiple ampersands 791dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown try { 792dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown String s = src.substring(pos, pos+9); 793dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown if ("Object & ".equals(s)) { 794dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown ai.setGenerateBound(false); 795dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown precedingChar = '.'; // suppress leading space 796dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown } 797dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown } catch (StringIndexOutOfBoundsException e) {} 798dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown } 799afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown if (ai.isGenerateExtends()) { // avoid multiple "extends" 800afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown try { 801dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown String s = src.substring(pos, pos+9); 802dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown if (" extends ".equals(s)) { 803afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown ai.setGenerateExtends(false); 804553a9a9a17ce582f701841b59edfadb491ed54adDan Brown pos += 8; 805afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } 806afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } catch (StringIndexOutOfBoundsException e) {} 807afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } 808afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } else if (iToInsert.getKind() == Insertion.Kind.CAST) { 8095491118a39a8545a38eb1a94bbc5f5a00a0b9beeDan Brown ((CastInsertion) iToInsert) 8105491118a39a8545a38eb1a94bbc5f5a00a0b9beeDan Brown .setOnArrayLiteral(src.charAt(pos) == '{'); 811afbac03e4be6a7c9f2e45998b56f9f0e6ae58c17Dan Brown } else if (iToInsert.getKind() == Insertion.Kind.RECEIVER) { 812c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown ReceiverInsertion ri = (ReceiverInsertion) iToInsert; 813c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown ri.setAnnotationsOnly(receiverInserted); 814c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown receiverInserted = true; 81584a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown } else if (iToInsert.getKind() == Insertion.Kind.NEW) { 81684a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown NewInsertion ni = (NewInsertion) iToInsert; 81784a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown ni.setAnnotationsOnly(newInserted); 81884a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown newInserted = true; 8190b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown } else if (iToInsert.getKind() == Insertion.Kind.CONSTRUCTOR) { 8200b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown ConstructorInsertion ci = (ConstructorInsertion) iToInsert; 8210b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown if (constructorInserted) { ci.setAnnotationsOnly(true); } 8220b2301392682d3b2cbaa314cf5f90b960c6f0253Dan Brown constructorInserted = true; 823c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown } 824c448ebefd28e4a67c0c4957ee387f02ab9020502Dan Brown 8253d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak String toInsert = iToInsert.getText(comments, abbreviate, 8268819fd6c8f50083311182795717e23e88cd04ac5Dan Brown gotSeparateLine, pos, precedingChar) + trailingWhitespace; 82752dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown if (seen.contains(toInsert)) { continue; } // eliminate duplicates 82852dda95b775d6ad255fb35f2582be363ab1ce4d2Dan Brown seen.add(toInsert); 829ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst 830ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // If it's already there, don't re-insert. This is a hack! 831ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst // Also, I think this is already checked when constructing the 83276be24f6310e0f8e8120e223e14bc0b4690408d4Werner Dietl // insertions. 833ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst int precedingTextPos = pos-toInsert.length()-1; 834ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst if (precedingTextPos >= 0) { 835ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst String precedingTextPlusChar 836ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst = src.getString().substring(precedingTextPos, pos); 8378819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (toInsert.equals( 8388819fd6c8f50083311182795717e23e88cd04ac5Dan Brown precedingTextPlusChar.substring(0, toInsert.length())) 839ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst || toInsert.equals(precedingTextPlusChar.substring(1))) { 8408819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug( 8418819fd6c8f50083311182795717e23e88cd04ac5Dan Brown "Inserting %s at %d in code of length %d with preceding text '%s'%n", 8428819fd6c8f50083311182795717e23e88cd04ac5Dan Brown toInsert, pos, src.getString().length(), 8438819fd6c8f50083311182795717e23e88cd04ac5Dan Brown precedingTextPlusChar); 8448819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("Already present, skipping%n"); 845ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst continue; 8464735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst } 84710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 8483d8c27ef3f539aea5f49643fed2b38e49e99eda4Eric Spishak 84984a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown // TODO: Neither the above hack nor this check should be 85084a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown // necessary. Find out why re-insertions still occur and 85184a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown // fix properly. 85284a43e620e89518fa2b0909bb51eb46c455bfd1fDan Brown if (iToInsert.getInserted()) { continue; } 853ed468b7eb950854ef28a3407e1887dfec12fee67Michael Ernst src.insert(pos, toInsert); 8548920570aa95ef0072bafd2cccff03d194c478bf1Dan Brown if (verbose && !debug) { 855c15d52e959f2b3052978e40552159de77c403428Michael Ernst System.out.print("."); 856c15d52e959f2b3052978e40552159de77c403428Michael Ernst num_insertions++; 857c15d52e959f2b3052978e40552159de77c403428Michael Ernst if ((num_insertions % 50) == 0) { 858c15d52e959f2b3052978e40552159de77c403428Michael Ernst System.out.println(); // terminate the line that contains dots 859c15d52e959f2b3052978e40552159de77c403428Michael Ernst } 860c15d52e959f2b3052978e40552159de77c403428Michael Ernst } 8618819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("Post-insertion source: %n" + src.getString()); 862c31338b45a78642c9b21cce154949870ea826abbDan Brown 863c31338b45a78642c9b21cce154949870ea826abbDan Brown Set<String> packageNames = iToInsert.getPackageNames(); 864c31338b45a78642c9b21cce154949870ea826abbDan Brown if (!packageNames.isEmpty()) { 865c31338b45a78642c9b21cce154949870ea826abbDan Brown dbug.debug("Need import %s%n due to insertion %s%n", 866c31338b45a78642c9b21cce154949870ea826abbDan Brown packageNames, toInsert); 867c31338b45a78642c9b21cce154949870ea826abbDan Brown imports.addAll(packageNames); 868c31338b45a78642c9b21cce154949870ea826abbDan Brown } 86910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 87010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 87110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 87204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 87304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (convert_jaifs) { 87404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (Map.Entry<String, AScene> entry : scenes.entrySet()) { 87504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown String filename = entry.getKey(); 87604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown AScene scene = entry.getValue(); 87704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown try { 87804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown IndexFileWriter.write(scene, filename + ".converted"); 87904cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } catch (DefException e) { 88004cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown System.err.println(filename + ": " + " format error in conversion"); 88104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown if (print_error_stack) { 88204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown e.printStackTrace(); 88304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 88404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 88504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 88604cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown return; // done with conversion 88704cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 88804cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 8898819fd6c8f50083311182795717e23e88cd04ac5Dan Brown if (dbug.isEnabled()) { 8908819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug("%d imports to insert%n", imports.size()); 89104cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown for (String classname : imports) { 8928819fd6c8f50083311182795717e23e88cd04ac5Dan Brown dbug.debug(" %s%n", classname); 89304cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 89404cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown } 89504cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown 89610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // insert import statements 89710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali { 89810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali Pattern importPattern = Pattern.compile("(?m)^import\\b"); 89910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali Pattern packagePattern = Pattern.compile("(?m)^package\\b.*;(\\n|\\r\\n?)"); 90010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali int importIndex = 0; // default: beginning of file 90110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali String srcString = src.getString(); 90204cf7f6206930db04e8a8c085bf18ba237b9dc05Dan Brown Matcher m = importPattern.matcher(srcString); 903059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown Set<String> inSource = new TreeSet<String>(); 90410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (m.find()) { 90510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali importIndex = m.start(); 906059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown do { 907059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown int i = m.start(); 908059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown int j = srcString.indexOf(System.lineSeparator(), i) + 1; 909059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown if (j <= 0) { 910059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown j = srcString.length(); 911059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown } 912059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown String s = srcString.substring(i, j); 913059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown inSource.add(s); 914059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown } while (m.find()); 91510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } else { 9168819fd6c8f50083311182795717e23e88cd04ac5Dan Brown // Debug.info("Didn't find import in " + srcString); 91710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali m = packagePattern.matcher(srcString); 91810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (m.find()) { 91910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali importIndex = m.end(); 92010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 92110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 92210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali for (String classname : imports) { 92310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali String toInsert = "import " + classname + ";" + fileLineSep; 924059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown if (!inSource.contains(toInsert)) { 925059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown inSource.add(toInsert); 926059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown src.insert(importIndex, toInsert); 927059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown importIndex += toInsert.length(); 928059a80f28ad2932bf2f9cdff444d6087d51d176fDan Brown } 92910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 93010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 93110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 93210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Write the source file. 93376f3628361358abc328f92c107a7e11733dad1d7Dan Brown File outfile = null; 93410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali try { 935f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (in_place) { 93676f3628361358abc328f92c107a7e11733dad1d7Dan Brown outfile = javafile; 937f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (verbose) { 938f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst System.out.printf("Renaming %s to %s%n", javafile, unannotated); 939f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 940f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst boolean success = javafile.renameTo(unannotated); 941f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (! success) { 942f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst throw new Error(String.format("Failed renaming %s to %s", 943f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst javafile, unannotated)); 944f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 945f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } else { 94676f3628361358abc328f92c107a7e11733dad1d7Dan Brown if (pkg.isEmpty()) { 94776f3628361358abc328f92c107a7e11733dad1d7Dan Brown outfile = new File(outdir, javafile.getName()); 94876f3628361358abc328f92c107a7e11733dad1d7Dan Brown } else { 94976f3628361358abc328f92c107a7e11733dad1d7Dan Brown String[] pkgPath = pkg.split("\\."); 95076f3628361358abc328f92c107a7e11733dad1d7Dan Brown StringBuilder sb = new StringBuilder(outdir); 95176f3628361358abc328f92c107a7e11733dad1d7Dan Brown for (int i = 0 ; i < pkgPath.length ; i++) { 95276f3628361358abc328f92c107a7e11733dad1d7Dan Brown sb.append(fileSep).append(pkgPath[i]); 95376f3628361358abc328f92c107a7e11733dad1d7Dan Brown } 95476f3628361358abc328f92c107a7e11733dad1d7Dan Brown outfile = new File(sb.toString(), javafile.getName()); 95576f3628361358abc328f92c107a7e11733dad1d7Dan Brown } 956f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst outfile.getParentFile().mkdirs(); 957f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 95810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali OutputStream output = new FileOutputStream(outfile); 959f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst if (verbose) { 960f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst System.out.printf("Writing %s%n", outfile); 961f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst } 96210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali src.write(output); 963f5fbd2ee90bc394cb18e8cf7dbaf3ecbbd4e7ad7Michael Ernst output.close(); 96410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } catch (IOException e) { 96510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.err.println("Problem while writing file " + outfile); 96610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali e.printStackTrace(); 96710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali System.exit(1); 96810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 96910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 97010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 97110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 9725534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst public static String pathToString(TreePath path) { 973f363307b8c8b78b369f6770b2d0b95eccf6754c9Michael Ernst if (path == null) { 9745534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return "null"; 975f363307b8c8b78b369f6770b2d0b95eccf6754c9Michael Ernst } 976f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst return treeToString(path.getLeaf()); 977f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst } 978f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst 979f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst public static String treeToString(Tree node) { 980f8955bfb5d46ff31634832d5143a95f2faaa14beMichael Ernst String asString = node.toString(); 9815534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst String oneLine = firstLine(asString); 9825534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return "\"" + oneLine + "\""; 9835534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 9845534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst 9855534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst /** 9865534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst * Return the first non-empty line of the string, adding an ellipsis 9875534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst * (...) if the string was truncated. 9885534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst */ 9895534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst public static String firstLine(String s) { 9905534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst while (s.startsWith("\n")) { 9915534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst s = s.substring(1); 9925534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 9935534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst int newlineIndex = s.indexOf('\n'); 9945534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst if (newlineIndex == -1) { 9955534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return s; 9965534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } else { 9975534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst return s.substring(0, newlineIndex) + "..."; 9985534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 9995534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst } 10005534e50f6966d53ba8c8104a4bf847df0cd53409Michael Ernst 1001aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb /** 1002aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb * Separates the annotation class from its arguments. 1003aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb * 1004aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb * @return given <code>@foo(bar)</code> it returns the pair <code>{ @foo, (bar) }</code>. 1005aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb */ 1006aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb public static Pair<String,String> removeArgs(String s) { 1007aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb int pidx = s.indexOf("("); 1008aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb return (pidx == -1) ? 1009615ec652dc360e33296fd763a4fa56e59c35b23cMichael Ernst Pair.of(s, (String)null) : 1010aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb Pair.of(s.substring(0, pidx), s.substring(pidx)); 1011aad82c9e3793937a33a4e6b2cd2e38f6478e0704mdb } 101210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali} 1013