NamedRange someModelBRange = new NamedRange("com.some.app.SomeBModel");
NamedRange someControllerRange = new NamedRange("com.some.app.SomeController");
NamedRange entryPointRange = new NamedRange("com.some.app.EntryPoint");
List<NamedRange> classRanges =
Lists.newArrayList(someModelARange, someModelBRange, someControllerRange, entryPointRange);
StatementRangesBuilder srb = new StatementRangesBuilder();
JsSourceMapBuilder smb = new JsSourceMapBuilder();
// Build the original JS and log boundaries.
StringBuilder sb = new StringBuilder();
appendStatement(sb, srb, smb, "<preamble>\n");
appendStatement(sb, srb, smb, "<java.lang.Object />\n");
appendStatement(sb, srb, smb, "<java.lang.Class />\n");
appendStatement(sb, srb, smb, "</preamble>\n");
{
programRange.setStartPosition(sb.length());
programRange.setStartLineNumber(lines);
appendTypeStatement(sb, srb, smb, someModelARange, "<com.some.app.SomeModelA>\n");
appendTypeStatement(sb, srb, smb, someModelBRange, "<com.some.app.SomeModelB>\n");
appendTypeStatement(sb, srb, smb, someControllerRange, "<com.some.app.SomeController>\n");
appendTypeStatement(sb, srb, smb, entryPointRange, "<com.some.app.EntryPoint>\n");
programRange.setEndPosition(sb.length());
programRange.setEndLineNumber(lines);
}
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();
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.SomeController>\n" + "<epilogue>\n<Some Bootstrap Code>\n</epilogue>\n",