appendStatement(sb, srb, smb, "<epilogue>\n");
appendStatement(sb, srb, smb, "<Some Bootstrap Code>\n");
appendStatement(sb, srb, smb, "</epilogue>\n");
String originalJs = sb.toString();
MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache();
// Create type inheritance.
Map<String, String> superClassesByClass =
minimalRebuildCache.getImmediateTypeRelations().getImmediateSuperclassesByClass();
superClassesByClass.put("java.lang.Class", "java.lang.Object");
superClassesByClass.put("com.some.app.SomeAModel", "java.lang.Object");
superClassesByClass.put("com.some.app.SomeBModel", "java.lang.Object");
superClassesByClass.put("com.some.app.SomeController", "java.lang.Object");
superClassesByClass.put("com.some.app.EntryPoint", "java.lang.Object");
// Record root types.
minimalRebuildCache.setRootTypeNames(Lists.newArrayList("com.some.app.EntryPoint"));
// Record type references.
minimalRebuildCache.addTypeReference("com.some.app.EntryPoint",
"com.some.app.SomeController");
minimalRebuildCache.addTypeReference("com.some.app.SomeController",
"com.some.app.SomeBModel");
minimalRebuildCache.addTypeReference("com.some.app.SomeController",
"com.some.app.SomeAModel");
JsTypeLinker jsTypeLinker = new JsTypeLinker(TreeLogger.NULL,
new JsNoopTransformer(originalJs, srb.build(), smb.build()), classRanges, programRange,
minimalRebuildCache, new JTypeOracle(null, minimalRebuildCache, true));
// Run the JS Type Linker.
jsTypeLinker.exec();
// Verify that the linker output all the expected classes and sorted them alphabetically.
assertEquals("<preamble>\n<java.lang.Object />\n<java.lang.Class />\n</preamble>\n"
+ "<com.some.app.EntryPoint>\n" + "<com.some.app.SomeModelA>\n"
+ "<com.some.app.SomeModelB>\n" + "<com.some.app.SomeController>\n"
+ "<epilogue>\n<Some Bootstrap Code>\n</epilogue>\n", jsTypeLinker.getJs());
assertEquals(Lists.newArrayList("preamble", "java.lang.Object", "java.lang.Class", "/preamble",
"com.some.app.EntryPoint", "com.some.app.SomeModelA", "com.some.app.SomeModelB",
"com.some.app.SomeController", "epilogue", "Some Bootstrap Code", "/epilogue"),
getTypeNames(jsTypeLinker.getSourceInfoMap()));
assertEquals(11, jsTypeLinker.getSourceInfoMap().getLines());
// Make SomeModelB the super class of SomeModelA and then verify that B comes out before A.
superClassesByClass.put("com.some.app.SomeAModel", "com.some.app.SomeBModel");
jsTypeLinker = new JsTypeLinker(TreeLogger.NULL,
new JsNoopTransformer(originalJs, srb.build(), smb.build()), classRanges, programRange,
minimalRebuildCache, new JTypeOracle(null, minimalRebuildCache, true));
jsTypeLinker.exec();
assertEquals("<preamble>\n<java.lang.Object />\n<java.lang.Class />\n</preamble>\n"
+ "<com.some.app.EntryPoint>\n" + "<com.some.app.SomeModelB>\n"
+ "<com.some.app.SomeModelA>\n" + "<com.some.app.SomeController>\n"
+ "<epilogue>\n<Some Bootstrap Code>\n</epilogue>\n", jsTypeLinker.getJs());
assertEquals(Lists.newArrayList("preamble", "java.lang.Object", "java.lang.Class", "/preamble",
"com.some.app.EntryPoint", "com.some.app.SomeModelB", "com.some.app.SomeModelA",
"com.some.app.SomeController", "epilogue", "Some Bootstrap Code", "/epilogue"),
getTypeNames(jsTypeLinker.getSourceInfoMap()));
assertEquals(11, jsTypeLinker.getSourceInfoMap().getLines());
// Stop referring to SomeModelA from the Controller and verify that SomeModelA is not in the
// output.
minimalRebuildCache.removeReferencesFrom("com.some.app.SomeController");
minimalRebuildCache.addTypeReference("com.some.app.SomeController",
"com.some.app.SomeBModel");
jsTypeLinker = new JsTypeLinker(TreeLogger.NULL,
new JsNoopTransformer(originalJs, srb.build(), smb.build()), classRanges, programRange,
minimalRebuildCache, new JTypeOracle(null, minimalRebuildCache, true));
jsTypeLinker.exec();