61 import static com.sun.tools.javac.util.ListBuffer.lb; |
61 import static com.sun.tools.javac.util.ListBuffer.lb; |
62 |
62 |
63 // TEMP, until we have a more efficient way to save doc comment info |
63 // TEMP, until we have a more efficient way to save doc comment info |
64 import com.sun.tools.javac.parser.DocCommentScanner; |
64 import com.sun.tools.javac.parser.DocCommentScanner; |
65 |
65 |
|
66 import java.util.Queue; |
66 import javax.lang.model.SourceVersion; |
67 import javax.lang.model.SourceVersion; |
67 |
68 |
68 /** This class could be the main entry point for GJC when GJC is used as a |
69 /** This class could be the main entry point for GJC when GJC is used as a |
69 * component in a larger software system. It provides operations to |
70 * component in a larger software system. It provides operations to |
70 * construct a new compiler, and to run a new compiler on a set of source |
71 * construct a new compiler, and to run a new compiler on a set of source |
458 return delegateCompiler.errorCount(); |
459 return delegateCompiler.errorCount(); |
459 else |
460 else |
460 return log.nerrors; |
461 return log.nerrors; |
461 } |
462 } |
462 |
463 |
463 protected final <T> List<T> stopIfError(ListBuffer<T> listBuffer) { |
464 protected final <T> Queue<T> stopIfError(Queue<T> queue) { |
464 if (errorCount() == 0) |
465 if (errorCount() == 0) |
465 return listBuffer.toList(); |
466 return queue; |
466 else |
467 else |
467 return List.nil(); |
468 return ListBuffer.lb(); |
468 } |
469 } |
469 |
470 |
470 protected final <T> List<T> stopIfError(List<T> list) { |
471 protected final <T> List<T> stopIfError(List<T> list) { |
471 if (errorCount() == 0) |
472 if (errorCount() == 0) |
472 return list; |
473 return list; |
774 case SIMPLE: |
775 case SIMPLE: |
775 generate(desugar(flow(attribute(todo)))); |
776 generate(desugar(flow(attribute(todo)))); |
776 break; |
777 break; |
777 |
778 |
778 case BY_FILE: |
779 case BY_FILE: |
779 for (List<Env<AttrContext>> list : groupByFile(flow(attribute(todo))).values()) |
780 for (Queue<Env<AttrContext>> queue : groupByFile(flow(attribute(todo))).values()) |
780 generate(desugar(list)); |
781 generate(desugar(queue)); |
781 break; |
782 break; |
782 |
783 |
783 case BY_TODO: |
784 case BY_TODO: |
784 while (todo.nonEmpty()) |
785 while (todo.nonEmpty()) |
785 generate(desugar(flow(attribute(todo.next())))); |
786 generate(desugar(flow(attribute(todo.next())))); |
1024 * Note that attributing classes may cause additional files to be |
1025 * Note that attributing classes may cause additional files to be |
1025 * parsed and entered via the SourceCompleter. |
1026 * parsed and entered via the SourceCompleter. |
1026 * Attribution of the entries in the list does not stop if any errors occur. |
1027 * Attribution of the entries in the list does not stop if any errors occur. |
1027 * @returns a list of environments for attributd classes. |
1028 * @returns a list of environments for attributd classes. |
1028 */ |
1029 */ |
1029 public List<Env<AttrContext>> attribute(ListBuffer<Env<AttrContext>> envs) { |
1030 public Queue<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) { |
1030 ListBuffer<Env<AttrContext>> results = lb(); |
1031 ListBuffer<Env<AttrContext>> results = lb(); |
1031 while (envs.nonEmpty()) |
1032 while (!envs.isEmpty()) |
1032 results.append(attribute(envs.next())); |
1033 results.append(attribute(envs.remove())); |
1033 return results.toList(); |
1034 return results; |
1034 } |
1035 } |
1035 |
1036 |
1036 /** |
1037 /** |
1037 * Attribute a parse tree. |
1038 * Attribute a parse tree. |
1038 * @returns the attributed parse tree |
1039 * @returns the attributed parse tree |
1066 * Perform dataflow checks on attributed parse trees. |
1067 * Perform dataflow checks on attributed parse trees. |
1067 * These include checks for definite assignment and unreachable statements. |
1068 * These include checks for definite assignment and unreachable statements. |
1068 * If any errors occur, an empty list will be returned. |
1069 * If any errors occur, an empty list will be returned. |
1069 * @returns the list of attributed parse trees |
1070 * @returns the list of attributed parse trees |
1070 */ |
1071 */ |
1071 public List<Env<AttrContext>> flow(List<Env<AttrContext>> envs) { |
1072 public Queue<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) { |
1072 ListBuffer<Env<AttrContext>> results = lb(); |
1073 ListBuffer<Env<AttrContext>> results = lb(); |
1073 for (List<Env<AttrContext>> l = envs; l.nonEmpty(); l = l.tail) { |
1074 for (Env<AttrContext> env: envs) { |
1074 flow(l.head, results); |
1075 flow(env, results); |
1075 } |
1076 } |
1076 return stopIfError(results); |
1077 return stopIfError(results); |
1077 } |
1078 } |
1078 |
1079 |
1079 /** |
1080 /** |
1080 * Perform dataflow checks on an attributed parse tree. |
1081 * Perform dataflow checks on an attributed parse tree. |
1081 */ |
1082 */ |
1082 public List<Env<AttrContext>> flow(Env<AttrContext> env) { |
1083 public Queue<Env<AttrContext>> flow(Env<AttrContext> env) { |
1083 ListBuffer<Env<AttrContext>> results = lb(); |
1084 ListBuffer<Env<AttrContext>> results = lb(); |
1084 flow(env, results); |
1085 flow(env, results); |
1085 return stopIfError(results); |
1086 return stopIfError(results); |
1086 } |
1087 } |
1087 |
1088 |
1130 * Prepare attributed parse trees, in conjunction with their attribution contexts, |
1131 * Prepare attributed parse trees, in conjunction with their attribution contexts, |
1131 * for source or code generation. |
1132 * for source or code generation. |
1132 * If any errors occur, an empty list will be returned. |
1133 * If any errors occur, an empty list will be returned. |
1133 * @returns a list containing the classes to be generated |
1134 * @returns a list containing the classes to be generated |
1134 */ |
1135 */ |
1135 public List<Pair<Env<AttrContext>, JCClassDecl>> desugar(List<Env<AttrContext>> envs) { |
1136 public Queue<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) { |
1136 ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = lb(); |
1137 ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = lb(); |
1137 for (List<Env<AttrContext>> l = envs; l.nonEmpty(); l = l.tail) |
1138 for (Env<AttrContext> env: envs) |
1138 desugar(l.head, results); |
1139 desugar(env, results); |
1139 return stopIfError(results); |
1140 return stopIfError(results); |
1140 } |
1141 } |
1141 |
1142 |
1142 /** |
1143 /** |
1143 * Prepare attributed parse trees, in conjunction with their attribution contexts, |
1144 * Prepare attributed parse trees, in conjunction with their attribution contexts, |
1144 * for source or code generation. If the file was not listed on the command line, |
1145 * for source or code generation. If the file was not listed on the command line, |
1145 * the current implicitSourcePolicy is taken into account. |
1146 * the current implicitSourcePolicy is taken into account. |
1146 * The preparation stops as soon as an error is found. |
1147 * The preparation stops as soon as an error is found. |
1147 */ |
1148 */ |
1148 protected void desugar(Env<AttrContext> env, ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results) { |
1149 protected void desugar(Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) { |
1149 if (errorCount() > 0) |
1150 if (errorCount() > 0) |
1150 return; |
1151 return; |
1151 |
1152 |
1152 if (implicitSourcePolicy == ImplicitSourcePolicy.NONE |
1153 if (implicitSourcePolicy == ImplicitSourcePolicy.NONE |
1153 && !inputFiles.contains(env.toplevel.sourcefile)) { |
1154 && !inputFiles.contains(env.toplevel.sourcefile)) { |
1178 if (env.tree instanceof JCCompilationUnit) { |
1179 if (env.tree instanceof JCCompilationUnit) { |
1179 if (!(stubOutput || sourceOutput || printFlat)) { |
1180 if (!(stubOutput || sourceOutput || printFlat)) { |
1180 List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake); |
1181 List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake); |
1181 if (pdef.head != null) { |
1182 if (pdef.head != null) { |
1182 assert pdef.tail.isEmpty(); |
1183 assert pdef.tail.isEmpty(); |
1183 results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, (JCClassDecl)pdef.head)); |
1184 results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, (JCClassDecl)pdef.head)); |
1184 } |
1185 } |
1185 } |
1186 } |
1186 return; |
1187 return; |
1187 } |
1188 } |
1188 |
1189 |
1192 JCClassDecl cdef = (JCClassDecl)env.tree; |
1193 JCClassDecl cdef = (JCClassDecl)env.tree; |
1193 if (untranslated instanceof JCClassDecl && |
1194 if (untranslated instanceof JCClassDecl && |
1194 rootClasses.contains((JCClassDecl)untranslated) && |
1195 rootClasses.contains((JCClassDecl)untranslated) && |
1195 ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || |
1196 ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || |
1196 cdef.sym.packge().getQualifiedName() == names.java_lang)) { |
1197 cdef.sym.packge().getQualifiedName() == names.java_lang)) { |
1197 results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, removeMethodBodies(cdef))); |
1198 results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, removeMethodBodies(cdef))); |
1198 } |
1199 } |
1199 return; |
1200 return; |
1200 } |
1201 } |
1201 |
1202 |
1202 env.tree = transTypes.translateTopLevelClass(env.tree, localMake); |
1203 env.tree = transTypes.translateTopLevelClass(env.tree, localMake); |
1208 //emit standard Java source file, only for compilation |
1209 //emit standard Java source file, only for compilation |
1209 //units enumerated explicitly on the command line |
1210 //units enumerated explicitly on the command line |
1210 JCClassDecl cdef = (JCClassDecl)env.tree; |
1211 JCClassDecl cdef = (JCClassDecl)env.tree; |
1211 if (untranslated instanceof JCClassDecl && |
1212 if (untranslated instanceof JCClassDecl && |
1212 rootClasses.contains((JCClassDecl)untranslated)) { |
1213 rootClasses.contains((JCClassDecl)untranslated)) { |
1213 results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); |
1214 results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); |
1214 } |
1215 } |
1215 return; |
1216 return; |
1216 } |
1217 } |
1217 |
1218 |
1218 //translate out inner classes |
1219 //translate out inner classes |
1222 return; |
1223 return; |
1223 |
1224 |
1224 //generate code for each class |
1225 //generate code for each class |
1225 for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) { |
1226 for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) { |
1226 JCClassDecl cdef = (JCClassDecl)l.head; |
1227 JCClassDecl cdef = (JCClassDecl)l.head; |
1227 results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); |
1228 results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); |
1228 } |
1229 } |
1229 } |
1230 } |
1230 finally { |
1231 finally { |
1231 log.useSource(prev); |
1232 log.useSource(prev); |
1232 } |
1233 } |
1273 /** Generates the source or class file for a list of classes. |
1274 /** Generates the source or class file for a list of classes. |
1274 * The decision to generate a source file or a class file is |
1275 * The decision to generate a source file or a class file is |
1275 * based upon the compiler's options. |
1276 * based upon the compiler's options. |
1276 * Generation stops if an error occurs while writing files. |
1277 * Generation stops if an error occurs while writing files. |
1277 */ |
1278 */ |
1278 public void generate(List<Pair<Env<AttrContext>, JCClassDecl>> list) { |
1279 public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue) { |
1279 generate(list, null); |
1280 generate(queue, null); |
1280 } |
1281 } |
1281 |
1282 |
1282 public void generate(List<Pair<Env<AttrContext>, JCClassDecl>> list, ListBuffer<JavaFileObject> results) { |
1283 public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue, ListBuffer<JavaFileObject> results) { |
1283 boolean usePrintSource = (stubOutput || sourceOutput || printFlat); |
1284 boolean usePrintSource = (stubOutput || sourceOutput || printFlat); |
1284 |
1285 |
1285 for (List<Pair<Env<AttrContext>, JCClassDecl>> l = list; l.nonEmpty(); l = l.tail) { |
1286 for (Pair<Env<AttrContext>, JCClassDecl> x: queue) { |
1286 Pair<Env<AttrContext>, JCClassDecl> x = l.head; |
|
1287 Env<AttrContext> env = x.fst; |
1287 Env<AttrContext> env = x.fst; |
1288 JCClassDecl cdef = x.snd; |
1288 JCClassDecl cdef = x.snd; |
1289 |
1289 |
1290 if (verboseCompilePolicy) { |
1290 if (verboseCompilePolicy) { |
1291 log.printLines(log.noticeWriter, "[generate " |
1291 log.printLines(log.noticeWriter, "[generate " |
1323 } |
1323 } |
1324 } |
1324 } |
1325 } |
1325 } |
1326 |
1326 |
1327 // where |
1327 // where |
1328 Map<JCCompilationUnit, List<Env<AttrContext>>> groupByFile(List<Env<AttrContext>> list) { |
1328 Map<JCCompilationUnit, Queue<Env<AttrContext>>> groupByFile(Queue<Env<AttrContext>> envs) { |
1329 // use a LinkedHashMap to preserve the order of the original list as much as possible |
1329 // use a LinkedHashMap to preserve the order of the original list as much as possible |
1330 Map<JCCompilationUnit, List<Env<AttrContext>>> map = new LinkedHashMap<JCCompilationUnit, List<Env<AttrContext>>>(); |
1330 Map<JCCompilationUnit, Queue<Env<AttrContext>>> map = new LinkedHashMap<JCCompilationUnit, Queue<Env<AttrContext>>>(); |
1331 Set<JCCompilationUnit> fixupSet = new HashSet<JCTree.JCCompilationUnit>(); |
1331 for (Env<AttrContext> env: envs) { |
1332 for (List<Env<AttrContext>> l = list; l.nonEmpty(); l = l.tail) { |
1332 Queue<Env<AttrContext>> sublist = map.get(env.toplevel); |
1333 Env<AttrContext> env = l.head; |
1333 if (sublist == null) { |
1334 List<Env<AttrContext>> sublist = map.get(env.toplevel); |
1334 sublist = new ListBuffer<Env<AttrContext>>(); |
1335 if (sublist == null) |
1335 map.put(env.toplevel, sublist); |
1336 sublist = List.of(env); |
|
1337 else { |
|
1338 // this builds the list for the file in reverse order, so make a note |
|
1339 // to reverse the list before returning. |
|
1340 sublist = sublist.prepend(env); |
|
1341 fixupSet.add(env.toplevel); |
|
1342 } |
1336 } |
1343 map.put(env.toplevel, sublist); |
1337 sublist.add(env); |
1344 } |
1338 } |
1345 // fixup any lists that need reversing back to the correct order |
|
1346 for (JCTree.JCCompilationUnit tree: fixupSet) |
|
1347 map.put(tree, map.get(tree).reverse()); |
|
1348 return map; |
1339 return map; |
1349 } |
1340 } |
1350 |
1341 |
1351 JCClassDecl removeMethodBodies(JCClassDecl cdef) { |
1342 JCClassDecl removeMethodBodies(JCClassDecl cdef) { |
1352 final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0; |
1343 final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0; |