JS: use one tag for inlining

This commit is contained in:
Alexey Tsvetkov
2015-03-10 15:51:20 +03:00
parent e83b253b3e
commit c7e8f52faf
9 changed files with 153 additions and 145 deletions
@@ -17,68 +17,25 @@ package com.google.gwt.dev.js;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.backend.js.ast.JsLiteral.JsBooleanLiteral;
import com.google.dart.compiler.common.SourceInfo;
import com.google.gwt.dev.js.parserExceptions.JsParserException;
import com.google.gwt.dev.js.rhino.*;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import static com.google.dart.compiler.util.AstUtil.toFunctionScope;
/**
* Parses JavaScript source.
*/
public class JsAstMapper {
private final JsProgram program;
private final ScopeContext scopeContext;
public static List<JsStatement> parse(
SourceInfo rootSourceInfo,
JsScope scope, Reader r,
ErrorReporter errorReporter,
boolean insideFunction
) throws IOException, JsParserException {
return new JsAstMapper(scope).parseImpl(rootSourceInfo, r, errorReporter, insideFunction);
}
/**
* since source maps are not mapped to kotlin source maps
*/
private static final String SOURCE_NAME_STUB = "jsCode";
private JsAstMapper(@NotNull JsScope scope) {
public JsAstMapper(@NotNull JsScope scope) {
scopeContext = new ScopeContext(scope);
program = scope.getProgram();
}
List<JsStatement> parseImpl(
final SourceInfo rootSourceInfo,
Reader r,
ErrorReporter errorReporter,
boolean insideFunction
) throws JsParserException, IOException {
// Create a custom error handler so that we can throw our own exceptions.
Context.enter().setErrorReporter(errorReporter);
try {
// Parse using the Rhino parser.
//
TokenStream ts = new TokenStream(r, SOURCE_NAME_STUB, rootSourceInfo.getLine());
Parser parser = new Parser(new IRFactory(ts), insideFunction);
Node topNode = (Node) parser.parse(ts);
return mapStatements(topNode);
}
finally {
Context.exit();
}
}
private static JsParserException createParserException(String msg, Node offender) {
CodePosition position = new CodePosition(offender.getLineno(), 0);
return new JsParserException("Parser encountered internal error: " + msg, position);
@@ -594,8 +551,9 @@ public class JsAstMapper {
}
}
private JsExpression mapFunction(Node fnNode) throws JsParserException {
public JsFunction mapFunction(Node fnNode) throws JsParserException {
int nodeType = fnNode.getType();
assert nodeType == TokenStream.FUNCTION: "Expected function node, got: " + TokenStream.tokenToName(nodeType);
Node fromFnNameNode = fnNode.getFirstChild();
Node fromParamNode = fnNode.getFirstChild().getNext().getFirstChild();
Node fromBodyNode = fnNode.getFirstChild().getNext().getNext();
@@ -954,7 +912,7 @@ public class JsAstMapper {
}
}
private List<JsStatement> mapStatements(Node nodeStmts)
public List<JsStatement> mapStatements(Node nodeStmts)
throws JsParserException {
List<JsStatement> stmts = new ArrayList<JsStatement>();
mapStatements(stmts, nodeStmts);
@@ -37,7 +37,10 @@
package com.google.gwt.dev.js.rhino;
import org.jetbrains.kotlin.js.parser.ParserEvents;
import java.io.IOException;
import java.util.Observable;
/**
* This class implements the JavaScript parser.
@@ -48,7 +51,7 @@ import java.io.IOException;
* @see TokenStream
*/
public class Parser {
public class Parser extends Observable {
public Parser(IRFactory nf, boolean insideFunction) {
this.nf = nf;
this.insideFunction = insideFunction;
@@ -165,8 +168,8 @@ public class Parser {
return pn;
}
private Object function(TokenStream ts, boolean isExpr) throws IOException,
JavaScriptException {
private Object function(TokenStream ts, boolean isExpr) throws IOException, JavaScriptException {
notifyObservers(new ParserEvents.OnFunctionParsingStart());
int baseLineno = ts.getLineno(); // line number where source starts
String name;
@@ -243,6 +246,7 @@ public class Parser {
wellTerminated(ts, ts.FUNCTION);
}
notifyObservers(new ParserEvents.OnFunctionParsingEnd(ts));
return pn;
}
@@ -1021,7 +1025,7 @@ public class Parser {
return pn;
}
private Object primaryExpr(TokenStream ts) throws IOException,
public Object primaryExpr(TokenStream ts) throws IOException,
JavaScriptException {
int tt;
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* 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 org.jetbrains.kotlin.js.parser
import com.google.gwt.dev.js.rhino.*
public object ParserEvents {
public class OnFunctionParsingStart
public class OnFunctionParsingEnd(public val tokenStream: TokenStream)
}
@@ -0,0 +1,88 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* 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 org.jetbrains.kotlin.js.parser
import com.google.dart.compiler.common.*
import com.google.dart.compiler.backend.js.ast.*
import com.google.gwt.dev.js.*
import com.google.gwt.dev.js.rhino.*
import com.intellij.util.*
import java.io.*
import java.util.*
private val FAKE_SOURCE_INFO = SourceInfoImpl(null, 0, 0, 0, 0)
public fun parse(code: String, reporter: ErrorReporter, insideFunction: Boolean): List<JsStatement> =
parse(code, 0, reporter, insideFunction, Parser::parse).toJsAst(JsAstMapper::mapStatements)
public fun parseFunction(code: String, offset: Int, reporter: ErrorReporter): JsFunction =
parse(code, offset, reporter, insideFunction = false) {
addObserver(FunctionParsingObserver())
primaryExpr(it)
}.toJsAst(JsAstMapper::mapFunction)
private class FunctionParsingObserver : Observer {
var functionsStarted = 0
override fun update(o: Observable?, arg: Any?): Unit =
when (arg) {
is ParserEvents.OnFunctionParsingStart -> {
functionsStarted++
}
is ParserEvents.OnFunctionParsingEnd -> {
functionsStarted--
if (functionsStarted == 0) {
arg.tokenStream.ungetToken(TokenStream.EOF)
}
}
}
}
inline
private fun parse(
code: String,
offset: Int,
reporter: ErrorReporter,
insideFunction: Boolean,
parseAction: Parser.(TokenStream)->Any
): Node {
Context.enter().setErrorReporter(reporter)
try {
val ts = TokenStream(StringReader(code, offset), "<parser>", FAKE_SOURCE_INFO.getLine())
val parser = Parser(IRFactory(ts), insideFunction)
return parser.parseAction(ts) as Node
} finally {
Context.exit()
}
}
inline
private fun Node.toJsAst<T>(mapAction: JsAstMapper.(Node)->T): T =
JsAstMapper(RootScope()).mapAction(this)
private fun StringReader(string: String, offset: Int): Reader {
val reader = StringReader(string)
reader.skip(offset.toLong())
return reader
}
private fun RootScope(): JsScope {
return JsRootScope(JsProgram("<parser>"))
}