Prototyping DCE tool for JS

This commit is contained in:
Alexey Andreev
2017-03-31 20:03:41 +03:00
parent d617b1d869
commit 9e89213d66
26 changed files with 1445 additions and 22 deletions
@@ -32,9 +32,13 @@ public class JsAstMapper {
private final JsProgram program;
private final ScopeContext scopeContext;
public JsAstMapper(@NotNull JsScope scope) {
@NotNull
private final String fileName;
public JsAstMapper(@NotNull JsScope scope, @NotNull String fileName) {
scopeContext = new ScopeContext(scope);
program = scope.getProgram();
this.fileName = fileName;
}
private static JsParserException createParserException(String msg, Node offender) {
@@ -43,6 +47,10 @@ public class JsAstMapper {
}
private JsNode map(Node node) throws JsParserException {
return withLocation(mapWithoutLocation(node), node);
}
private JsNode mapWithoutLocation(Node node) throws JsParserException {
switch (node.getType()) {
case TokenStream.SCRIPT: {
JsBlock block = new JsBlock();
@@ -1115,4 +1123,18 @@ public class JsAstMapper {
int type = jsNode.getType();
return type == TokenStream.NUMBER || type == TokenStream.NUMBER;
}
private <T extends JsNode> T withLocation(T astNode, Node node) {
int lineNumber = node.getLineno();
if (lineNumber >= 0) {
JsLocation location = new JsLocation(fileName, lineNumber, 0);
if (astNode instanceof SourceInfoAwareJsNode) {
astNode.setSource(location);
}
else if (astNode instanceof JsExpressionStatement) {
((JsExpressionStatement) astNode).getExpression().setSource(location);
}
}
return astNode;
}
}
@@ -29,17 +29,19 @@ import java.util.*
private val FAKE_SOURCE_INFO = SourceInfoImpl(null, 0, 0, 0, 0)
fun parse(code: String, reporter: ErrorReporter, scope: JsScope): List<JsStatement> {
fun parse(code: String, reporter: ErrorReporter, scope: JsScope, fileName: String): List<JsStatement> {
val insideFunction = scope is JsFunctionScope
val node = parse(code, 0, reporter, insideFunction, Parser::parse)
return node.toJsAst(scope, JsAstMapper::mapStatements)
return node.toJsAst(scope, fileName) {
mapStatements(it)
}
}
fun parseFunction(code: String, offset: Int, reporter: ErrorReporter, scope: JsScope): JsFunction =
fun parseFunction(code: String, fileName: String, offset: Int, reporter: ErrorReporter, scope: JsScope): JsFunction =
parse(code, offset, reporter, insideFunction = false) {
addObserver(FunctionParsingObserver())
primaryExpr(it)
}.toJsAst(scope, JsAstMapper::mapFunction)
}.toJsAst(scope, fileName, JsAstMapper::mapFunction)
private class FunctionParsingObserver : Observer {
var functionsStarted = 0
@@ -80,8 +82,8 @@ private fun parse(
}
inline
private fun <T> Node.toJsAst(scope: JsScope, mapAction: JsAstMapper.(Node)->T): T =
JsAstMapper(scope).mapAction(this)
private fun <T> Node.toJsAst(scope: JsScope, fileName: String, mapAction: JsAstMapper.(Node)->T): T =
JsAstMapper(scope, fileName).mapAction(this)
private fun StringReader(string: String, offset: Int): Reader {
val reader = StringReader(string)