/*
* Copyright 2008 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.javascript.rhino.Node;
import junit.framework.TestCase;
/**
* Tests for {@link RecordFunctionInformation}
*
*/
public class RecordFunctionInformationTest extends TestCase {
public void testFunction() {
String g = "function g(){}";
String fAndG = "function f(){" + g + "}";
String js = "var h=" + fAndG + ";h()";
FunctionInformationMap.Builder expected =
FunctionInformationMap.newBuilder();
expected.addEntry(
FunctionInformationMap.Entry.newBuilder()
.setId(0)
.setSourceName("testcode")
.setLineNumber(1)
.setModuleName("")
.setSize(g.length())
.setName("f::g")
.setCompiledSource(g).build());
expected.addEntry(
FunctionInformationMap.Entry.newBuilder()
.setId(1)
.setSourceName("testcode")
.setLineNumber(1)
.setModuleName("")
.setSize(fAndG.length())
.setName("f")
.setCompiledSource(fAndG).build());
expected.addModule(
FunctionInformationMap.Module.newBuilder()
.setName("")
.setCompiledSource(js + ";").build());
test(js, expected.build());
}
public void testModule() {
String g = "function g(){}";
String fAndG = "function f(){" + g + "}";
String m0_js = "var h=" + fAndG + ";h()";
String sum = "function(a,b){return a+b}";
String m1_js = "var x=" + sum + "(1,2)";
FunctionInformationMap.Builder expected =
FunctionInformationMap.newBuilder();
expected.addEntry(
FunctionInformationMap.Entry.newBuilder()
.setId(0)
.setSourceName("i0")
.setLineNumber(1)
.setModuleName("m0")
.setSize(g.length())
.setName("f::g")
.setCompiledSource(g).build());
expected.addEntry(
FunctionInformationMap.Entry.newBuilder()
.setId(1)
.setSourceName("i0")
.setLineNumber(1)
.setModuleName("m0")
.setSize(fAndG.length())
.setName("f")
.setCompiledSource(fAndG).build());
expected.addEntry(
FunctionInformationMap.Entry.newBuilder()
.setId(2)
.setSourceName("i1")
.setLineNumber(1)
.setModuleName("m1")
.setSize(sum.length())
.setName("<anonymous>")
.setCompiledSource(sum).build());
expected.addModule(
FunctionInformationMap.Module.newBuilder()
.setName("m0")
.setCompiledSource(m0_js + ";").build());
expected.addModule(
FunctionInformationMap.Module.newBuilder()
.setName("m1")
.setCompiledSource(m1_js + ";").build());
test(CompilerTestCase.createModules(m0_js, m1_js), expected.build());
}
public void testMotionPreservesOriginalSourceName() {
String f = "function f(){}";
String g = "function g(){}";
String m0_before = f + g;
String m1_before = "";
JSModule[] modules = CompilerTestCase.createModules(m0_before, m1_before);
Compiler compiler = compilerFor(modules);
Node root = root(compiler);
Node externsRoot = externs(root);
Node mainRoot = main(root);
String m0_after = f;
String m1_after = g;
Node nodeG = mainRoot.getFirstChild().getLastChild();
mainRoot.getFirstChild().removeChild(nodeG);
mainRoot.getLastChild().addChildrenToBack(nodeG.cloneTree());
FunctionInformationMap.Builder expected =
FunctionInformationMap.newBuilder();
expected.addEntry(
FunctionInformationMap.Entry.newBuilder()
.setId(0)
.setSourceName("i0")
.setLineNumber(1)
.setModuleName("m0")
.setSize(g.length())
.setName("f")
.setCompiledSource(f).build());
expected.addEntry(
FunctionInformationMap.Entry.newBuilder()
.setId(1)
.setSourceName("i0")
.setLineNumber(1)
.setModuleName("m1")
.setSize(g.length())
.setName("g")
.setCompiledSource(g).build());
expected.addModule(
FunctionInformationMap.Module.newBuilder()
.setName("m0")
.setCompiledSource(m0_after + ";").build());
expected.addModule(
FunctionInformationMap.Module.newBuilder()
.setName("m1")
.setCompiledSource(m1_after + ";").build());
test(compiler, externsRoot, mainRoot, expected.build());
}
private void test(String js, FunctionInformationMap expected) {
Compiler compiler = new Compiler();
compiler.init(ImmutableList.of(SourceFile.fromCode("externs", "")),
ImmutableList.of(SourceFile.fromCode("testcode", js)),
new CompilerOptions());
test(compiler, expected);
}
private void test(JSModule[] modules, FunctionInformationMap expected) {
test(compilerFor(modules), expected);
}
private void test(Compiler compiler, FunctionInformationMap expected) {
Node root = root(compiler);
test(compiler, externs(root), main(root), expected);
}
private void test(Compiler compiler, Node externsRoot, Node mainRoot,
FunctionInformationMap expected) {
FunctionNames functionNames = new FunctionNames(compiler);
functionNames.process(externsRoot, mainRoot);
RecordFunctionInformation processor =
new RecordFunctionInformation(compiler, functionNames);
processor.process(externsRoot, mainRoot);
FunctionInformationMap result = processor.getMap();
assertEquals(expected, result);
}
private Compiler compilerFor(JSModule[] modules) {
Compiler compiler = new Compiler();
compiler.initModules(
ImmutableList.of(SourceFile.fromCode("externs", "")),
Lists.newArrayList(modules),
new CompilerOptions());
return compiler;
}
private Node root(Compiler compiler) {
return compiler.parseInputs();
}
private Node externs(Node root) {
return root.getFirstChild();
}
private Node main(Node root) {
return root.getFirstChild().getNext();
}
}