You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2016/04/18 15:31:50 UTC
[01/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - VarDeclarationEmitter: fixed
sourcemap for assignment when type is omitted
Repository: flex-falcon
Updated Branches:
refs/heads/feature/maven-migration-test 316710d68 -> beaf5b63a
VarDeclarationEmitter: fixed sourcemap for assignment when type is omitted
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/e36c544c
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/e36c544c
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/e36c544c
Branch: refs/heads/feature/maven-migration-test
Commit: e36c544cf9ebe6900dfb84ddffd2bdc9bd94733c
Parents: bc19c66
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 14:03:18 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 14:03:18 2016 -0700
----------------------------------------------------------------------
.../js/sourcemaps/TestSourceMapStatements.java | 14 ++++++++++++++
.../internal/codegen/js/jx/VarDeclarationEmitter.java | 12 ++++++++++--
2 files changed, 24 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e36c544c/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
index 3c25d07..8f4cf77 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
@@ -27,6 +27,20 @@ public class TestSourceMapStatements extends SourceMapTestBase
}
@Test
+ public void testVarDeclaration_withAssignedValue()
+ {
+ IVariableNode node = (IVariableNode) getNode("var a = 42;",
+ IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ //var /** @type {*} */ a = 42
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // var
+ assertMapping(node, 0, 4, 0, 21, 0, 22); // a
+ assertMapping(node, 0, 5, 0, 4, 0, 21); // (type)
+ assertMapping(node, 0, 5, 0, 22, 0, 25); // =
+ assertMapping(node, 0, 8, 0, 25, 0, 27); // 42
+ }
+
+ @Test
public void testVarDeclaration_withType()
{
IVariableNode node = (IVariableNode) getNode("var a:int;",
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e36c544c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
index f43b288..911a280 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
@@ -54,7 +54,8 @@ public class VarDeclarationEmitter extends JSSubEmitter implements
}
IExpressionNode variableTypeNode = node.getVariableTypeNode();
- if(variableTypeNode.getLine() >= 0)
+ boolean hasVariableType = variableTypeNode.getLine() >= 0;
+ if(hasVariableType)
{
startMapping(variableTypeNode,
variableTypeNode.getLine(),
@@ -95,7 +96,14 @@ public class VarDeclarationEmitter extends JSSubEmitter implements
fjs.emitDeclarationName(node);
if (avnode != null && !(avnode instanceof IEmbedNode))
{
- startMapping(node, node.getVariableTypeNode());
+ if (hasVariableType)
+ {
+ startMapping(node, node.getVariableTypeNode());
+ }
+ else
+ {
+ startMapping(node, node.getNameExpressionNode());
+ }
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.EQUAL);
endMapping(node);
[02/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - compiler.jx.tests: added some
tests for if statement source maps
Posted by cd...@apache.org.
compiler.jx.tests: added some tests for if statement source maps
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/a9a399be
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/a9a399be
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/a9a399be
Branch: refs/heads/feature/maven-migration-test
Commit: a9a399be7217b2632d41916a6338a0b4e1310ecd
Parents: e36c544
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 14:58:23 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 14:58:23 2016 -0700
----------------------------------------------------------------------
.../js/sourcemaps/TestSourceMapStatements.java | 104 +++++++++++++++++++
1 file changed, 104 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a9a399be/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
index 8f4cf77..5d11227 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
@@ -4,6 +4,7 @@ import org.apache.flex.compiler.driver.IBackend;
import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend;
import org.apache.flex.compiler.internal.test.SourceMapTestBase;
import org.apache.flex.compiler.tree.as.IForLoopNode;
+import org.apache.flex.compiler.tree.as.IIfNode;
import org.apache.flex.compiler.tree.as.IVariableNode;
import org.junit.Test;
@@ -178,6 +179,109 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 21, 0, 39, 0, 40); // )
}
+ //----------------------------------
+ // if ()
+ //----------------------------------
+
+ @Test
+ public void testVisitIf_1()
+ {
+ IIfNode node = (IIfNode) getNode("if (a) b++;", IIfNode.class);
+ asBlockWalker.visitIf(node);
+ //if (a)\n b++;
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
+ }
+
+ @Test
+ public void testVisitIf_2()
+ {
+ IIfNode node = (IIfNode) getNode("if (a) b++; else c++;", IIfNode.class);
+ asBlockWalker.visitIf(node);
+ //if (a)\n b++;\nelse\n c++;
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
+ assertMapping(node, 0, 12, 2, 0, 2, 4); // else
+ }
+
+ @Test
+ public void testVisitIf_4()
+ {
+ IIfNode node = (IIfNode) getNode(
+ "if (a) b++; else if (c) d++; else if(e) --f;", IIfNode.class);
+ asBlockWalker.visitIf(node);
+ //if (a)\n b++;\nelse if (c)\n d++;\nelse if (e)\n --f;
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
+ assertMapping(node, 0, 12, 2, 0, 2, 9); // else if (
+ assertMapping(node, 0, 22, 2, 10, 2, 11); // )
+ assertMapping(node, 0, 29, 4, 0, 4, 9); // else if (
+ assertMapping(node, 0, 38, 4, 10, 4, 11); // )
+ }
+
+ //----------------------------------
+ // if () { }
+ //----------------------------------
+
+ @Test
+ public void testVisitIf_1a()
+ {
+ IIfNode node = (IIfNode) getNode("if (a) { b++; }", IIfNode.class);
+ asBlockWalker.visitIf(node);
+ //if (a) {\n b++;\n}
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
+ assertMapping(node, 0, 5, 0, 5, 0, 7); // )
+ }
+
+ @Test
+ public void testVisitIf_1b()
+ {
+ IIfNode node = (IIfNode) getNode("if (a) { b++; } else { c++; }",
+ IIfNode.class);
+ asBlockWalker.visitIf(node);
+ //if (a) {\n b++;\n} else {\n c++;\n}
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
+ assertMapping(node, 0, 5, 0, 5, 0, 7); // )
+ assertMapping(node, 0, 16, 2, 2, 2, 7); // else
+ }
+
+ @Test
+ public void testVisitIf_1c()
+ {
+ IIfNode node = (IIfNode) getNode(
+ "if (a) { b++; } else if (b) { c++; } else { d++; }",
+ IIfNode.class);
+ asBlockWalker.visitIf(node);
+ //if (a) {\n b++;\n} else if (b) {\n c++;\n} else {\n d++;\n}
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
+ assertMapping(node, 0, 5, 0, 5, 0, 7); // )
+ assertMapping(node, 0, 16, 2, 2, 2, 11); // else if(
+ assertMapping(node, 0, 26, 2, 12, 2, 14); // )
+ assertMapping(node, 0, 37, 4, 2, 4, 7); // else
+ }
+
+ @Test
+ public void testVisitIf_3()
+ {
+ IIfNode node = (IIfNode) getNode(
+ "if (a) b++; else if (c) d++; else --e;", IIfNode.class);
+ asBlockWalker.visitIf(node);
+ //if (a)\n b++;\nelse if (c)\n d++;\nelse\n --e;
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
+ assertMapping(node, 0, 12, 2, 0, 2, 9); // else if (
+ assertMapping(node, 0, 21, 2, 9, 2, 10); // c
+ assertMapping(node, 0, 22, 2, 10, 2, 11); // )
+ assertMapping(node, 0, 29, 4, 0, 4, 4); // else
+ }
+
protected IBackend createBackend()
{
return new FlexJSBackend();
[12/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - Merge branches 'develop' and
'feature/maven-migration-test' of
https://git-wip-us.apache.org/repos/asf/flex-falcon into
feature/maven-migration-test
Posted by cd...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
----------------------------------------------------------------------
diff --cc compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
index 34cb240,0000000..4d4936b
mode 100644,000000..100644
--- a/compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
+++ b/compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
@@@ -1,3223 -1,0 +1,3223 @@@
+header
+{
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.parsing.as;
+
+/*
+ * This file is generated from ASTreeAssembler.g
+ * DO NOT MAKE EDITS DIRECTLY TO THIS FILE. THEY WILL BE LOST WHEN THE FILE IS GENERATED AGAIN!!!
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.flex.compiler.tree.as.*;
+import org.apache.flex.compiler.workspaces.IWorkspace;
+import org.apache.flex.compiler.parsing.IASToken;
+import org.apache.flex.compiler.parsing.IASToken.ASTokenKind;
+import org.apache.flex.compiler.tree.as.IContainerNode.ContainerType;
+import org.apache.flex.compiler.tree.as.ILiteralNode.LiteralType;
+import org.apache.flex.compiler.internal.tree.as.*;
+import org.apache.flex.compiler.internal.tree.as.metadata.*;
+import org.apache.flex.compiler.asdoc.IASParserASDocDelegate;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.*;
+
+}
+
+/**
+ * ActionScript3 parser grammar. It consumes ASTokens and produces IASNode AST.
+ * The number of tokens in a single syntactic predicate can not be greater than
+ * StreamingTokenBuffer.REWIND_BUFFER_SIZE.
+ *
+ * @see <a href="https://zerowing.corp.adobe.com/display/FlashPlayer/ActionScript+Language+Specification">ActionScript Language Syntax Specification</a>
+ */
+class ASParser extends Parser("org.apache.flex.compiler.internal.parsing.as.BaseASParser");
+
+options
+{
+ exportVocab = AS;
+ defaultErrorHandler = false;
+}
+
+tokens
+{
+ // These hidden tokens are matched by the raw tokenizer but are not sent to the parser.
+ HIDDEN_TOKEN_COMMENT;
+ HIDDEN_TOKEN_SINGLE_LINE_COMMENT;
+ HIDDEN_TOKEN_STAR_ASSIGNMENT;
+ HIDDEN_TOKEN_BUILTIN_NS;
+ HIDDEN_TOKEN_MULTI_LINE_COMMENT;
+
+ // These two tokens are used by code model's ASDoc tokenizer.
+ TOKEN_ASDOC_TAG;
+ TOKEN_ASDOC_TEXT;
+
+ // These tokens are transformed from reserved words by StreamingASTokenizer.
+ TOKEN_RESERVED_WORD_EACH;
+ TOKEN_RESERVED_WORD_CONFIG;
+ TOKEN_KEYWORD_INCLUDE;
+ TOKEN_RESERVED_WORD_GOTO;
+}
+
+{
+
+ /**
+ * Construct an AS3 parser from a token buffer.
+ */
+ public ASParser(IWorkspace workspace, IRepairingTokenBuffer buffer)
+ {
+ super(workspace, buffer);
+ tokenNames = _tokenNames;
+ }
+
+ /**
+ * Construct an AS3 parser for parsing command line config args
+ */
+ public ASParser(IWorkspace workspace, IRepairingTokenBuffer buffer, boolean parsingProjectConfigVariables)
+ {
+ super(workspace, buffer, parsingProjectConfigVariables);
+ tokenNames = _tokenNames;
+ }
+}
+
+
+/**
+ * Matches multiple directives. This layer is added to handle parsing error in directives.
+ */
+fileLevelDirectives[ContainerNode c]
+ : (directive[c, NO_END_TOKEN])*
+ ;
+ exception catch [RecognitionException parserError] { handleParsingError(parserError); }
+
+/**
+ * Matches a "directive" level input.
+ * The first couple of alternatives gated with semantic predicates are used to
+ * either disambiguate inputs, or to trap erroneous syntax.
+ */
+directive[ContainerNode c, int endToken]
+{
+ final ASToken lt1 = LT(1);
+ final ASToken lt2 = LT(2);
+ final int la1 = LA(1);
+ final int la2 = LA(2);
+ final int la3 = LA(3);
+ final int la4 = LA(4);
+}
+ : { la1 == TOKEN_BLOCK_OPEN }? groupDirective[c, endToken]
+ | { la1 == TOKEN_RESERVED_WORD_NAMESPACE && la2 == TOKEN_PAREN_OPEN }? statement[c, endToken]
+ | { la1 == TOKEN_IDENTIFIER && la2 == TOKEN_NAMESPACE_ANNOTATION && lt1.getLine() == lt2.getLine() }?
+ // Skip over the user-defined namespace name and continue.
+ nsT:TOKEN_IDENTIFIER attributedDefinition[c]
+ { trapInvalidNamespaceAttribute((ASToken)nsT); }
+ | asDocComment
+ | importDirective[c]
+ | useNamespaceDirective[c]
+ | { la1 == TOKEN_NAMESPACE_NAME &&
+ la2 == TOKEN_OPERATOR_NS_QUALIFIER &&
+ la3 == TOKEN_IDENTIFIER &&
+ la4 == TOKEN_BLOCK_OPEN}?
+ // ns::var { ... }
+ groupDirectiveWithConfigVariable[c, endToken]
+ | { la1 == TOKEN_NAMESPACE_NAME &&
+ la2 == TOKEN_OPERATOR_NS_QUALIFIER &&
+ la3 == TOKEN_NAMESPACE_ANNOTATION }?
+ // ns::var private var foo:int;
+ attributedDefinition[c]
+ | { la1 == TOKEN_NAMESPACE_NAME &&
+ la2 == TOKEN_OPERATOR_NS_QUALIFIER }?
+ // "ns::var" or "ns::[x, y]"
+ statement[c,endToken]
+ | { !isFunctionClosure() }?
+ attributedDefinition[c]
+ | packageDirective[c]
+ | statement[c,endToken]
+ | configNamespace[c]
+ | includeDirective
+ // The following alternatives are error traps
+ | fT:TOKEN_KEYWORD_FINALLY { reportUnexpectedTokenProblem((ASToken)fT); }
+ | cT:TOKEN_KEYWORD_CATCH { reportUnexpectedTokenProblem((ASToken)cT); }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ handleParsingError(ex, endToken);
+ consumeUntilKeywordOrIdentifier(endToken);
+ }
+
+/**
+ * Include processing is usually done in the lexer. However, this rule is added
+ * in order to support code model partitioner whose tokenizer is set to not
+ * "follow includes". In a normal AS3 compilation, the parser would never see
+ * the "include" token.
+ */
+includeDirective
+ : TOKEN_KEYWORD_INCLUDE TOKEN_LITERAL_STRING
+ ;
+
+/**
+ * Matches an attributed definition. An "attribute" can be a namespace or a
+ * modifier.
+ */
+attributedDefinition[ContainerNode c]
+{
+ List<INamespaceDecorationNode> namespaceAttributes = new ArrayList<INamespaceDecorationNode>();
+ List<ModifierNode> modifiers = new ArrayList<ModifierNode>();
+ INamespaceDecorationNode namespaceAttr = null;
+
+ boolean enabled = isDefinitionEnabled(c);
+ boolean eval = true;
+}
+ : (eval=configConditionOfDefinition)?
+ {
+ // A configuration condition variable can either be matched by
+ // the above rule or be transformed into a LiteralNode of boolean
+ // type. If either is evaluated to false, the definition is disabled.
+ enabled &= eval;
+ if (!enabled)
+ c = new ContainerNode();
+ }
+ (attribute[modifiers, namespaceAttributes])*
+ {
+ // Verify that at most one namespace attribute is matched.
+ verifyNamespaceAttributes(namespaceAttributes);
+
+ if (!namespaceAttributes.isEmpty())
+ namespaceAttr = namespaceAttributes.get(0);
+ }
+ definition[c, namespaceAttr, modifiers]
+ exception catch [RecognitionException ex]
+ {
+ handleParsingError(ex);
+ }
+ ;
+
+/**
+ * Matches an attribute such as:
+ * - Modifiers: dynamic, final, native, override, static, virtual.
+ * - Namespace names.
+ * - Reserved namespace names: internal, private, public, protected.
+ *
+ * A definition can have at most one "namespace attribute".
+ * The matched attribute is added to the lists passed in as arguments.
+ */
+attribute [List<ModifierNode> modifiers, List<INamespaceDecorationNode> namespaceAttributes]
+{
+ ExpressionNodeBase namespaceNode = null;
+ ModifierNode modifierNode = null;
+}
+ : modifierNode=modifierAttribute
+ {
+ if (modifierNode != null)
+ modifiers.add(modifierNode);
+ }
+ | namespaceNode=namespaceModifier
+ {
+ if (namespaceNode instanceof INamespaceDecorationNode)
+ namespaceAttributes.add((INamespaceDecorationNode) namespaceNode);
+ }
+ ;
+
+
+/**
+ * Matches a definition of variable, function, namespace, class or interface.
+ */
+definition[ContainerNode c, INamespaceDecorationNode ns, List<ModifierNode> modList]
+ : variableDefinition[c, ns, modList]
+ | functionDefinition[c, ns, modList]
+ | namespaceDefinition[c, ns, modList]
+ | classDefinition[c, ns, modList]
+ | interfaceDefinition[c, ns, modList]
+ ;
+
+/**
+ * Matches a "group" in a "group directive".
+ * Entering a "Block" leaves the global context, but entering a "Group" doesn't.
+ */
+groupDirective[ContainerNode c, int endToken]
+{
+ BlockNode b = new BlockNode();
+ enterGroup();
+}
+ : openT:TOKEN_BLOCK_OPEN { b.startAfter(openT); }
+ (directive[c, endToken])*
+ { if(b.getChildCount() > 0) c.addItem(b); }
+ closeT:TOKEN_BLOCK_CLOSE { b.endBefore(closeT); leaveGroup(); }
+ ;
+
+/**
+ * Matches a config condition such as "CONFIG::debug". This rule only applies
+ * to blocks gated with configuration variable.
+ *
+ * @return Evaluated result of the configuration variable.
+ */
+configCondition returns [boolean result]
+{
+ result = false;
+}
+ : ns:TOKEN_NAMESPACE_NAME op:TOKEN_OPERATOR_NS_QUALIFIER id:TOKEN_IDENTIFIER
+ {
+ result = evaluateConfigurationVariable(new NamespaceIdentifierNode((ASToken)ns), (ASToken) op, new IdentifierNode((ASToken)id));
+ }
+ ;
+
+/**
+ * Similar to "configCondition", only that the token type after "::" is
+ * "TOKEN_NAMESPACE_ANNOTATION". This rule only applies to "attributed
+ * definitions".
+ */
+configConditionOfDefinition returns [boolean result]
+{
+ result = false;
+}
+ : ns:TOKEN_NAMESPACE_NAME op:TOKEN_OPERATOR_NS_QUALIFIER id:TOKEN_NAMESPACE_ANNOTATION
+ {
+ result = evaluateConfigurationVariable(new NamespaceIdentifierNode((ASToken)ns), (ASToken) op, new IdentifierNode((ASToken)id));
+ }
+ ;
+
+/**
+ * Matches a group of directives gated with configuration variable.
+ *
+ * CONFIG::debug {
+ * trace("debugging code");
+ * }
+ *
+ * If the configuration variable evaluates to false, the following block will
+ * not be added to the resulting AST.
+ */
+groupDirectiveWithConfigVariable [ContainerNode c, int endToken]
+{
+ boolean b;
+ ConfigConditionBlockNode block;
+ final Token lt = LT(1);
+}
+ : b=configCondition
+ {
+ block = new ConfigConditionBlockNode(b);
+ block.startBefore(lt);
+ c.addItem(block);
+ }
+ groupDirective[block, endToken]
+ ;
+
+/**
+ * Matches a statement.
+ *
+ * Note that the "SuperStatement" in ASL syntax spec is not explicitly defined.
+ * The "super" statements like <code>super(args);</code> are matched as regular
+ * "call" expressions.
+ */
+statement[ContainerNode c, int exitCondition]
+{
+ final int la1 = LA(1);
+ final int la2 = LA(2);
+}
+ : breakOrContinueStatement[c]
+ | defaultXMLNamespaceStatement[c]
+ | gotoStatement[c]
+ | emptyStatement
+ | { la1 == TOKEN_IDENTIFIER && la2 == TOKEN_COLON }? labeledStatement[c, exitCondition]
+ | { la1 != TOKEN_SQUARE_OPEN &&
+ la1 != TOKEN_OPERATOR_LESS_THAN &&
+ la1 != TOKEN_BLOCK_OPEN }? expressionStatement[c]
+ | forStatement[c]
+ | ifStatement[c]
+ | meta[c]
+ | returnStatement[c]
+ | switchStatement[c]
+ | throwsStatement[c]
+ | tryStatement[c]
+ | whileStatement[c]
+ | doStatement[c]
+ | withStatement[c]
+ ;
+ exception catch [RecognitionException ex]
+ {
+ handleParsingError(ex);
+ consumeUntilKeywordOrIdentifier(exitCondition);
+ }
+
+/**
+ * Matches an "expression statement". The ASL syntax specification says the
+ * lookahead can not be "[", "{" or "function". Legacy code requires that "<"
+ * be excluded as well.
+ */
+expressionStatement[ContainerNode c]
+{
+ ExpressionNodeBase e = null;
+
+ if (LA(1) == TOKEN_KEYWORD_FUNCTION)
+ {
+ // Recover: continue parsing function as an anonymous function.
+ logSyntaxError(LT(1));
+ }
+}
+ : e=expression
+ {
+ c.addItem(e);
+ if (!matchOptionalSemicolon())
+ {
+ recoverFromExpressionStatementMissingSemicolon(e);
+ }
+ }
+ ;
+
+/**
+ * <h1>From ASL syntax spec:</h1>
+ * <quote>
+ * InnerSubstatement is defined in the grammar for the sole purpose of
+ * specifying side conditions that disambiguate various syntactic ambiguities
+ * in a context-sensitive manner specified in Section 5.
+ * </quote>
+ *
+ * It is only used in "do statement" and "if statement" to loosen the following
+ * two cases allowed by AS3 but not by ECMA5.
+ *
+ * <code>
+ * do x++ while (x < 10); // ES5 would require a ; after x++
+ * if (x > 10) x++ else y++; // ES5 would require a ; after x++
+ * <code>
+ */
+innerSubstatement[ContainerNode c]
+ : substatement[c] { afterInnerSubstatement(); }
+ ;
+
+/**
+ * Matches a sub-statement.
+ */
+substatement[ContainerNode c]
+ : ( { LA(1) != TOKEN_BLOCK_OPEN }? statement[c,NO_END_TOKEN]
+ | block[c]
+ | variableDefinition[c, null, null]
+ )
+ {
+ if (c.getContainerType() == ContainerType.SYNTHESIZED)
+ c.setContainerType(ContainerType.IMPLICIT);
+ }
+ ;
+
+/**
+ * Matches a "labeled statement". For example:
+ *
+ * innerLoop: x++;
+ *
+ */
+labeledStatement[ContainerNode c, int exitCondition]
+{
+ LabeledStatementNode statementNode = null;
+ ASToken offendingNSToken = null;
+}
+ : labelT:TOKEN_IDENTIFIER TOKEN_COLON
+ {
+ final NonResolvingIdentifierNode labelNode =
+ new NonResolvingIdentifierNode(
+ labelT != null ? labelT.getText() : "",
+ labelT);
+ statementNode = new LabeledStatementNode(labelNode);
+ c.addItem(statementNode);
+ }
+ ( { LA(1) == TOKEN_RESERVED_WORD_NAMESPACE && LA(2) == TOKEN_IDENTIFIER }?
+ { offendingNSToken = LT(1); }
+ namespaceDefinition[c, null, null]
+ { trapInvalidSubstatement(offendingNSToken); }
+ | substatement[statementNode.getLabeledStatement()]
+ )
+ ;
+
+/**
+ * Matches a block.
+ */
+block[ContainerNode b]
+ : openT:TOKEN_BLOCK_OPEN
+ {
+ b.startAfter(openT);
+ b.setContainerType(ContainerType.BRACES);
+ }
+ (directive[b, TOKEN_BLOCK_CLOSE])*
+ closeT:TOKEN_BLOCK_CLOSE { b.endBefore(closeT); }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ handleParsingError(ex);
+ consumeUntilKeywordOrIdentifier(TOKEN_BLOCK_CLOSE);
+ endContainerAtError(ex, b);
+ }
+
+/**
+ * Matches an import directive.
+ *
+ * import flash.display.Sprite;
+ * import flash.events.*;
+ */
+importDirective[ContainerNode c]
+{
+ ExpressionNodeBase n = null;
+ ImportNode i = null;
+}
+ : importT:TOKEN_KEYWORD_IMPORT
+ {
+ i = new ImportNode((ExpressionNodeBase) null);
+ i.startBefore(importT);
+ i.endAfter(importT);
+ c.addItem(i);
+ }
+
+ n=importName
+ {
+ if(n != null) {
+ i.setImportTarget(n);
+ i.setEnd(n.getEnd());
+ encounteredImport(i);
+ }
+ else {
+ i.setImportTarget(new IdentifierNode(""));
+ }
+ matchOptionalSemicolon();
+ }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches "use namespace ns" directive.
+ */
+useNamespaceDirective[ContainerNode c]
+{
+ ExpressionNodeBase n = null;
+ UseNamespaceNode u = null;
+}
+ : useT:TOKEN_KEYWORD_USE { u = new UseNamespaceNode(n); u.startBefore(useT); c.addItem(u); }
+ nsT:TOKEN_RESERVED_WORD_NAMESPACE { u.endAfter(nsT); } n=restrictedName
+ {
+ u.setTargetNamespace(n);
+ u.setEnd(n.getEnd());
+ matchOptionalSemicolon();
+ }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ if (u != null && u.getTargetNamespace() == null)
+ u.setTargetNamespace(handleMissingIdentifier(ex));
+ else
+ handleParsingError(ex);
+ }
+
+/**
+ * Matches an ASDoc block.
+ */
+asDocComment
+ : asdocT:TOKEN_ASDOC_COMMENT
+ {
+ asDocDelegate.setCurrentASDocToken(asdocT);
+ }
+ ;
+
+/**
+ * Matches a "modifier attribute" such as "final", "dynamic", "override",
+ * "static" or "native".
+ */
+modifierAttribute returns [ModifierNode modifierNode]
+{
+ modifierNode = null;
+ final ASToken modifierT = LT(1);
+}
+ : ( TOKEN_MODIFIER_FINAL
+ | TOKEN_MODIFIER_DYNAMIC
+ | TOKEN_MODIFIER_OVERRIDE
+ | TOKEN_MODIFIER_STATIC
+ | TOKEN_MODIFIER_NATIVE
+ | TOKEN_MODIFIER_VIRTUAL
+ )
+ { modifierNode = new ModifierNode((ASToken) modifierT); }
+ ;
+
+
+/**
+ * Matches a namespace modifier on an "attributed definition".
+ */
+namespaceModifier returns[ExpressionNodeBase n]
+{
+ n = null;
+}
+ : nsPart1T:TOKEN_NAMESPACE_ANNOTATION
+ {
+ // If our text token is a member access, then build a normal
+ // identifier. Otherwise, build a NS specific one.
+
+ if (LA(1) == TOKEN_OPERATOR_MEMBER_ACCESS)
+ {
+ n = new IdentifierNode((ASToken)nsPart1T) ;
+ }
+ else
+ {
+ final NamespaceIdentifierNode nsNode = new NamespaceIdentifierNode((ASToken)nsPart1T);
+ nsNode.setIsConfigNamespace(isConfigNamespace(nsNode));
+ n = nsNode;
+ }
+ }
+ (
+ dotT:TOKEN_OPERATOR_MEMBER_ACCESS
+ (
+ nsNameT:TOKEN_NAMESPACE_ANNOTATION
+ {
+ IdentifierNode id = new IdentifierNode((ASToken)nsNameT);
+ n = new FullNameNode(n, (ASToken) dotT, id);
+ }
+ )
+ )*
+ {
+ if (n instanceof FullNameNode)
+ n = new QualifiedNamespaceExpressionNode((FullNameNode)n);
+ }
+
+ ;
+
+/**
+ * Matches a "metadata statement".
+ *
+ * [ExcludeClass()]
+ * [Bindable]
+ */
+meta[ContainerNode c]
+{
+ ArrayLiteralNode al = new ArrayLiteralNode();
+ final ASToken lt = LT(1);
+}
+ : attributeT:TOKEN_ATTRIBUTE
+ {
+ // Note that a separate parser is invoked here for metadata.
+ parseMetadata(attributeT, errors);
+ preCheckMetadata(attributeT, c);
+ }
+ | { isIncompleteMetadataTagOnDefinition() }?
+ TOKEN_SQUARE_OPEN
+ // Error trap for "[" before a definition item.
+ { logSyntaxError(LT(1)); }
+ | arrayInitializer[al]
+ // This is statement-level metadata.
+ {
+ // Synthesize a MetaTagsNode to hold the metadata offsets.
+ currentAttributes = new MetaTagsNode();
+ currentAttributes.span(al, al);
+ preCheckMetadata(lt, c);
+ }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ recoverFromMetadataTag(c, al);
+ }
+
+/**
+ * Matches a "config namespace foo" directive.
+ */
+configNamespace[ContainerNode c]
+ : TOKEN_RESERVED_WORD_CONFIG TOKEN_RESERVED_WORD_NAMESPACE configN:TOKEN_IDENTIFIER
+ {
+ NamespaceNode cNode = new ConfigNamespaceNode(new IdentifierNode((ASToken)configN));
+ addConditionalCompilationNamespace(cNode);
+ matchOptionalSemicolon();
+ }
+
+ ;
+ exception catch [RecognitionException ex]
+ { handleParsingError(ex); }
+
+/**
+ * Matches a "package" block.
+ *
+ * package mx.controls { ... }
+ *
+ */
+packageDirective[ContainerNode c]
+{
+ PackageNode p = null;
+ ExpressionNodeBase name = null;
+ BlockNode b = null;
+}
+ : packageT:TOKEN_KEYWORD_PACKAGE { enterPackage((ASToken)packageT); }
+ (name=packageName)?
+ {
+ p = new PackageNode(name != null ? name : IdentifierNode.createEmptyIdentifierNodeAfterToken(packageT), (ASToken)packageT);
+ p.startBefore(packageT);
+ c.addItem(p);
+ b = p.getScopedNode();
+ }
+ ( openT:TOKEN_BLOCK_OPEN { b.startAfter(openT); }
+ packageContents[b]
+ )
+ { leavePackage(); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); leavePackage(); }
+
+/**
+ * Matches a package name such as:
+ * org.apache.flex
+ *
+ * A Whitespace or LineTerminator is allowed around a . in a PackageName.
+ * For example, the following is a syntactically valid
+ * <pre>
+ * package a .
+ * b
+ * { }
+ * </pre>
+ * The resulting PackageName value is equivalent to a PackageName without any intervening Whitespace and LineTerminators.
+ */
+packageName returns [ExpressionNodeBase n]
+{
+ n = null;
+ ExpressionNodeBase e = null;
+}
+ : n=identifier
+ (options{greedy=true;}: { LA(2) != TOKEN_OPERATOR_STAR }?
+ dotT:TOKEN_OPERATOR_MEMBER_ACCESS
+ {
+ n = new FullNameNode(n, (ASToken) dotT, null);
+ }
+ e=identifier
+ {
+ ((FullNameNode)n).setRightOperandNode(e);
+ }
+ )*
+ ;
+ exception catch [RecognitionException ex] { return handleMissingIdentifier(ex, n); }
+
+/**
+ * Matches contents in a package block.
+ */
+packageContents[ContainerNode b]
+ : (directive[b, TOKEN_BLOCK_CLOSE])*
+ closeT:TOKEN_BLOCK_CLOSE { b.endBefore(closeT); }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ if(handleParsingError(ex))
+ {
+ //attempt to recover from the error so we can keep parsing within the block
+ packageContents(b);
+ }
+ else
+ {
+ endContainerAtError(ex, b);
+ }
+ }
+
+/**
+ * Matches a namespace definition.
+ *
+ * namespace ns1;
+ */
+namespaceDefinition[ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+{
+ NamespaceNode n = null;
+ IdentifierNode id = null;
+ ExpressionNodeBase v = null;
+}
+ : nsT:TOKEN_RESERVED_WORD_NAMESPACE id=identifier
+ {
+ n = new NamespaceNode(id);
+ n.startBefore(nsT);
+ storeDecorations(n, c, namespace, modList);
+ checkNamespaceDefinition(n);
+ }
+ (initializer[n])?
+ {
+ c.addItem(n);
+ matchOptionalSemicolon();
+ }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an interface definition.
+ *
+ * interface IFoo extends IBar {...}
+ */
+interfaceDefinition[ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+{
+ InterfaceNode interfaceNode = null;
+ IdentifierNode intName = null;
+ ExpressionNodeBase baseInterfaceName = null;
+ BlockNode b = null;
+ enterInterfaceDefinition(LT(1));
+}
+ : intT:TOKEN_KEYWORD_INTERFACE intName=identifier
+ {
+ interfaceNode = new InterfaceNode(intName);
+ interfaceNode.setInterfaceKeyword((IASToken)intT);
+ storeDecorations(interfaceNode, c, namespace, modList);
+ c.addItem(interfaceNode);
+
+ // Recover from invalid interface name.
+ final int la1 = LA(1);
+ if (la1 != TOKEN_RESERVED_WORD_EXTENDS && la1 != TOKEN_BLOCK_OPEN)
+ {
+ addProblem(new SyntaxProblem(LT(1)));
+ consumeUntilKeywordOr(TOKEN_BLOCK_OPEN);
+ }
+ }
+
+ ( extendsT:TOKEN_RESERVED_WORD_EXTENDS
+ { interfaceNode.setExtendsKeyword((ASToken)extendsT); }
+ ( baseInterfaceName=restrictedName
+ {
+ interfaceNode.addBaseInterface(baseInterfaceName);
+ interfaceNode.setEnd(baseInterfaceName.getEnd());
+ }
+
+ ( commaT:TOKEN_COMMA
+ { interfaceNode.endAfter(commaT); }
+ ( baseInterfaceName=restrictedName
+ {
+ interfaceNode.addBaseInterface(baseInterfaceName);
+ interfaceNode.setEnd(baseInterfaceName.getEnd());
+ }
+ )
+ )*
+ )
+ )?
+
+ {
+ b = interfaceNode.getScopedNode();
+ }
+
+ openT:TOKEN_BLOCK_OPEN
+ { b.startAfter(openT); }
+ classOrInterfaceBlock[b]
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a class definition. For example:
+ *
+ * class Player extends my_ns::GameObject implements IPlayer { ... }
+ *
+ */
+classDefinition [ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+{
+ IdentifierNode className = null;
+ ExpressionNodeBase superName = null;
+ ExpressionNodeBase interfaceName = null;
+ ClassNode classNode = null;
+ disableSemicolonInsertion();
+ enterClassDefinition(LT(1));
+}
+ : classT:TOKEN_KEYWORD_CLASS className=identifier
+ {
+ // When class name is empty, it is a synthesized IdentifierNode
+ // created by the error recovery logic in "identifier" rule.
+ // In such case, we fast-forward the token stream to the next
+ // keyword to recover.
+ if (className.getName().isEmpty())
+ {
+ // If the parser recover from "extends", "implements" or "{",
+ // we are could continue parsing the class definition, because
+ // these tokens are the "follow set" of a class name token.
+ // Otherwise, the next keyword is still a good starting point.
+ consumeUntilKeywordOr(TOKEN_BLOCK_OPEN);
+ }
+
+ insideClass = true;
+ classNode = new ClassNode(className);
+ classNode.setSourcePath(((IASToken)classT).getSourcePath());
+ classNode.setClassKeyword((IASToken)classT);
+ storeDecorations(classNode, c, namespace, modList);
+ c.addItem(classNode);
+ }
+
+ ( extendsT:TOKEN_RESERVED_WORD_EXTENDS
+ { classNode.setExtendsKeyword((ASToken)extendsT); }
+ // The rule for super type should be "restrictedName". However, in
+ // order to trap errors like "class Foo extends Vector.<T>", the
+ // parser has to allow parameterized type as super name. It's up to
+ // semantic analysis to report this problem.
+ superName=type
+ {
+ classNode.setBaseClass(superName);
+ classNode.setEnd(superName.getEnd());
+ }
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )?
+
+ ( impT: TOKEN_RESERVED_WORD_IMPLEMENTS
+ { classNode.setImplementsKeyword((ASToken)impT); }
+ ( interfaceName=restrictedName
+ {
+ classNode.addInterface(interfaceName);
+ classNode.setEnd(interfaceName.getEnd());
+ }
+ ( commaT:TOKEN_COMMA
+ { classNode.endAfter(commaT); }
+ interfaceName=restrictedName
+ {
+ classNode.addInterface(interfaceName);
+ classNode.setEnd(interfaceName.getEnd());
+ }
+ )*
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )?
+
+ openT:TOKEN_BLOCK_OPEN
+ { classNode.getScopedNode().startAfter(openT); }
+ classOrInterfaceBlock[classNode.getScopedNode()]
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the content block of a class definition or an interface definition.
+ */
+classOrInterfaceBlock[BlockNode b]
+ { enableSemicolonInsertion(); }
+
+ : (directive[b, TOKEN_BLOCK_CLOSE])*
+ closeT:TOKEN_BLOCK_CLOSE
+ { b.endBefore(closeT); }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ if(handleParsingError(ex)) {
+ classOrInterfaceBlock(b); //attempt to retry
+ } else {
+ endContainerAtError(ex, b);
+ }
+ }
+
+/**
+ * Matches an anonymous function (function closure).
+ */
+functionExpression returns [FunctionObjectNode n]
+{
+ n = null;
+ BlockNode b = null;
+ FunctionNode f = null;
+ IdentifierNode name=null;
+ ContainerNode p = null;
+}
+ : functionT:TOKEN_KEYWORD_FUNCTION
+
+ // optional function name
+ (name=identifier)?
+ {
+ if(name == null)
+ name = IdentifierNode.createEmptyIdentifierNodeAfterToken(functionT);
+ f = new FunctionNode((ASToken)functionT, name);
+ n = new FunctionObjectNode(f);
+ f.startBefore(functionT);
+ n.startBefore(functionT);
+ b = f.getScopedNode();
+ disableSemicolonInsertion();
+ }
+
+ // function signature
+ lpT:TOKEN_PAREN_OPEN
+ {
+ p = f.getParametersContainerNode();
+ p.startBefore(lpT);
+ }
+ formalParameters[p]
+ rpT:TOKEN_PAREN_CLOSE
+ { p.endAfter(rpT); }
+ (resultType[f])?
+ { enableSemicolonInsertion(); }
+
+ // non-optional function body
+ lbT:TOKEN_BLOCK_OPEN
+ { b.startAfter(lbT);}
+ functionBlock[f, (ASToken)lbT]
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a function block, excluding the open "{" but including the closing "}".
+ */
+functionBlock[FunctionNode f, ASToken openT]
+{
+ final BlockNode b = f.getScopedNode();
+ b.setContainerType(IContainerNode.ContainerType.BRACES);
+ skipFunctionBody(f, openT);
+}
+ : (directive[b, TOKEN_BLOCK_CLOSE])*
+ rbT:TOKEN_BLOCK_CLOSE
+ { b.endBefore(rbT); }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ IASToken prev = buffer.previous();
+ if (prev.getType() != ASTokenTypes.EOF)
+ b.endAfter(prev);
+ else
+ b.setEnd(b.getStart());
+ if(handleParsingError(ex)) {
+ functionBlock(f, openT); //attempt to retry
+ }
+ }
+
+/**
+ * Matches an optional function body. It can either be a "block" or a
+ * "semicolon".
+ */
+optionalFunctionBody [FunctionNode f]
+{
+ BlockNode blockNode = f.getScopedNode();
+ enableSemicolonInsertion();
+}
+ : { LA(1) == TOKEN_BLOCK_OPEN }? lbT:TOKEN_BLOCK_OPEN
+ { blockNode.startAfter(lbT); }
+ functionBlock[f, (ASToken)lbT]
+ | { buffer.matchOptionalSemicolon() }? // Matches a function without body.
+ | {
+ final Token lt = LT(1);
+ blockNode.startBefore(lt);
+ blockNode.endBefore(lt);
+
+ // Report missing left-curly problem if there's no other syntax
+ // problems in the function definition.
+ reportFunctionBodyMissingLeftBraceProblem();
+ }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a function definition. For example:
+ *
+ * private function myFunction(name:String) : void
+ * {
+ * return;
+ * }
+ *
+ */
+functionDefinition[ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+{
+ IdentifierNode name=null;
+ disableSemicolonInsertion();
+}
+ : ( functionT:TOKEN_KEYWORD_FUNCTION
+
+ // optional accessors:
+ // Although "get" and "set" can be identifiers as well, here
+ // they can only be the reserved words, unless it's a function
+ // called "get()" or "set()". As a result, the parser
+ // needs to match it in a "greedy" fashion.
+ (options{greedy=true;}:
+ { LA(2) != TOKEN_PAREN_OPEN}? getT:TOKEN_RESERVED_WORD_GET
+ | { LA(2) != TOKEN_PAREN_OPEN}? setT:TOKEN_RESERVED_WORD_SET
+ )?
+
+ // non-optional function name:
+ name=identifier
+ //we need to be able to keep going in case we are in the processing of typing a function name
+ exception catch [RecognitionException ex] { name = handleMissingIdentifier(ex); }
+ )
+ {
+ final FunctionNode n ;
+ if (getT != null)
+ n = new GetterNode((ASToken)functionT, (ASToken)getT, name);
+ else if (setT != null)
+ n = new SetterNode((ASToken)functionT, (ASToken)setT, name);
+ else
+ n = new FunctionNode((ASToken)functionT, name);
+
+ storeDecorations(n, c, namespace, modList);
+ c.addItem(n);
+ }
+
+ // function signature:
+ lpT:TOKEN_PAREN_OPEN
+ {
+ final ContainerNode parameters = n.getParametersContainerNode();
+ parameters.startBefore(lpT);
+ }
+ formalParameters[parameters]
+ ( rpT:TOKEN_PAREN_CLOSE
+ { parameters.endAfter(rpT); }
+ // error recovery for typing in-progress function definitions
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )
+ (resultType[n])?
+
+ optionalFunctionBody[n]
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the parameters of a function definition signature (excluding the parenthesis).
+ *
+ * arg1:int, arg2:String
+ */
+formalParameters[ContainerNode c]
+ : (formal[c] (TOKEN_COMMA formal[c])*)?
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a single parameter in a function definition.
+ */
+formal[ContainerNode c]
+ { ParameterNode p = null; }
+
+ :(p=restParameter | p=parameter)
+ { if (p != null) c.addItem(p); }
+ ;
+
+/**
+ * Matches the "rest parameters" in a function definition.
+ *
+ * ...args
+ */
+restParameter returns [ParameterNode p]
+ { p = null; }
+
+ : e:TOKEN_ELLIPSIS p=parameter
+ {
+ if (p != null){
+ // ??? following is an override on default type-specification
+ // ??? and should be pulled soon as that gets resolved.
+ if (p.getTypeNode() == null){
+ p.span(e);
+ }
+ p.setIsRestParameter(true);
+ }
+ }
+ ;
+
+/**
+ * Matches a parameter in a function definition.
+ */
+parameter returns [ParameterNode p]
+{
+ p = null;
+ ASToken t = null;
+ IdentifierNode name = null;
+}
+ : ( t=varOrConst
+ {
+ // const allowed here, var is not...log error, keep going
+ if (t.getType() == TOKEN_KEYWORD_VAR)
+ handleParsingError(new RecognitionException());
+ }
+ )?
+
+ name=identifier
+ {
+ p = new ParameterNode(name);
+ if (t != null && t.getType() == TOKEN_KEYWORD_CONST)
+ p.setKeyword(t);
+ }
+
+ (resultType[p])?
+ (initializer[p])?
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches keyword "var" or keyword "const".
+ */
+varOrConst returns[ASToken token]
+{
+ token = LT(1);
+}
+ : TOKEN_KEYWORD_VAR
+ | TOKEN_KEYWORD_CONST
+ ;
+
+/**
+ * Matches a result type: either a "void" keyword or a restricted name.
+ *
+ * :void
+ * :String
+ * :int
+ *
+ */
+resultType [BaseTypedDefinitionNode result]
+{
+ ExpressionNodeBase t = null;
+}
+ : colon:TOKEN_COLON
+ ( ( t=voidLiteral | t=type )
+ exception catch [RecognitionException ex]
+ { t = handleMissingIdentifier(ex); }
+ )
+ {
+ if(t.getStart() == -1)
+ t.startAfter(colon);
+
+ if (t.getEnd() == -1)
+ t.endAfter(colon);
+
+ result.endAfter(colon);
+ result.setType((ASToken) colon, t);
+ }
+ ;
+
+/**
+ * Matches an initializer in a variable/constant definition.
+ */
+initializer [IInitializableDefinitionNode v]
+{
+ ExpressionNodeBase e = null;
+}
+ : assignT:TOKEN_OPERATOR_ASSIGNMENT
+ e=assignmentRightValue
+ { v.setAssignedValue((IASToken) assignT, e); }
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a variable/constant definition.
+ */
+variableDefinition[ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+{
+ VariableNode v = null;
+ ChainedVariableNode v2 = null;
+ ASToken tok = null;
+ asDocDelegate.beforeVariable();
+}
+
+ : tok=varOrConst v=singleVariable[(ASToken)tok, namespace]
+ {
+ asDocDelegate.afterVariable();
+ storeVariableDecorations(v, c, namespace, modList);
+ if(v instanceof ConfigConstNode) {
+ addConfigConstNode((ConfigConstNode)v);
+ } else {
+ c.addItem(v);
+ }
+ }
+ // don't allow chain after a config
+ ( {!(v instanceof ConfigConstNode)}?
+ TOKEN_COMMA v2=chainedVariable[c]
+ {
+ if(v2 != null)
+ {
+ v.addChainedVariableNode(v2);
+ storeEmbedDecoration(v2, v.getMetaTags());
+ }
+ }
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )*
+ { matchOptionalSemicolon(); setAllowErrorsInContext(true); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); setAllowErrorsInContext(true); }
+
+/**
+ * Matches a single variable/constant definition.
+ */
+singleVariable[IASToken keyword, INamespaceDecorationNode namespace] returns [VariableNode v]
+{
+ v = null;
+ IdentifierNode name = null;
+}
+ : name=identifier
+ {
+ if(namespaceIsConfigNamespace(namespace)) {
+ v = new ConfigConstNode(name);
+ } else {
+ v = new VariableNode(name);
+ }
+ v.setKeyword(keyword);
+ v.setIsConst(keyword.getType() == TOKEN_KEYWORD_CONST);
+ if(name.getStart() == -1) {
+ name.startAfter(keyword);
+ name.endAfter(keyword);
+ }
+ }
+
+ (resultType[v])?
+ (initializer[v])?
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a chained variable/constant definition.
+ */
+chainedVariable[ContainerNode c] returns [ChainedVariableNode v]
+{
+ v = null;
+ IdentifierNode name = null;
+}
+ : name=identifier
+ { v = new ChainedVariableNode(name); }
+
+ (resultType[v])?
+ (initializer[v])?
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches variable definitions in a for loop.
+ */
+variableDefExpression returns[NodeBase v]
+{
+ v = null;
+ ContainerNode c = null;
+ NodeBase v1 = null;
+ ASToken varT = null;
+}
+ : varT=varOrConst v=singleVariableDefExpression[varT, varT.getType() == TOKEN_KEYWORD_CONST]
+ ( TOKEN_COMMA v1=singleVariableDefExpression[null, varT.getType() == TOKEN_KEYWORD_CONST]
+ {
+ if (c == null) {
+ c = new ContainerNode();
+ c.setStart(v.getStart());
+ c.addItem(v);
+ v = c;
+ }
+ c.addItem(v1);
+ c.setEnd(v1.getEnd());
+ }
+ )*
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a single variable definition in a for loop.
+ */
+singleVariableDefExpression[ASToken varToken, boolean isConst] returns [ExpressionNodeBase n]
+{
+ n = null;
+ VariableNode variable = null;
+ IdentifierNode varName = null;
+ ExpressionNodeBase value = null;
+}
+ : varName=identifier
+ {
+ variable = new VariableNode(varName);
+ if(varToken != null)
+ variable.setKeyword(varToken);
+ variable.setIsConst(isConst);
+ n = new VariableExpressionNode(variable);
+ }
+
+ (resultType[variable])?
+
+ (initializer[variable])?
+ ;
+
+/**
+ * Matches a default XML namespace statement. For example:
+ *
+ * default xml namespace = "domain";
+ *
+ */
+defaultXMLNamespaceStatement[ContainerNode c]
+ { ExpressionNodeBase e = null; }
+
+ : defT:TOKEN_DIRECTIVE_DEFAULT_XML TOKEN_OPERATOR_ASSIGNMENT e=assignmentExpression
+ {
+ DefaultXMLNamespaceNode n = new DefaultXMLNamespaceNode(new KeywordNode((IASToken)defT));
+ c.addItem(n);
+ n.setExpressionNode(e);
+ matchOptionalSemicolon();
+ }
+ ;
+
+/**
+ * Matches an expression in a pair of parenthesis. It's usually used as a
+ * condition expression in {@code if (...)}, {@code while (...)}, etc.
+ *
+ * (....)
+ */
+statementParenExpression returns [ExpressionNodeBase e]
+{
+ e = null;
+}
+ : TOKEN_PAREN_OPEN { disableSemicolonInsertion(); }
+ e=expression
+ TOKEN_PAREN_CLOSE { enableSemicolonInsertion(); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); enableSemicolonInsertion(); }
+
+
+/**
+ * Matches an empty statement which is an explicit semicolon.
+ */
+emptyStatement
+ : TOKEN_SEMICOLON
+ ;
+
+/**
+ * Matches a "return" statement.
+ */
+returnStatement[ContainerNode c]
+{
+ ExpressionNodeBase n = null;
+ ExpressionNodeBase e = null;
+}
+ : returnT:TOKEN_KEYWORD_RETURN
+ {
+ n = new ReturnNode((ASToken)returnT);
+ c.addItem(n);
+ afterRestrictedToken((ASToken)returnT);
+ }
+
+ e=optExpression
+ {
+ ((ReturnNode)n).setStatementExpression(e);
+ }
+ { matchOptionalSemicolon(); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "throw" statement.
+ */
+throwsStatement[ContainerNode c]
+{
+ ExpressionNodeBase n = null;
+ ExpressionNodeBase e = null;
+}
+ : throwT:TOKEN_KEYWORD_THROW
+ {
+ n = new ThrowNode((ASToken)throwT);
+ c.addItem(n);
+ afterRestrictedToken((ASToken)throwT);
+ }
+
+ ( e=expression
+ {
+ ((ThrowNode)n).setStatementExpression(e);
+ }
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )
+ { matchOptionalSemicolon(); }
+ ;
+
+/**
+ * Matches a "for loop" statement.
+ */
+forStatement[ContainerNode c]
+{
+ ForLoopNode node = null;
+ ContainerNode forContainer = null;
+ BlockNode b = null;
+ NodeBase fi = null;
+ ExpressionNodeBase e = null;
+ BinaryOperatorNodeBase inNode = null;
+}
+ : forKeyword:TOKEN_KEYWORD_FOR lparenT:TOKEN_PAREN_OPEN
+ {
+ node = new ForLoopNode((ASToken)forKeyword);
+ c.addItem(node);
+ forContainer = node.getConditionalsContainerNode();
+ b = node.getContentsNode();
+ forContainer.startAfter(lparenT);
+ }
+
+ {
+ expressionMode = ExpressionMode.noIn;
+ }
+ fi=forInitializer
+ {
+ expressionMode = ExpressionMode.normal;
+ }
+
+ ( TOKEN_SEMICOLON { forContainer.addItem(fi); }
+ forCondition[forContainer]
+ TOKEN_SEMICOLON
+ forStep[forContainer]
+ | in:TOKEN_KEYWORD_IN
+ {
+ final ExpressionNodeBase leftOfIn;
+ if (fi instanceof ExpressionNodeBase)
+ {
+ leftOfIn = (ExpressionNodeBase) fi;
+ }
+ else
+ {
+ // for...in doesn't allow multiple variable definition in the initializer clause
+ addProblem(new InvalidForInInitializerProblem(node));
+ if (fi instanceof ContainerNode &&
+ fi.getChildCount() > 0 &&
+ ((ContainerNode)fi).getChild(0) instanceof ExpressionNodeBase)
+ {
+ // Recover by taking the first variable initializer and
+ // drop the rest.
+ leftOfIn = (ExpressionNodeBase)((ContainerNode)fi).getChild(0);
+ }
+ else
+ {
+ // No valid variable initializer found: recover by adding
+ // an empty identifier node.
+ leftOfIn = IdentifierNode.createEmptyIdentifierNodeAfterToken((ASToken)lparenT);
+ }
+ }
+ inNode = BinaryOperatorNodeBase.create((ASToken)in, leftOfIn, null);
+ forContainer.addItem(inNode);
+ }
+ e=optExpression
+ { inNode.setRightOperandNode(e); }
+ )? // Make optional for error handling.
+
+ {
+ if (forContainer.getChildCount() == 0 && fi != null)
+ forContainer.addItem(fi);
+ }
+
+ ( rparenT:TOKEN_PAREN_CLOSE
+ {
+ forContainer.endBefore(rparenT);
+ }
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )
+ substatement[b]
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the "initializer" part in a for loop.
+ */
+forInitializer returns [NodeBase n]
+{
+ n = null;
+}
+ : n=variableDefExpression
+ | n=optExpression
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches the "condition" part in a for loop.
+ */
+forCondition[ContainerNode c]
+{
+ ExpressionNodeBase e = null;
+}
+ : e=optExpression
+ {if (e != null) c.addItem(e);}
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches the "step" part in a for loop.
+ */
+forStep[ContainerNode c]
+{
+ ExpressionNodeBase e = null;
+}
+ : e=optExpression
+ {if (e != null) c.addItem(e);}
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a "do...while" statement.
+ */
+doStatement[ContainerNode c]
+{
+ DoWhileLoopNode n = null;
+ ExpressionNodeBase e = null;
+ BlockNode b = null;
+}
+ : doT:TOKEN_KEYWORD_DO
+ {
+ n = new DoWhileLoopNode((ASToken)doT);
+ c.addItem(n);
+ b = n.getContentsNode();
+ }
+
+ innerSubstatement[b]
+
+ TOKEN_KEYWORD_WHILE e=statementParenExpression
+ {
+ n.setConditionalExpression(e);
+ matchOptionalSemicolon();
+ }
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a "while" loop statement.
+ *
+ * while (x > 1) { x--; }
+ */
+whileStatement[ContainerNode c]
+{
+ WhileLoopNode n = null;
+ ExpressionNodeBase e = null;
+ BlockNode b = null;
+}
+ : whileT:TOKEN_KEYWORD_WHILE e=statementParenExpression
+ {
+ n = new WhileLoopNode((ASToken)whileT);
+ n.setConditionalExpression(e);
+ c.addItem(n);
+ b = n.getContentsNode();
+ }
+
+ substatement[b]
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+
+/**
+ * Matches a "break statement" or a "continue statement". For example:
+ *
+ * break;
+ * break innerLoop;
+ * continue;
+ * continue outerLoop;
+ *
+ */
+breakOrContinueStatement[ContainerNode c]
+{
+ IdentifierNode id = null;
+ IterationFlowNode n = null;
+ final ASToken t = LT(1);
+}
+ : ( TOKEN_KEYWORD_CONTINUE | TOKEN_KEYWORD_BREAK )
+ {
+ n = new IterationFlowNode(t);
+ c.addItem(n);
+ afterRestrictedToken(t);
+ }
+
+ // "greedy" mode is required to associate the following ID with the flow control.
+ (options{greedy=true;}:
+ id=identifier
+ { n.setLabel(id); }
+ )?
+ { matchOptionalSemicolon(); }
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a "goto" statement.
+ */
+gotoStatement[ContainerNode c]
+{
+ IdentifierNode id = null;
+ IterationFlowNode n = null;
+ final ASToken t = LT(1);
+}
+ : TOKEN_RESERVED_WORD_GOTO id=identifier
+ {
+ n = new IterationFlowNode(t);
+ c.addItem(n);
+ n.setLabel(id);
+ matchOptionalSemicolon();
+ }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "with" statement.
+ */
+withStatement[ContainerNode c]
+{
+ WithNode n = null;
+ ExpressionNodeBase e = null;
+ BlockNode b = null;
+}
+ : withT:TOKEN_KEYWORD_WITH e=statementParenExpression
+ {
+ n = new WithNode((ASToken)withT);
+ n.setConditionalExpression(e);
+ c.addItem(n);
+ b = n.getContentsNode();
+ }
+ substatement[b]
+ ;
+
+/**
+ * Matches a "try...catch...finally" statement.
+ */
+tryStatement[ContainerNode c]
+{
+ TryNode n = null;
+ BlockNode b = null;
+}
+ : tryT:TOKEN_KEYWORD_TRY
+ {
+ n = new TryNode((ASToken)tryT);
+ b = n.getContentsNode();
+ c.addItem(n);
+ }
+
+ block[b]
+
+ ( options { greedy=true;}:
+ catchBlock[n]
+ )*
+
+ ( options { greedy=true;}:
+ finallyT:TOKEN_KEYWORD_FINALLY
+ {
+ TerminalNode t = new TerminalNode((ASToken)finallyT);
+ n.addFinallyBlock(t);
+ b = t.getContentsNode();
+ }
+ block[b]
+ )?
+ ;
+
+/**
+ * Matches the "catch" block in a "try" statement.
+ */
+catchBlock[TryNode tryNode]
+{
+ CatchNode n = null;
+ ParameterNode arg = null;
+ BlockNode b = null;
+}
+ : catchT:TOKEN_KEYWORD_CATCH TOKEN_PAREN_OPEN
+ { disableSemicolonInsertion(); }
+
+ arg=catchBlockArgument
+ {
+ n = new CatchNode(arg);
+ tryNode.addCatchClause(n);
+ b = n.getContentsNode();
+ n.startBefore(catchT);
+ }
+
+ ( rpT:TOKEN_PAREN_CLOSE
+ {
+ enableSemicolonInsertion();
+ n.endAfter(rpT);
+ }
+
+ exception catch [RecognitionException ex]
+ {handleParsingError(ex); enableSemicolonInsertion(); }
+ )
+
+ block[b]
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the argument in the "try...catch(arg)" statement.
+ */
+catchBlockArgument returns [ParameterNode p]
+{
+ p = null;
+ IdentifierNode name = null;
+ ExpressionNodeBase t = null;
+}
+ : name=identifier
+ { p = new ParameterNode(name); }
+
+ ( colonT:TOKEN_COLON
+ { p.setType((ASToken)colonT, null); }
+ t=type
+ { p.setType((ASToken)colonT, t); }
+ )?
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an "if" statement.
+ */
+ifStatement[ContainerNode c]
+{
+ IfNode i = null;
+ ExpressionNodeBase cond = null;
+ ContainerNode b = null;
+ boolean hasElse = false;
+}
+ : ifT:TOKEN_KEYWORD_IF cond=statementParenExpression
+ {
+ i = new IfNode((ASToken)ifT);
+ ConditionalNode cNode = new ConditionalNode((ASToken)ifT);
+ cNode.setConditionalExpression(cond);
+ b = cNode.getContentsNode();
+ i.addBranch(cNode);
+ c.addItem(i);
+ }
+ innerSubstatement[b]
+
+ (options{greedy=true;}:
+ hasElse=elsePart[i]
+ { if (hasElse == true) return; }
+ )*
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the optional "else" block of an "if" statement.
+ *
+ * @return true if there is an "else" block.
+ */
+elsePart[IfNode i] returns [boolean hasElse]
+{
+ hasElse = false;
+ ContainerNode b = null;
+ ExpressionNodeBase cond = null;
+ ConditionalNode elseIf = null;
+}
+
+ : elseT:TOKEN_KEYWORD_ELSE
+ (options{greedy=true;}:
+ TOKEN_KEYWORD_IF cond=statementParenExpression
+ {
+ elseIf = new ConditionalNode((ASToken) elseT);
+ elseIf.setConditionalExpression(cond);
+ i.addBranch(elseIf);
+ b = elseIf.getContentsNode();
+ }
+ )?
+
+ {
+ if (elseIf == null){
+ hasElse = true;
+ TerminalNode t = new TerminalNode((ASToken) elseT);
+ i.addBranch(t);
+ b = t.getContentsNode();
+ }
+ }
+ substatement[b]
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a "switch" statement.
+ */
+switchStatement[ContainerNode c]
+{
+ SwitchNode sw = null;
+ ExpressionNodeBase e = null;
+}
+ : switchT:TOKEN_KEYWORD_SWITCH e=statementParenExpression
+ {
+ sw = new SwitchNode((ASToken)switchT);
+ c.addItem(sw);
+ if(e != null)
+ sw.setConditionalExpression(e);
+ }
+
+ cases[sw]
+ ;
+
+/**
+ * Matches the "case" block in a "switch" statement.
+ */
+cases[SwitchNode sw]
+{
+ final ContainerNode b = sw.getContentsNode();
+}
+ : TOKEN_BLOCK_OPEN caseClauses[b] TOKEN_BLOCK_CLOSE
+ ;
+
+/**
+ * Matches the "case" clauses in a "switch" statement.
+ */
+caseClauses[ContainerNode swb]
+ : (caseClause[swb])*
+ ;
+
+/**
+ * Matches a single "case" clause in a "switch" statement.
+ */
+caseClause[ContainerNode swb]
+{
+ ExpressionNodeBase e = null;
+ ContainerNode b = null;
+}
+ : caseT:TOKEN_KEYWORD_CASE e=expression colon
+ {
+ ConditionalNode cond = new ConditionalNode((ASToken) caseT);
+ cond.setConditionalExpression(e);
+ swb.addItem(cond);
+ b = cond.getContentsNode();
+ }
+ caseStatementList[b]
+
+ | defaultT:TOKEN_KEYWORD_DEFAULT colon
+ {
+ TerminalNode t = new TerminalNode((ASToken)defaultT);
+ swb.addItem(t);
+ b = t.getContentsNode();
+ }
+ caseStatementList[b]
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a colon token ":" or recover from a missing colon.
+ */
+colon
+ : TOKEN_COLON
+ ;
+ exception catch [RecognitionException ex] { addProblem(unexpectedTokenProblem(LT(1), ASTokenKind.COLON)); }
+
+/**
+ * Matches the statements in a "case" clause.
+ */
+caseStatementList[ContainerNode b]
+ : (directive[b, TOKEN_BLOCK_CLOSE])*
+ ;
+ exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches an identifier token. An identifier can come from different token
+ * types such as:
+ *
+ * - IDENTIFIER
+ * - namespace
+ * - get
+ * - set
+ *
+ * This is because in AS3, these elements are not reserved keyword. However they
+ * have special meaning in some syntactic contexts.
+ * See "AS3 syntax spec - 3.5 Keywords and Punctuators" for details.
+ */
+identifier returns [IdentifierNode n]
+{
+ n = null;
+ final ASToken token = LT(1);
+}
+ : ( TOKEN_IDENTIFIER
+ | TOKEN_RESERVED_WORD_NAMESPACE
+ | TOKEN_RESERVED_WORD_GET
+ | TOKEN_RESERVED_WORD_SET
+ )
+ { n = new IdentifierNode(token); }
+ ;
+ exception
+ catch [NoViableAltException e1] { n = expectingIdentifier(e1); }
+ catch [RecognitionException e2] { n = handleMissingIdentifier(e2); }
+
+/**
+ * Matches an "import-able" name.
+ *
+ * flash.display.Sprite;
+ * flash.events.*;
+ */
+importName returns [ExpressionNodeBase n]
+{
+ n=null;
+ ExpressionNodeBase e = null;
+}
+
+ : n=packageName
+ ( dot:TOKEN_OPERATOR_MEMBER_ACCESS
+ {
+ n = new FullNameNode(n, (ASToken) dot, null);
+ }
+ e=starLiteral
+ {
+ ((FullNameNode)n).setRightOperandNode(e);
+ }
+ )?
+ ;
+ exception catch [RecognitionException ex] { return handleMissingIdentifier(ex, n); }
+
+/**
+ * Matches a restricted name. For example:
+ *
+ * my.package.name.Clock;
+ * private::myPrivateVar;
+ * UnqualifiedTypeClock;
+ *
+ */
+restrictedName returns [ExpressionNodeBase nameExpression]
+{
+ nameExpression = null;
+ IdentifierNode placeHolderRightNode = null;
+ ASToken opToken = null;
+ ExpressionNodeBase part = null;
+}
+ : nameExpression=restrictedNamePart
+
+ // LL(1) grammar can only branch on the next token.
+ // The LA(2) semantic predicate is used to disambiguate:
+ // 1. "foo.bar" - a restricted name consisting two identifiers
+ // 2. "foo.(bar)" - a member expression whose left-hand side is an identifier
+ // and the right-hand side is a parenthesis expression
+ (options { greedy=true; }: { LA(2) != TOKEN_PAREN_OPEN }?
+ {
+ opToken = LT(1);
+
+ // The place-holder node is a safe-net in case parsing the
+ // "right" node fails, so that we will still have a balanced
+ // FullNameNode.
+ placeHolderRightNode = IdentifierNode.createEmptyIdentifierNodeAfterToken(opToken);
+
+ final ExpressionNodeBase nameLeft = nameExpression;
+ }
+ ( TOKEN_OPERATOR_MEMBER_ACCESS
+ { nameExpression = new FullNameNode(nameLeft, opToken, placeHolderRightNode); }
+ | TOKEN_OPERATOR_NS_QUALIFIER
+ { nameExpression = new NamespaceAccessExpressionNode(nameLeft, opToken, placeHolderRightNode); }
+ )
+
+ ( { opToken.getType() == TOKEN_OPERATOR_NS_QUALIFIER && LA(1) == TOKEN_SQUARE_OPEN }?
+ // matches ns::["var_in_ns"]
+ nameExpression=bracketExpression[nameLeft]
+ | part=restrictedNamePart
+ {
+ ((BinaryOperatorNodeBase)nameExpression).setRightOperandNode(part);
+ checkForChainedNamespaceQualifierProblem(opToken, part);
+ }
+ )
+ )*
+ ;
+ exception catch [RecognitionException ex]
+ {
+ if (nameExpression == null)
+ nameExpression = handleMissingIdentifier(ex);
+ else
+ consumeParsingError(ex);
+ }
+
+
+/**
+ * Matches the identifier part of a restricted name. For example:
+ *
+ * private
+ * public
+ * foo
+ * MyType
+ *
+ */
+restrictedNamePart returns [IdentifierNode id]
+{
+ id = null;
+ final ASToken lt = LT(1);
+}
+ : id=identifier
+ | TOKEN_NAMESPACE_NAME
+ { id = new IdentifierNode(lt); }
+ | TOKEN_KEYWORD_SUPER
+ { id = LanguageIdentifierNode.buildSuper(lt); }
+ ;
+ // "identifier", "namespace name" and "super" are all "identifiers" to
+ // the user. So we override the default error handling in order to emit
+ // "expecting identifier but found ..." syntax problem.
+ exception catch [NoViableAltException ex] { id = expectingIdentifier(ex); }
+
+/**
+ * Keep legacy rule for Falcon-JS.
+ */
+typedNameOrStar returns [ExpressionNodeBase n]
+ : n=type
+ ;
+
+/**
+ * Matches a type reference.
+ *
+ * String
+ * int
+ * *
+ * Vector.<Clock>
+ * foo.bar.Vector.<T>
+ *
+ */
+type returns [ExpressionNodeBase n]
+{
+ n = null;
+}
+ : n=starLiteral
+ | n=restrictedName ( n=typeApplication[n] )?
+ ;
+ exception catch [RecognitionException ex] { n = handleMissingIdentifier(ex); }
+
+/**
+ * Matches a "type application" part>
+ *
+ * .<String>
+ * .<Clock>
+ * .<uint>
+ *
+ */
+typeApplication [ExpressionNodeBase root] returns[TypedExpressionNode n]
+{
+ n = null;
+ ExpressionNodeBase t = null;
+ Token closeT = null;
+ enterTypeApplication(root);
+}
+ : openT:TOKEN_TYPED_COLLECTION_OPEN
+ t=type
+ {
+ n = new TypedExpressionNode(root, t, (ASToken)openT);
+ closeT = LT(1);
+ }
+ ( TOKEN_TYPED_COLLECTION_CLOSE | TOKEN_OPERATOR_GREATER_THAN )
+ { n.endAfter(closeT); }
+ ;
+ exception catch [RecognitionException ex] { consumeParsingError(ex); }
+
+
+/**
+ * Matches an optional expression.
+ * @return NilNode or ExpressionNodeBase.
+ */
+optExpression returns[ExpressionNodeBase e]
+{
+ e = null;
+}
+ : (options{greedy=true;}: e=expression)?
+ { if (e == null) e = new NilNode(); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an expression or a comma-separated expression list.
+ */
+expression returns [ExpressionNodeBase n]
+{
+ n = null;
+ ExpressionNodeBase e1 = null;
+}
+ : n=assignmentExpression
+ (options{greedy=true;}:
+ op:TOKEN_COMMA
+ e1=assignmentExpression
+ { n = BinaryOperatorNodeBase.create((ASToken)op,n,e1); }
+ )*
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an "assignment expression".
+ *
+ * According to ASL sytax spec, the productions for an "assignment expression"
+ * is either a "conditional expression" or a "left-hand side expression" followed
+ * by an "assignment operator" and an "assignment expression". However, since
+ * "assignmentExpression" and "conditionaExpression" is ambiguous at indefinite
+ * look-ahead distance, this LL(1) grammar can't decide which alternative to
+ * choose. As a result, the implementation is more lenient in that an AST node
+ * for an assignment binary node will be built even the left-hand side expression
+ * is not a valid "LeftHandSideExpression", such as a constant.
+ *
+ * For example:
+ * <code>100 = "hello";</code>
+ * This statement will be parsed without syntax error, generating tree like:
+ * <pre>
+ * =
+ * / \
+ * 100 "hello"
+ * </pre>
+ *
+ * A possible solution to this is to find out the difference between "conditional
+ * expression" and "left-hand side expression", then insert a semantic predicate
+ * before matching a "assignment operator".
+ */
+assignmentExpression returns [ExpressionNodeBase n]
+{
+ n = null;
+ ASToken op = null;
+ ExpressionNodeBase r = null;
+}
+ : n=condExpr
+ (options{greedy=true;}:
+ op=assignOp
+ r=assignmentRightValue
+ { n = BinaryOperatorNodeBase.create(op,n,r); }
+ )?
+ ;
+
+/**
+ * Matches the right-hand side of an assignment expression.
+ * "public" namespace is allowed as an R-value for backward compatibility.
+ * @see "CMP-335 and ASLSPEC-19"
+ */
+assignmentRightValue returns [ExpressionNodeBase rightExpr]
+{
+ rightExpr = null;
+}
+ : { isNextTokenPublicNamespace() }? p:TOKEN_NAMESPACE_ANNOTATION
+ { rightExpr = new NamespaceIdentifierNode((ASToken)p); }
+ | rightExpr=assignmentExpression
+ ;
+
+assignOp returns [ASToken op]
+{
+ op = LT(1);
+}
+ : TOKEN_OPERATOR_ASSIGNMENT
+ | TOKEN_OPERATOR_LOGICAL_AND_ASSIGNMENT
+ | TOKEN_OPERATOR_LOGICAL_OR_ASSIGNMENT
+ | TOKEN_OPERATOR_PLUS_ASSIGNMENT
+ | TOKEN_OPERATOR_MINUS_ASSIGNMENT
+ | TOKEN_OPERATOR_MULTIPLICATION_ASSIGNMENT
+ | TOKEN_OPERATOR_DIVISION_ASSIGNMENT
+ | TOKEN_OPERATOR_MODULO_ASSIGNMENT
+ | TOKEN_OPERATOR_BITWISE_AND_ASSIGNMENT
+ | TOKEN_OPERATOR_BITWISE_OR_ASSIGNMENT
+ | TOKEN_OPERATOR_BITWISE_XOR_ASSIGNMENT
+ | TOKEN_OPERATOR_BITWISE_LEFT_SHIFT_ASSIGNMENT
+ | TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT_ASSIGNMENT
+ | TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT
+ ;
+
+/**
+ * Matches a ternary expression such as:
+ *
+ * (x > 2) ? "greater" : "smaller"
+ */
+condExpr returns [ExpressionNodeBase n]
+{
+ n = null;
+ ExpressionNodeBase trueExpr = null;
+ ExpressionNodeBase falseExpr = null;
+ TernaryOperatorNode ternary = null;
+}
+ : n=binaryExpr
+ ( op:TOKEN_OPERATOR_TERNARY
+ {
+ ternary = new TernaryOperatorNode((ASToken)op,n,null,null);
+ n = ternary;
+ }
+ trueExpr=assignmentExpression { ternary.setLeftOperandNode(trueExpr); }
+ TOKEN_COLON
+ falseExpr=assignmentExpression { ternary.setRightOperandNode(falseExpr); }
+ )?
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ ;
+
+/**
+ * Binary expression uses operator precedence parser in BaseASParser.
+ */
+binaryExpr returns [ExpressionNodeBase n]
+{
+ n = precedenceParseExpression(4);
+ if (true) return n;
+}
+ : fakeExpr
+ ;
+
+/**
+ * fakeExpr simulates the set of allowable follow tokens in an expression context, which allows antlr to function.
+ * It is unreachable.
+ */
+fakeExpr
+{
+ ExpressionNodeBase n = null;
+}
+ : n=unaryExpr (options{greedy=true;}: binaryOperators fakeExpr)?
+ ;
+
+/**
+ * Declares all the binary operators.
+ */
+binaryOperators
+ : TOKEN_OPERATOR_LOGICAL_OR
+ | TOKEN_OPERATOR_LOGICAL_AND
+ | TOKEN_OPERATOR_BITWISE_OR
+ | TOKEN_OPERATOR_BITWISE_XOR
+ | TOKEN_OPERATOR_BITWISE_AND
+ | TOKEN_OPERATOR_EQUAL
+ | TOKEN_OPERATOR_NOT_EQUAL
+ | TOKEN_OPERATOR_STRICT_EQUAL
+ | TOKEN_OPERATOR_STRICT_NOT_EQUAL
+ | TOKEN_OPERATOR_GREATER_THAN
+ | TOKEN_OPERATOR_GREATER_THAN_EQUALS
+ | TOKEN_OPERATOR_LESS_THAN
+ | TOKEN_OPERATOR_LESS_THAN_EQUALS
+ | TOKEN_KEYWORD_INSTANCEOF
+ | TOKEN_KEYWORD_IS
+ | TOKEN_KEYWORD_AS
+ | TOKEN_KEYWORD_IN
+ | TOKEN_OPERATOR_BITWISE_LEFT_SHIFT
+ | TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT
+ | TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT
+ | TOKEN_OPERATOR_MINUS
+ | TOKEN_OPERATOR_PLUS
+ | TOKEN_OPERATOR_DIVISION
+ | TOKEN_OPERATOR_MODULO
+ | TOKEN_OPERATOR_STAR
+ ;
+
+/**
+ * Matches a "prefix expression".
+ *
+ * delete x[i]
+ * ++i
+ * --i
+ *
+ * The distinction between this rule and "unary expression" makes the parser
+ * more strict about what expressions can follow what tokens.
+ */
+prefixExpression returns [ExpressionNodeBase n]
+{
+ n = null;
+ final ASToken op = LT(1);
+}
+ : n=postfixExpr
+ | ( TOKEN_KEYWORD_DELETE n=postfixExpr
+ | TOKEN_OPERATOR_INCREMENT n=lhsExpr
+ | TOKEN_OPERATOR_DECREMENT n=lhsExpr
+ )
+ {
+ if (n == null)
+ n = IdentifierNode.createEmptyIdentifierNodeAfterToken(op);
+ n = UnaryOperatorNodeBase.createPrefix(op, n);
+ }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "unary expression".
+ *
+ * This rule is called out of the precedence parser in BaseASParser.
+ * If you need to change the name of this rule, you'll also need to update
+ * the base class.
+ */
+unaryExpr returns [ExpressionNodeBase n]
+{
+ n = null;
+ ASToken op = null;
+}
+ : ( n=prefixExpression
+ | op=unaryOp n=unaryExpr
+ {
+ if (n == null)
+ n = IdentifierNode.createEmptyIdentifierNodeAfterToken(op);
+ n = UnaryOperatorNodeBase.createPrefix(op, n);
+ }
+ )
+ (options { greedy = true; }:
+ n=propertyAccessExpression[n]
+ | n=arguments[n]
+ )*
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a unary operator.
+ */
+unaryOp returns [ASToken op]
+{
+ op = LT(1);
+}
+ : TOKEN_KEYWORD_VOID
+ | TOKEN_KEYWORD_TYPEOF
+ | TOKEN_OPERATOR_PLUS
+ | TOKEN_OPERATOR_MINUS
+ | TOKEN_OPERATOR_BITWISE_NOT
+ | TOKEN_OPERATOR_LOGICAL_NOT
+ ;
+
+/**
+ * Matches "Postfix Expression" such as: i++, i--
+ *
+ * Since ECMA semicolon insertion rule requires that if a "++" or "--" is not
+ * on the same line as its left-hand side expression, a semicolon is inserted
+ * before the "--" or "++" token. The side-effect of the inserted semicolon is
+ * to terminate the expression parsing at this point. As a result, we have to
+ * return "null" to stop parsing the expression. An upstream production will
+ * pickup the "--" or "++" by starting a new expression.
+ *
+ * A good test case for such situation would be:
+ *
+ * var i = 99
+ * ++i
+ *
+ * A semicolon should be inserted after "99", resulting in two separate ASTs
+ * for "var i=99" and "++i". Otherwise, "var i=99++" is a bad recognition.
+ */
+postfixExpr returns [ExpressionNodeBase n]
+{
+ n = null;
+ boolean isSemicolonInserted = false;
+}
+ : n=lhsExpr
+ {
+ final ASToken nextToken = LT(1);
+ if (nextToken.getType() == ASTokenTypes.TOKEN_OPERATOR_INCREMENT ||
+ nextToken.getType() == ASTokenTypes.TOKEN_OPERATOR_DECREMENT)
+ isSemicolonInserted = beforeRestrictedToken(nextToken);
+ }
+ ( {!isSemicolonInserted}? (options{greedy=true;}: n=postfixOp[n])?
+ | // Do nothing if optional semicolon is inserted.
+ // This empty alternative is required because otherwise a semantic
+ // predicate exception will be thrown, leading the code enter error
+ // handling, which will create incorrect tree shape.
+ )
+ ;
+
+/**
+ * Matches a "postfix" operator such as: ++, --
+ * The parameter "n" is the expression the postfix operator acts on.
+ * The return value "top" is a UnaryOperatorNode.
+ */
+postfixOp[ExpressionNodeBase n] returns [UnaryOperatorNodeBase top]
+{
+ final ASToken op = LT(1);
+ top = null;
+}
+ : ( TOKEN_OPERATOR_INCREMENT
+ | TOKEN_OPERATOR_DECREMENT )
+ { top = UnaryOperatorNodeBase.createPostfix(op, n); }
+ ;
+
+/**
+ * Matches a primary expression.
+ */
+primaryExpression returns [ExpressionNodeBase n]
+{
+ n = null;
+ ASToken token = LT(1);
+}
+ : TOKEN_KEYWORD_NULL
+ { n = new LiteralNode(token, LiteralType.NULL); }
+ | TOKEN_KEYWORD_TRUE
+ { n = new LiteralNode(token, LiteralType.BOOLEAN); }
+ | TOKEN_KEYWORD_FALSE
+ { n = new LiteralNode(token, LiteralType.BOOLEAN); }
+ | TOKEN_KEYWORD_THIS
+ { n = LanguageIdentifierNode.buildThis(token); }
+ | token=numericLiteral
+ { n = new NumericLiteralNode(token); }
+ | TOKEN_LITERAL_STRING
+ { n = new LiteralNode(token, LiteralType.STRING); }
+ | TOKEN_VOID_0
+ { n = new LiteralNode(token, LiteralType.OBJECT); }
+ | TOKEN_LITERAL_REGEXP
+ { n = new RegExpLiteralNode(token, this); }
+ | { n = new ArrayLiteralNode(); } arrayInitializer[(ArrayLiteralNode)n]
+ | n=objectLiteralExpression
+ | n=xmlInitializer { leaveXMLLiteral(); }
+ | n=xmlListInitializer { leaveXMLLiteral(); }
+ | n=functionExpression
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a numeric literal token.
+ */
+numericLiteral returns [ASToken op]
+{
+ op = LT(1);
+}
+ : TOKEN_LITERAL_NUMBER
+ | TOKEN_LITERAL_HEX_NUMBER
+ ;
+
+/**
+ * Matches an "object literal".
+ */
+objectLiteralExpression returns [ExpressionNodeBase n]
+{
+ ObjectLiteralNode o = new ObjectLiteralNode();
+ n = o;
+ ContainerNode b = o.getContentsNode();
+ ExpressionNodeBase vp = null;
+}
+ : openT:TOKEN_BLOCK_OPEN { n.startBefore(openT); }
+ ( vp=objectLiteralValuePair { b.addItem(vp); }
+ ( TOKEN_COMMA vp=objectLiteralValuePair
+ { if (vp != null) b.addItem(vp); }
+ exception catch [RecognitionException ex]
+ { handleParsingError(ex); }
+ )*
+ )?
+ closeT:TOKEN_BLOCK_CLOSE { n.endAfter(closeT); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "field" in an "object literal".
+ * The "field" can be gated with a "config condition". If the condition is
+ * "false", return "null" value; Otherwise, return the expression node of the
+ * key/value pair.
+ */
+objectLiteralValuePair returns [ExpressionNodeBase n]
+{
+ ExpressionNodeBase v = null;
+ n = null;
+ boolean condition = true;
+ ASToken numberT = null;
+}
+ : ( { isConfigCondition() && LA(4) != TOKEN_COLON && LA(4) != TOKEN_BLOCK_CLOSE }?
+ condition=configCondition
+ | // Skip - no config varaible.
+ )
+
+ // Field name:
+ ( nameT:TOKEN_IDENTIFIER
+ { n = new NonResolvingIdentifierNode(nameT != null ? nameT.getText() : "",nameT); }
+ | numberT=numericLiteral
+ { n = new NumericLiteralNode(numberT); }
+ | stringT:TOKEN_LITERAL_STRING
+ { n = new LiteralNode(LiteralType.STRING, stringT); }
+ )
+
+ c:TOKEN_COLON
+
+ // Field value:
+ v=assignmentExpression
+ {
+ if (condition)
+ n = new ObjectLiteralValuePairNode((ASToken)c,n,v);
+ else
+ n = null;
+ }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+
+/**
+ * Matches array literal. For example:
+ *
+ * []
+ * ["hello", 3.14, foo]
+ * [ , x, y]
+ * [ , ,]
+ *
+ * "Holes" (empty array elements) are allowed. See "arrayElements" rule for details.
+ */
+arrayInitializer [ArrayLiteralNode node]
+ {
+ final ContainerNode contents = node.getContentsNode();
+ }
- : open:TOKEN_SQUARE_OPEN { contents.startBefore(open); }
++ : open:TOKEN_SQUARE_OPEN { node.startBefore(open); contents.startAfter(open); }
+ arrayElements[contents]
- close:TOKEN_SQUARE_CLOSE { contents.endAfter(close); }
++ close:TOKEN_SQUARE_CLOSE { node.endAfter(close); contents.endBefore(close); }
+ ;
+ exception catch [RecognitionException ex]
+ {
+ // Do not convert keywords to identifiers.
+ // This is for recovering from:
+ // [
+ // var x:int;
+ handleParsingError(ex);
+ // Notify the caller that the array literal failed.
+ throw ex;
+ }
+
+/**
+ * Matches all the elements in an "arrayInitializer". For example:
+ *
+ * x,y,z
+ * x,,
+ * (empty)
+ * ,,,,,,
+ *
+ * "Holes" are compiled as "undefined".
+ * Leading "holes" are kept as "undefined" values.
+ * "Holes" in the middle are kept as "undefined" values.
+ * Trailing "holes" are kept as "undefined" values except that the last "hole"
+ * is dropped.
+ *
+ * For example: x=[,,1,,,2,,,] has 2 leading holes, 2 holes in the middle, and 3
+ * holes at the end. All the holes except for the last trailing holes are kept
+ * as undefined values:
+ *
+ * x[0]=undefined
+ * x[1]=undefined
+ * x[2]=1
+ * x[3]=undefined
+ * x[4]=undefined
+ * x[5]=2
+ * x[6]=undefined
+ * x[7]=undefined
+ * (end)
+ *
+ */
+arrayElements[ContainerNode b]
+{
+ ExpressionNodeBase e = null;
+}
+ : ( TOKEN_COMMA { b.addItem(new NilNode()); } )*
+ ( { LA(1) != TOKEN_SQUARE_CLOSE}?
+ e=arrayElement { b.addItem(e); /*1*/ }
+ ( TOKEN_COMMA
+ ( { LA(1) != TOKEN_SQUARE_CLOSE && LA(1) != TOKEN_COMMA }? e=arrayElement { b.addItem(e); /*2*/}
+ | { LA(1) != TOKEN_SQUARE_CLOSE && LA(1) == TOKEN_COMMA }? { b.addItem(new NilNode()); }
+ | // Next token is "]" - pass.
+ )
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )*
+ | // Next token is "]" - the initializer is a list of commas: [,,,,,]
+ )
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an "array element" in an "array literal". An array element can be
+ * gated with a config variable. If the config variable is false, the element
+ * will be matched as a "hole" in the array literal.
+ */
+arrayElement returns [ExpressionNodeBase e]
+{
+ e = null;
+ boolean c = true; // config variable
+}
+ : ( { isConfigCondition() && LA(4) != TOKEN_COMMA && LA(4) != TOKEN_SQUARE_CLOSE }?
+ c=configCondition
+ | // Skip - no config varaible.
+ )
+ e=assignmentExpression
+ {
+ if (!c)
+ {
+ final NilNode nilNode = new NilNode();
+ nilNode.span(e, e);
+ e = nilNode;
+ }
+ }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "vector initializer".
+ */
+vectorLiteralExpression returns [VectorLiteralNode node]
+{
+ node = new VectorLiteralNode();
+ ContainerNode b = node.getContentsNode();
+ ExpressionNodeBase type = null;
+}
+ : open:TOKEN_TYPED_LITERAL_OPEN { node.endAfter(open); }
+ type=type { node.setCollectionTypeNode(type); }
+ close:TOKEN_TYPED_LITERAL_CLOSE { node.endAfter(close); }
+ openT:TOKEN_SQUARE_OPEN { b.startAfter(openT); }
+ (vectorLiteralContents[b])?
+ closeT:TOKEN_SQUARE_CLOSE { b.endBefore(closeT); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "vector element" in a vector initializer.
+ */
+vectorLiteralContents[ContainerNode b]
+{
+ ExpressionNodeBase e = null;
+}
+ : e=arrayElement { b.addItem(e); }
+ ( TOKEN_COMMA
+ {
+ // A trailing comma is allowed, but
+ // an intermediate comma is not.
+ if ( LA(1) != TOKEN_SQUARE_CLOSE ){
+ e=arrayElement();
+ b.addItem(e);
+ }
+ }
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+ )*
+ ;
+
+/**
+ * Matches "XML literal expression".
+ */
+xmlInitializer returns [XMLLiteralNode n]
+{
+ n = new XMLLiteralNode();
+ final ASToken lt = LT(1);
+ enterXMLLiteral();
+}
+ : { LA(1) == TOKEN_E4X_COMMENT ||
+ LA(1) == TOKEN_E4X_CDATA ||
+ LA(1) == TOKEN_E4X_PROCESSING_INSTRUCTION
+ }?
+ xmlMarkup
+ { n.appendLiteralToken(lt); }
+ xmlWhitespace[n]
+ | (options { greedy = true; }: xmlElementContent[n] )+
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Match XML whitespace tokens. If {@code ContainerNode} is null, drop the
+ * whitespace tokens.
+ */
+xmlWhitespace [BaseLiteralContainerNode n]
+ : (options { greedy = true; }:
+ ws:TOKEN_E4X_WHITESPACE
+ {
+ if (n != null)
+ n.appendLiteralToken((ASToken)ws);
+ }
+ )*
+ ;
+
+/**
+ * Matches an XML comment, XML CDATA or XML PI token.
+ */
+xmlMarkup
+ : TOKEN_E4X_COMMENT
+ | TOKEN_E4X_CDATA
+ | TOKEN_E4X_PROCESSING_INSTRUCTION
+ ;
+
+/**
+ * Matches an E4X token that can be aggregated in "xmlTokenAggregated".
+ * Instead of a full recursive descent parser for XML tags, the base class
+ * uses a tag name stack to check matching tags. A complete parse tree with
+ * XML structure is unnecessary and adds extra overhead to the parser.
+ */
+xmlToken [BaseLiteralContainerNode n]
+{
+ final ASToken t = LT(1);
+}
+ : ( xmlMarkup
+ | TOKEN_E4X_WHITESPACE
+ | TOKEN_E4X_ENTITY
+ | TOKEN_E4X_DECIMAL_ENTITY
+ | TOKEN_E4X_HEX_ENTITY
+ | TOKEN_E4X_TEXT
+ | TOKEN_E4X_STRING
+ )
+ { n.appendLiteralToken(t); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an XML tag.
+ *
+ * <foo>
+ * </foo>
+ * <foo />
+ * <{name}>
+ * <foo name={nameValue}>
+ * <foo {attrs}>
+ */
+xmlTag [BaseLiteralContainerNode n]
+ : ( openT:TOKEN_E4X_OPEN_TAG_START // <foo
+ {
+ xmlTagOpen((ASToken)openT);
+ n.appendLiteralToken((ASToken)openT);
+ }
+ | closeT:TOKEN_E4X_CLOSE_TAG_START // </foo
+ {
+ xmlTagClose((ASToken)closeT);
+ n.appendLiteralToken((ASToken)closeT);
+ }
+ | openNoNameT:HIDDEN_TOKEN_E4X // <
+ {
+ xmlTagOpenBinding((ASToken)openNoNameT);
+ n.appendLiteralToken((ASToken)openNoNameT);
+ }
+
+ // Note about compatibility:
+ // x = < tagName foo="bar" />;
+ // ^
+ // Whitespace isn't allowed here according to ASL spec.
+ // Avik from AS3 spec team confirmed it was a bug that the old ASC allowed it.
+
+ ( xmlContentBlock[n]
+ | nT:TOKEN_E4X_NAME
+ { n.appendLiteralToken((ASToken)nT); }
+ )
+ )
+ xmlWhitespace[n]
+ ( ( { isXMLAttribute() }? xmlAttribute[n]
+ | xmlContentBlock[n] )
+ xmlWhitespace[n]
+ )*
+ ( endT:TOKEN_E4X_TAG_END // >
+ { n.appendLiteralToken((ASToken)endT); }
+ | emptyEndT:TOKEN_E4X_EMPTY_TAG_END // />
+ {
+ xmlEmptyTagEnd((ASToken)emptyEndT);
+ n.appendLiteralToken((ASToken)emptyEndT);
+ }
+ )
+ ;
+
+/**
+ * Matches an XML attribute.
+ *
+ * name="value"
+ * name='value'
+ * name={value}
+ * {name}="value"
+ * {name}='value'
+ * {name}={value}
+ */
+xmlAttribute [BaseLiteralContainerNode n]
+ : ( nT:TOKEN_E4X_NAME
+ { n.appendLiteralToken((ASToken)nT); }
+ | nsT:TOKEN_E4X_XMLNS
+ { n.appendLiteralToken((ASToken)nsT); }
+ | xmlAttributeBlock[n]
+ )
+ ( dT:TOKEN_E4X_NAME_DOT
+ { n.appendLiteralToken((ASToken)dT); }
+ dnT:TOKEN_E4X_DOTTED_NAME_PART
+ { n.appendLiteralToken((ASToken)dnT); }
+ )*
+ xmlWhitespace[n]
+ eqT:TOKEN_E4X_EQUALS
+ { n.appendLiteralToken((ASToken)eqT); }
+ xmlWhitespace[n]
+ (options { greedy = true; }:
+ strT:TOKEN_E4X_STRING
+ { n.appendLiteralToken((ASToken)strT); }
+ | eT:TOKEN_E4X_ENTITY
+ { n.appendLiteralToken((ASToken)eT); }
+ | hexT:TOKEN_E4X_HEX_ENTITY
+ { n.appendLiteralToken((ASToken)hexT); }
+ | xmlContentBlock[n]
+ )+
+ ;
+
+/**
+ * Matches an expression block in XML literals.
+ *
+ * <foo>{ this.fooValue }</foo>
+ */
+xmlElementContent [BaseLiteralContainerNode n]
+ : xmlToken[n]
+ | xmlContentBlock[n]
+ | xmlTag[n]
+ ;
+
+/**
+ * Matches an E4X XML list expression.
+ */
+xmlListInitializer returns [XMLListLiteralNode n]
+{
+ n = new XMLListLiteralNode();
+ enterXMLLiteral();
+}
+ : xmlListT:TOKEN_LITERAL_XMLLIST
+ { n.getContentsNode().addItem(new LiteralNode(LiteralType.XML, xmlListT)); }
+ ( xmlElementContent[n] )*
+ closeT: TOKEN_E4X_XMLLIST_CLOSE
+ { n.getContentsNode().addItem(new LiteralNode(LiteralType.XML, closeT)); }
+ xmlWhitespace[null]
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a binding expression in an XML literal.
+ */
+xmlContentBlock[BaseLiteralContainerNode n]
+{
+ ExpressionNodeBase e = null;
+}
+ : TOKEN_E4X_BINDING_OPEN
+ e=expression
+ {
+ if(e != null)
+ n.getContentsNode().addItem(e);
+ }
+ TOKEN_E4X_BINDING_CLOSE
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+
+/**
+ * Matches a binding expression in an XML literal attribute name.
+ */
+xmlAttributeBlock[BaseLiteralContainerNode n]
+{
+ ExpressionNodeBase e = null;
+}
+ : TOKEN_E4X_BINDING_OPEN
+ e=lhsExpr
+ {
+ if(e != null)
+ n.getContentsNode().addItem(e);
+ }
+ TOKEN_E4X_BINDING_CLOSE
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+
+/**
+ * Matches a left-hand side (of asssignment) expression.
+ */
+lhsExpr returns [ExpressionNodeBase n]
+{
+ n = null;
+}
+ : ( n=newExpression
+ | n=parenExpression
+ | n=nameExpression
+ | n=primaryExpression
+ | n=xmlAttributeName
+ )
+ (options { greedy = true; }:
+ n=propertyAccessExpression[n]
+ | n=arguments[n]
+ )*
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a member expression. See ASL syntax spec for details.
+ */
+memberExpression returns [ExpressionNodeBase n]
+ : ( n=primaryExpression
+ | n=parenExpression
+ | n=propertyName
+ | n=newExpression
+ )
+ ( options { greedy = true; }: n=propertyAccessExpression[n] )*
+ ;
+
+/**
+ * Matches a new expression. See ASL syntax spec for details.
+ */
+newExpression returns[ExpressionNodeBase n]
+{
+ n = null;
+}
+ : newT:TOKEN_KEYWORD_NEW
+ ( { LA(1) != TOKEN_KEYWORD_FUNCTION }?
+ ( n=vectorLiteralExpression
+ | n=memberExpression
+ )
+ {
+ if (n == null)
+ n= handleMissingIdentifier(null);
+ else
+ n = FullNameNode.toMemberAccessExpressionNode(n);
+ n = new FunctionCallNode((ASToken)newT, n);
+ }
+ (options{greedy=true;}: n=arguments[n])?
+ | n=functionExpression { n = new FunctionCallNode((ASToken)newT, n); }
+ )
+ exception catch [RecognitionException ex] {
+ //if we have the 'new' keyword, but no expression, drop in a dummy identifier
+ if(newT != null && n == null) {
+ IdentifierNode identifier = handleMissingIdentifier(ex);
+ if(identifier != null) {
+ //if we're here, that means identifier fixup is turned on
+ n = new FunctionCallNode((ASToken)newT, identifier);
+ }
+ } else {
+ handleParsingError(ex);
+ }
+ }
+ ;
+
+/**
+ * Matches an expression with parenthesis.
+ *
+ * (id)
+ * (1 + 2)
+ * (name == "hello")
+ *
+ */
+parenExpression returns[ExpressionNodeBase n]
+{
+ n = null;
+}
+ : TOKEN_PAREN_OPEN n=expression TOKEN_PAREN_CLOSE
+ { if(n != null) n.setHasParenthesis(true); }
+ ;
+ exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a property name in a member expression.
+ */
+propertyName returns [ExpressionNodeBase n]
+{
+ n = null;
+}
+ : n=starLiteral // *
+ | n=restrictedName // qualified & unqualified name
+ | n=xmlAttributeName // e4x attribute
+ ;
+
+/**
+ * This is a non-greedy and non-aggregating version of "restricted name".
+ * It is defined in addition to "propertyName" in order to get correct
+ * precedence in the name expressions and expected tree shapes.
+ */
+nameExpression returns[ExpressionNodeBase n]
+ { n = null; }
+
+ : n=identifier
+ | n=starLiteral
+ | superT:TOKEN_KEYWORD_SUPER
+ { n = LanguageIdentifierNode.buildSuper((IASToken)superT); }
+ | nsT:TOKEN_NAMESPACE_NAME
+ {
+ n = new NamespaceIdentifierNode((ASToken)nsT);
+ ((NamespaceIdentifierNode)n).setIsConfigNamespace(isConfigNamespace((NamespaceIdentifie
<TRUNCATED>
[05/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - TestSourceMapStatements: added
block open { to tested mappings
Posted by cd...@apache.org.
TestSourceMapStatements: added block open { to tested mappings
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/c22e5a07
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/c22e5a07
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/c22e5a07
Branch: refs/heads/feature/maven-migration-test
Commit: c22e5a075e3fc760b68fd273fcfcdb1f3c389f3b
Parents: 6705005
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 15:54:21 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 15:54:21 2016 -0700
----------------------------------------------------------------------
.../codegen/js/sourcemaps/TestSourceMapStatements.java | 9 +++++++++
1 file changed, 9 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c22e5a07/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
index 5d11227..436ee15 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
@@ -127,6 +127,7 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 18, 0, 36, 0, 38); // ;
assertMapping(node, 0, 27, 0, 45, 0, 47); // ;
assertMapping(node, 0, 32, 0, 50, 0, 52); // )
+ assertMapping(node, 0, 34, 0, 52, 0, 53); // {
}
@Test
@@ -153,6 +154,7 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 5, 0, 5, 0, 6); // ;
assertMapping(node, 0, 6, 0, 6, 0, 7); // ;
assertMapping(node, 0, 7, 0, 7, 0, 9); // )
+ assertMapping(node, 0, 9, 0, 9, 0, 10); // {
}
@Test
@@ -165,6 +167,7 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
assertMapping(node, 0, 14, 0, 32, 0, 36); // in
assertMapping(node, 0, 21, 0, 39, 0, 41); // )
+ assertMapping(node, 0, 23, 0, 41, 0, 42); // {
}
@Test
@@ -235,6 +238,7 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
assertMapping(node, 0, 4, 0, 4, 0, 5); // a
assertMapping(node, 0, 5, 0, 5, 0, 7); // )
+ assertMapping(node, 0, 7, 0, 7, 0, 8); // {
}
@Test
@@ -247,7 +251,9 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
assertMapping(node, 0, 4, 0, 4, 0, 5); // a
assertMapping(node, 0, 5, 0, 5, 0, 7); // )
+ assertMapping(node, 0, 7, 0, 7, 0, 8); // {
assertMapping(node, 0, 16, 2, 2, 2, 7); // else
+ assertMapping(node, 0, 21, 2, 7, 2, 8); // {
}
@Test
@@ -261,9 +267,12 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
assertMapping(node, 0, 4, 0, 4, 0, 5); // a
assertMapping(node, 0, 5, 0, 5, 0, 7); // )
+ assertMapping(node, 0, 7, 0, 7, 0, 8); // {
assertMapping(node, 0, 16, 2, 2, 2, 11); // else if(
assertMapping(node, 0, 26, 2, 12, 2, 14); // )
+ assertMapping(node, 0, 28, 2, 14, 2, 15); // {
assertMapping(node, 0, 37, 4, 2, 4, 7); // else
+ assertMapping(node, 0, 42, 4, 7, 4, 8); // {
}
@Test
[04/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - JSEmitter: overrides
emitBlockOpen() and emitBlockClose() so that it can generate source maps
Posted by cd...@apache.org.
JSEmitter: overrides emitBlockOpen() and emitBlockClose() so that it can generate source maps
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/6705005c
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/6705005c
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/6705005c
Branch: refs/heads/feature/maven-migration-test
Commit: 6705005c66ea099c9c3e8010731731ac50d931d0
Parents: 8c39361
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 15:42:33 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 15:42:33 2016 -0700
----------------------------------------------------------------------
.../compiler/internal/codegen/js/JSEmitter.java | 18 ++++++++
.../codegen/js/jx/BlockCloseEmitter.java | 43 ++++++++++++++++++++
.../codegen/js/jx/BlockOpenEmitter.java | 43 ++++++++++++++++++++
3 files changed, 104 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/6705005c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
index a50e288..1a73cf6 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
@@ -30,6 +30,8 @@ import org.apache.flex.compiler.common.ISourceLocation;
import org.apache.flex.compiler.definitions.ITypeDefinition;
import org.apache.flex.compiler.internal.codegen.as.ASEmitter;
import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.jx.BlockCloseEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.BlockOpenEmitter;
import org.apache.flex.compiler.internal.codegen.js.jx.DoWhileLoopEmitter;
import org.apache.flex.compiler.internal.codegen.js.jx.DynamicAccessEmitter;
import org.apache.flex.compiler.internal.codegen.js.jx.ForLoopEmitter;
@@ -82,6 +84,8 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
{
private JSSessionModel model;
+ public BlockOpenEmitter blockOpenEmitter;
+ public BlockCloseEmitter blockCloseEmitter;
public NumericLiteralEmitter numericLiteralEmitter;
public ParametersEmitter parametersEmitter;
public ParameterEmitter parameterEmitter;
@@ -126,6 +130,8 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
model = new JSSessionModel();
sourceMapMappings = new ArrayList<SourceMapMapping>();
+ blockOpenEmitter = new BlockOpenEmitter(this);
+ blockCloseEmitter = new BlockCloseEmitter(this);
numericLiteralEmitter = new NumericLiteralEmitter(this);
parametersEmitter = new ParametersEmitter(this);
parameterEmitter = new ParameterEmitter(this);
@@ -305,6 +311,18 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
interationFlowEmitter.emit(node);
}
+ @Override
+ public void emitBlockOpen(IContainerNode node)
+ {
+ blockOpenEmitter.emit(node);
+ }
+
+ @Override
+ public void emitBlockClose(IContainerNode node)
+ {
+ blockCloseEmitter.emit(node);
+ }
+
public void pushSourceMapName(ISourceLocation node)
{
boolean isValidMappingScope = node instanceof ITypeNode
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/6705005c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java
new file mode 100644
index 0000000..3099eda
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.js.jx;
+
+import org.apache.flex.compiler.codegen.ISubEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+
+public class BlockCloseEmitter extends JSSubEmitter implements
+ ISubEmitter<IContainerNode>
+{
+ public BlockCloseEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+ @Override
+ public void emit(IContainerNode node)
+ {
+ startMapping(node);
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ endMapping(node);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/6705005c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockOpenEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockOpenEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockOpenEmitter.java
new file mode 100644
index 0000000..5487d9c
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockOpenEmitter.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.js.jx;
+
+import org.apache.flex.compiler.codegen.ISubEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+
+public class BlockOpenEmitter extends JSSubEmitter implements
+ ISubEmitter<IContainerNode>
+{
+ public BlockOpenEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+ @Override
+ public void emit(IContainerNode node)
+ {
+ startMapping(node, node.getLine(), node.getColumn() - 1);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ endMapping(node);
+ }
+}
[11/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - Merge branches 'develop' and
'feature/maven-migration-test' of
https://git-wip-us.apache.org/repos/asf/flex-falcon into
feature/maven-migration-test
Posted by cd...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/java/org/apache/flex/compiler/common/ISourceLocation.java
----------------------------------------------------------------------
diff --cc compiler/src/main/java/org/apache/flex/compiler/common/ISourceLocation.java
index 738bdf3,0000000..25f6b6d
mode 100644,000000..100644
--- a/compiler/src/main/java/org/apache/flex/compiler/common/ISourceLocation.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/ISourceLocation.java
@@@ -1,75 -1,0 +1,85 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.common;
+
+/**
+ * This interface provides information about where something
+ * (a token, a tag, an attribute, a node, a definition, etc.)
+ * appears in source code.
+ * <p>
+ * Its primary purpose is for problem reporting.
+ * The start and end offsets are used to highlight
+ * a soruce range in the Flash Builder editor.
+ * The line and column numbers are used by command-line
+ * tools to report problems.
+ */
+public interface ISourceLocation
+{
+ /**
+ * Indicates an unknown or implicit starting offset, ending offset,
+ * line number, or column number.
+ */
+ static final int UNKNOWN = -1;
+
+ /**
+ * Gets the normalized source path.
+ */
+ String getSourcePath();
+
+ /**
+ * Gets the local starting offset. It is zero-based.
+ */
+ int getStart();
+
+ /**
+ * Gets the local ending offset. It is zero-based.
+ */
+ int getEnd();
+
+ /**
+ * Gets the local line number. It is zero-based.
+ */
+ int getLine();
+
+ /**
+ * Gets the local column number. It is zero-based.
+ */
+ int getColumn();
+
+ /**
++ * Gets the local line number at the end. It is zero-based.
++ */
++ int getEndLine();
++
++ /**
++ * Gets the local column number at the end. It is zero-based.
++ */
++ int getEndColumn();
++
++ /**
+ * Gets the absolute starting offset. It is zero-based.
+ */
+ int getAbsoluteStart();
+
+ /**
+ * Gets the absolute starting offset. It is zero-based.
+ */
+ int getAbsoluteEnd();
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java
----------------------------------------------------------------------
diff --cc compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java
index 88998b7,0000000..0d0e1b0
mode 100644,000000..100644
--- a/compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java
@@@ -1,361 -1,0 +1,415 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.common;
+
+import org.apache.flex.utils.FilenameNormalization;
+
+/**
+ * Common class to store file/location information across all source types
+ * such as AS, CSS etc
+ */
+public class SourceLocation implements ISourceLocation
+{
+ /**
+ * Constructor for a known source location.
+ */
+ public SourceLocation(String sourcePath, int start, int end, int line, int column)
+ {
+ this.sourcePath = sourcePath;
+ this.start = start;
+ this.end = end;
+ this.line = line;
+ this.column = column;
++ this.endLine = UNKNOWN;
++ this.endColumn = UNKNOWN;
+ }
+
+ /**
+ * Copy Constructor for a known source location.
+ */
+ public SourceLocation(ISourceLocation location)
+ {
+ this(location.getSourcePath(),
+ location.getStart(),
+ location.getEnd(),
+ location.getLine(),
+ location.getColumn());
+ }
+
+ /**
+ * Constructor for an unknown source location.
+ */
+ public SourceLocation()
+ {
+ this(null, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN);
+ }
+
+ /**
+ * Source path.
+ */
+ private String sourcePath;
+
+ /**
+ * Zero-based starting offset.
+ * <p>
+ * This class does not distinguish between local and absolute offsets,
+ * but subclasses may. If so, they should store the absolute starting
+ * offset in this field and use it to compute the local starting offset.
+ */
+ private int start;
+
+ /**
+ * Zero-based ending offset.
+ * <p>
+ * This class does not distinguish between local and absolute offsets,
+ * but subclasses may. If so, they should store the absolute ending
+ * offset in this field and use it to compute the local ending offset.
+ */
+ private int end;
+
+ /**
+ * Zero-based line number.
+ * Corresponds to start, not end.
+ */
+ private int line;
+
+ /**
+ * Zero-based column number.
+ * Corresponds to start, not end.
+ */
+ private int column;
++
++ /**
++ * Zero-based line number that corresponds to end.
++ */
++ private int endLine;
++
++ /**
++ * Zero-based column number that corresponds to end.
++ */
++ private int endColumn;
+
+ /**
+ * Copies source location information from another instance
+ * into this instance.
+ */
+ public final void setSourceLocation(ISourceLocation src)
+ {
+ assert src != null : "source location can't be null";
+
+ this.start = src.getStart();
+ this.end = src.getEnd();
+ this.line = src.getLine();
+ this.column = src.getColumn();
++ this.endLine = src.getEndLine();
++ this.endColumn = src.getEndColumn();
+ this.sourcePath = src.getSourcePath();
+ }
+
+ /**
+ * @return The local start offset
+ */
+ @Override
+ public int getStart()
+ {
+ assert start >= 0 || start == UNKNOWN : "Invalid value for start: " + start;
+ return start;
+ }
+
+ /**
+ * @return The absolute start offset.
+ */
+ @Override
+ public int getAbsoluteStart()
+ {
+ assert start >= 0 || start == UNKNOWN : "Invalid value for start: " + start;
+ return start;
+ }
+
+ /**
+ * @return The absolute end offset.
+ */
+ @Override
+ public int getAbsoluteEnd()
+ {
+ assert end >= 0 || end == UNKNOWN : "Invalid value for end: " + end;
+ return end;
+ }
+
+ /**
+ * Set the absolute offset where this node starts.
+ */
+ public void setStart(int start)
+ {
+ if (start != UNKNOWN)
+ this.start = start;
+ }
+
+ /**
+ * @return The local end offset.
+ */
+ @Override
+ public int getEnd()
+ {
+ assert end >= 0 || end == UNKNOWN : "Invalid value for end: " + end;
+ return end;
+ }
+
+ /**
+ * Set the absolute offset where this node ends.
+ */
+ public void setEnd(int end)
+ {
+ if (end != UNKNOWN)
+ this.end = end;
+ }
+
+ /**
+ * Get the line number where this node starts.
+ * Line numbers start at 0, not 1.
+ * @return The line number
+ */
+ @Override
+ public int getLine()
+ {
+ assert line >= 0 || line == UNKNOWN : "Invalid value for line: " + line;
+ return line;
+ }
+
+ /**
+ * Set the line number where this node starts.
+ * Column numbers start at 0, not 1.
+ * @param line The line number
+ */
+ public void setLine(int line)
+ {
+ if (line != UNKNOWN)
+ this.line = line;
+ }
+
+ /**
+ * Get the column number where this node starts.
+ * @return The column number
+ */
+ @Override
+ public int getColumn()
+ {
+ assert column >= 0 || column == UNKNOWN : "Invalid value for column: " + column;
+ return column;
+ }
+
+ /**
+ * Set the column number where this node starts.
+ * @param column The column number
+ */
+ public void setColumn(int column)
+ {
+ if (column != UNKNOWN)
+ this.column = column;
+ }
+
+ /**
++ * Get the line number where this node ends.
++ * Line numbers start at 0, not 1.
++ * @return The line number
++ */
++ public int getEndLine()
++ {
++ return endLine;
++ }
++
++ /**
++ * Set the line number where this node ends.
++ * Column numbers start at 0, not 1.
++ * @param line The line number
++ */
++ public void setEndLine(int line)
++ {
++ this.endLine = line;
++ }
++
++ /**
++ * Get the column number where this node ends.
++ * @return The column number
++ */
++ public int getEndColumn()
++ {
++ return endColumn;
++ }
++
++ /**
++ * Set the column number where this node ends.
++ * @param column The column number
++ */
++ public void setEndColumn(int column)
++ {
++ this.endColumn = column;
++ }
++
++ /**
+ * Get the source path for this node.
+ * @return The source path for this node
+ */
+ @Override
+ public final String getSourcePath()
+ {
+ // null means the source is unknown.
+ // "" means the source is a buffer that hasn't yet been saved to a file.
+ // Something like "framework.swc:defaults.css" means the source is a file inside a SWC.
+ // TODO Shouldn't the part before the colon be normalized?
+ // Anything else should be a normalized path to a source file.
+ assert sourcePath == null ||
+ sourcePath.isEmpty() ||
+ sourcePath.contains(".swc:") ||
+ FilenameNormalization.isNormalized(sourcePath) :
+ "Invalid value for sourcePath: " + sourcePath;
+ return sourcePath;
+ }
+
+ /**
+ * Set the source path of the node.
+ * @param sourcePath The source path
+ */
+ public final void setSourcePath(String sourcePath)
+ {
+ this.sourcePath = sourcePath;
+ }
+
+ /**
+ * Displays line, column, start, end, and sourcepath in a format such as
+ * <pre>
+ * "17:5 160-188 C:\test.as"
+ * </pre>
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getLineColumnString());
+ sb.append(getOffsetsString());
+ sb.append(getSourcePathString());
+ return sb.toString();
+ }
+
+ /**
+ * Displays Line and Column numbers
+ */
+ protected String getLineColumnString()
+ {
+ StringBuilder sb = new StringBuilder();
+ int line = getLine();
+ if (line != UNKNOWN)
+ sb.append(line);
+ else
+ sb.append('?');
+ sb.append(':');
+ int column = getColumn();
+ if (column != UNKNOWN)
+ sb.append(column);
+ else
+ sb.append('?');
+
+ sb.append(' ');
+ return sb.toString();
+ }
+
+ /**
+ * Displays sourcepath
+ *
+ */
+ protected String getSourcePathString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(' ');
+
+ String sourcePath = getSourcePath();
+ if (sourcePath != null)
+ sb.append(sourcePath);
+ else
+ sb.append('?');
+ return sb.toString();
+ }
+
+ /**
+ * Displays line, column, start, end
+ *
+ */
+ protected String getOffsetsString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("loc: ");
+ int start = getStart();
+ if (start != UNKNOWN)
+ sb.append(start);
+ else
+ sb.append('?');
+ sb.append('-');
+ int end = getEnd();
+ if (end != UNKNOWN)
+ sb.append(end);
+ else
+ sb.append('?');
+
+ sb.append(' ');
+
+ sb.append("abs: ");
+ int absoluteStart = getAbsoluteStart();
+ if (absoluteStart != UNKNOWN)
+ sb.append(absoluteStart);
+ else
+ sb.append('?');
+ sb.append('-');
+ int absoluteEnd = getAbsoluteEnd();
+ if (absoluteEnd != UNKNOWN)
+ sb.append(absoluteEnd);
+ else
+ sb.append('?');
+ return sb.toString();
+ }
+
+
+ /**
+ * Span the location range from {@code start} to {@code end}.
+ *
+ * @param start Start location.
+ * @param end End location.
+ */
+ public final void span(ISourceLocation start, ISourceLocation end)
+ {
+ setSourcePath(start.getSourcePath());
+ setStart(start.getStart());
+ setEnd(end.getEnd());
+ setLine(start.getLine());
+ setColumn(start.getColumn());
++ setEndLine(end.getEndLine());
++ setEndColumn(end.getEndColumn());
+ }
+
+ /**
+ * Span the location range from {@code start} to {@code end}.
+ *
+ * @param location The location
+ */
+ public final void span(ISourceLocation location)
+ {
+ if (location != null)
+ setSourceLocation(location);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
----------------------------------------------------------------------
diff --cc compiler/src/main/java/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
index 92b9350,0000000..5b0b18e
mode 100644,000000..100644
--- a/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
@@@ -1,365 -1,0 +1,377 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.definitions.metadata;
+
+import java.util.Arrays;
+
+import org.apache.flex.compiler.common.IMetaInfo;
+import org.apache.flex.compiler.common.NodeReference;
+import org.apache.flex.compiler.constants.IMetaAttributeConstants;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.metadata.IMetaTag;
+import org.apache.flex.compiler.definitions.metadata.IMetaTagAttribute;
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.definitions.DefinitionBase;
+import org.apache.flex.compiler.internal.parsing.as.OffsetLookup;
+import org.apache.flex.compiler.internal.scopes.ASFileScope;
+import org.apache.flex.compiler.internal.scopes.ASScope;
+import org.apache.flex.compiler.internal.tree.as.ClassNode;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.metadata.IMetaTagNode;
+import org.apache.flex.compiler.tree.metadata.IMetaTagsNode;
+import org.apache.flex.compiler.workspaces.IWorkspace;
+
+public class MetaTag implements IMetaTag
+{
+ /**
+ * Append a {@link IMetaTag} to an array of {@link IMetaTag}.
+ *
+ * @param metaTags An existing array of meta tags. May be empty but
+ * may not be null.
+ * @param metaTag The new meta tag to append to the metaTags array.
+ * If null, the metaTags parameter is returned unmodified.
+ * @return The new array of meta tags.
+ */
+ public static IMetaInfo[] addMetaTag(IMetaInfo[] metaTags, IMetaInfo metaTag)
+ {
+ assert metaTags != null;
+
+ if (metaTag != null)
+ {
+ IMetaInfo[] newMetaTags = Arrays.copyOf(metaTags, metaTags.length + 1, IMetaInfo[].class);
+ newMetaTags[metaTags.length] = metaTag;
+ metaTags = newMetaTags;
+ }
+
+ return metaTags;
+ }
+
+ /**
+ * Create a new meta tag for either "__go_to_ctor_definition_help" or
+ * "__go_to_definition_help".
+ *
+ * @param definition The definition to add the meta data for.
+ * @param file The absolute path of the source file the definition is found
+ * in. May be null.
+ * @param pos The position of the definition in the source file. If "-1"
+ * no MetaTag is created.
+ * @param ctor True if the definition is for a constructor, false otherwise.
+ * @return A new MetaTag. If the pos paramater is "-1", null is returned.
+ */
+ public static MetaTag createGotoDefinitionHelp(IDefinition definition,
+ String file, String pos, boolean ctor)
+ {
+ assert pos != null;
+
+ if (pos.equals("-1"))
+ return null;
+
+ IMetaTagAttribute[] attributes = new MetaTagAttribute[file != null ? 2 : 1];
+ if (file != null)
+ {
+ attributes[0] = new MetaTagAttribute(IMetaAttributeConstants.NAME_GOTODEFINITIONHELP_FILE,
+ file);
+ }
+
+ attributes[file != null ? 1 : 0] = new MetaTagAttribute(IMetaAttributeConstants.NAME_GOTODEFINITIONHELP_POS,
+ pos);
+
+ return new MetaTag(definition,
+ ctor ? IMetaAttributeConstants.ATTRIBUTE_GOTODEFINITION_CTOR_HELP :
+ IMetaAttributeConstants.ATTRIBUTE_GOTODEFINITIONHELP,
+ attributes);
+ }
+
+ public MetaTag(IDefinition decoratedDefinition, String tagName, IMetaTagAttribute[] attributes)
+ {
+ this.decoratedDefinition = decoratedDefinition;
+ this.tagName = tagName;
+ if (attributes == null)
+ {
+ // this is a low cost way to make sure that clients never get null attributes
+ attributes = emptyAttributes;
+ }
+ this.attributes = attributes;
+ }
+
+ private IDefinition decoratedDefinition;
+
+ private String tagName;
+
+ private IMetaTagAttribute[] attributes;
+
+ // Singleton empty array to be shared by all instances that don't have attributes
+ private static final IMetaTagAttribute[] emptyAttributes = new IMetaTagAttribute[0];
+
+ private String sourcePath;
+
+ private int absoluteStart = UNKNOWN;
+
+ private int absoluteEnd = UNKNOWN;
+
+ private int line = UNKNOWN;
+
+ private int column = UNKNOWN;
+
+ // Hold a reference to the node this definition came from
+ // (NodeReference only holds onto the node weakly, so we don't have to worry about leaks).
+ private NodeReference nodeRef = NodeReference.noReference;
+
+ @Override
+ public String getTagName()
+ {
+ return tagName;
+ }
+
+ @Override
+ public IMetaTagAttribute[] getAllAttributes()
+ {
+ return attributes;
+ }
+
+ @Override
+ public IMetaTagAttribute getAttribute(String key)
+ {
+ for (IMetaTagAttribute attribute : attributes)
+ {
+ String attrKey = attribute.getKey();
+ if (attrKey != null && attrKey.equals(key))
+ return attribute;
+ }
+ return null;
+ }
+
+ @Override
+ public String getAttributeValue(String key)
+ {
+ for (IMetaTagAttribute attribute : attributes)
+ {
+ // For metadata such as [Foo("abc", "def")],
+ // the attribute keys are null, so a null
+ // check on the key is necessary.
+ // BTW, keyless values like "abc" and "def"
+ // cannot be retrieved by this API;
+ // you have to use getAttributes()[i].getValue().
+ String attrKey = attribute.getKey();
+ if (attrKey != null && attrKey.equals(key))
+ return attribute.getValue();
+ }
+ return null;
+ }
+
+ @Override
+ public String getSourcePath()
+ {
+ return sourcePath;
+ }
+
+ private OffsetLookup getOffsetLookup()
+ {
+ DefinitionBase definition = (DefinitionBase)getDecoratedDefinition();
+ if (definition == null)
+ return null;
+
+ final ASFileScope fileScope = definition.getFileScope();
+ if (fileScope == null)
+ return null;
+
+ return fileScope.getOffsetLookup();
+ }
+
+ @Override
+ public int getStart()
+ {
+ OffsetLookup offsetLookup = getOffsetLookup();
+
+ if (offsetLookup == null)
+ return absoluteStart;
+
+ return offsetLookup.getLocalOffset(absoluteStart);
+ }
+
+ @Override
+ public int getEnd()
+ {
+ OffsetLookup offsetLookup = getOffsetLookup();
+
+ if (offsetLookup == null)
+ return absoluteEnd;
+
+ return offsetLookup.getLocalOffset(absoluteEnd);
+ }
+
+ @Override
+ public int getLine()
+ {
+ return line;
+ }
+
+ @Override
+ public int getColumn()
+ {
+ return column;
+ }
+
+ @Override
++ public int getEndLine()
++ {
++ return line;
++ }
++
++ @Override
++ public int getEndColumn()
++ {
++ return column;
++ }
++
++ @Override
+ public int getAbsoluteStart()
+ {
+ return absoluteStart;
+ }
+
+ @Override
+ public int getAbsoluteEnd()
+ {
+ return absoluteEnd;
+ }
+
+ @Override
+ public IDefinition getDecoratedDefinition()
+ {
+ return decoratedDefinition;
+ }
+
+ @Override
+ public String getValue()
+ {
+ return attributes.length == 1 && !attributes[0].hasKey() ?
+ attributes[0].getValue() :
+ null;
+ }
+
+ @Override
+ public IMetaTagNode getTagNode()
+ {
+ // If this definition didn't come from source, return null.
+ if (nodeRef == NodeReference.noReference)
+ return null;
+
+ // Get the scope for the definition this metadata is attached to.
+ ASScope containingScope = (ASScope)getDecoratedDefinition().getContainingScope();
+ if (containingScope == null)
+ return null;
+
+ // Get the file scope for that scope.
+ ASFileScope fileScope = containingScope.getFileScope();
+ if (fileScope == null)
+ return null;
+
+ // Get the workspace.
+ IWorkspace workspace = fileScope.getWorkspace();
+ assert workspace != null;
+
+ // Use the stored NodeReference to get the original node.
+ IASNode node = nodeRef.getNode(workspace, containingScope);
+ if (!(node instanceof IMetaTagNode))
+ {
+ // CMP-2168: The NodeReference resolver assumes that all definitions
+ // have a unique start offset. This true in every case except when
+ // there are metadata definitions decorating a class. In this case, the
+ // start of the metadata and the start of the class are the same, and the
+ // resolver will return the ClassNode, not the MetaTagNode. Catch this
+ // case by when we get a ClassNode, walking any metatags on the class
+ // looking for an offset that matches this MetaTag offset.
+ if (node instanceof ClassNode)
+ {
+ IMetaTagsNode metaTags = ((ClassNode)node).getMetaTags();
+ if (metaTags != null)
+ {
+ for (IMetaTagNode metaTagNode : metaTags.getAllTags())
+ {
+ if (metaTagNode.getAbsoluteStart() == getAbsoluteStart())
+ return metaTagNode;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ return (IMetaTagNode)node;
+ }
+
+ /**
+ * Updates the location information of this tag.
+ */
+ public void setLocation(IFileSpecification containingFileSpec, int absoluteStart, int absoluteEnd, int line, int column)
+ {
+ this.nodeRef = new NodeReference(containingFileSpec, absoluteStart);
+ this.sourcePath = containingFileSpec.getPath();
+ this.absoluteStart = absoluteStart;
+ this.absoluteEnd = absoluteEnd;
+ this.line = line;
+ this.column = column;
+ }
+
+ /**
+ * For debugging only.
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append('[');
+ sb.append(tagName);
+
+ IMetaTagAttribute[] attrs = getAllAttributes();
+ if (attrs != null && attrs.length > 0)
+ {
+ sb.append('(');
+
+ int i = 0;
+ for (IMetaTagAttribute attr : getAllAttributes())
+ {
+ if (i != 0)
+ {
+ sb.append(',');
+ sb.append(' ');
+ }
+
+ String key = attr.getKey();
+ String value = attr.getValue();
+
+ sb.append(key);
+ sb.append('=');
+ sb.append('"');
+ sb.append(value);
+ sb.append('"');
+
+ i++;
+ }
+ sb.append(')');
+ }
+
+ sb.append(']');
+
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/java/org/apache/flex/compiler/internal/parsing/TokenBase.java
----------------------------------------------------------------------
diff --cc compiler/src/main/java/org/apache/flex/compiler/internal/parsing/TokenBase.java
index 68a76eb,0000000..ff726da
mode 100644,000000..100644
--- a/compiler/src/main/java/org/apache/flex/compiler/internal/parsing/TokenBase.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/parsing/TokenBase.java
@@@ -1,515 -1,0 +1,559 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.parsing;
+
+import antlr.Token;
+
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.internal.common.Counter;
+import org.apache.flex.compiler.internal.parsing.as.ASTokenTypes;
+import org.apache.flex.compiler.internal.parsing.as.IncludeHandler;
+import org.apache.flex.compiler.parsing.ICMToken;
+
+/**
+ * Base class of ASToken, MXMLToken, CSSToken
+ */
+public abstract class TokenBase extends Token implements ICMToken, ISourceLocation
+{
+ /**
+ * Constructor
+ *
+ * @param tokenType type of token
+ * @param start location location information
+ * @param end location location information
+ * @param line location location information
+ * @param column location location information
+ * @param text actual text represented by token
+ */
+ public TokenBase(int tokenType, int start, int end, int line, int column, CharSequence text)
+ {
+ type = tokenType;
+ localStart = this.start = start;
+ localEnd = this.end = end;
+ this.line = line;
+ this.column = column;
+ this.text = text;
++ this.endLine = line;
++ this.endColumn = column + end - start;
+
+ if (Counter.COUNT_TOKENS)
+ countTokens();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param o token to copy
+ */
+ public TokenBase(TokenBase o)
+ {
+ type = o.type;
+ start = o.start;
+ end = o.end;
+ line = o.line;
+ column = o.column;
++ endLine = o.endLine;
++ endColumn = o.endColumn;
+ text = o.text;
+
+ localStart = o.localStart;
+ localEnd = o.localEnd;
+ sourcePath = o.sourcePath;
+
+ if (Counter.COUNT_TOKENS)
+ countTokens();
+ }
+
+ /**
+ * Text represented by this token
+ */
+ private CharSequence text;
+
+ /**
+ * Start of this token
+ */
+ private int start;
+
+ /**
+ * End offset of this token
+ */
+ private int end;
+
+ /**
+ * Line of this token
+ */
+ private int line;
+
+ /**
+ * Column of this token
+ */
+ private int column;
+
+ /**
++ * End line of this token
++ */
++ private int endLine;
++
++ /**
++ * End column of this token
++ */
++ private int endColumn;
++
++ /**
+ * Flag to determine if this token is locked
+ */
+ private boolean locked;
+
+ /**
+ * Local start offset.
+ */
+ private int localStart;
+
+ /**
+ * Local end offset.
+ */
+ private int localEnd;
+
+ protected abstract String getTypeString();
+
+ /**
+ * @return Local start offset.
+ */
+ public final int getLocalStart()
+ {
+ return localStart;
+ }
+
+ /**
+ * @return Local end offset.
+ */
+ public final int getLocalEnd()
+ {
+ return localEnd;
+ }
+
+ public final void reuse(final int tokenType, final int start, final int end,
+ final int line, final int column, final CharSequence text)
+ {
+ type = tokenType;
+ this.start = start;
+ this.end = end;
+ this.line = line;
+ this.column = column;
++ this.endLine = line;
++ this.endColumn = column + end - start;
+ this.text = text;
+ }
+
+ /**
+ * Locks this token. When locked, if this token is in a token pool, it will
+ * not be overwritten
+ */
+ public void lock()
+ {
+ locked = true;
+ }
+
+ /**
+ * Returns whether this token can be overwritten when it is a member of a
+ * token pool
+ *
+ * @return true if we are locked
+ */
+ public boolean isLocked()
+ {
+ return locked;
+ }
+
+ /**
+ * Get the text represented by this token
+ *
+ * @return text represented by this token
+ * @see antlr.Token#getText()
+ */
+ @Override
+ public String getText()
+ {
+ //we're either going to be a String or a StringBuilder
+ //String.toString returns itself
+ //StringBuilder toString returns a new String
+ if (text != null)
+ return text.toString();
+ return "";
+ }
+
+ /**
+ * Returns the underlying CharSequence that represents the contents of this
+ * token
+ *
+ * @return a {@link CharSequence} or null
+ */
+ public CharSequence getCharSequence()
+ {
+ return text;
+ }
+
+ /**
+ * Set the text represented by this token
+ *
+ * @param text text represented by this token
+ * @see antlr.Token#setText(java.lang.String)
+ */
+ @Override
+ public void setText(String text)
+ {
+ this.text = text;
+ }
+
+ /**
+ * Set the CharSequence represented by this token
+ *
+ * @param text text represented by this token
+ */
+ public void setText(CharSequence text)
+ {
+ this.text = text;
+ }
+
+ public void setLocation(int start, int end, int line, int column)
+ {
+ this.start = start;
+ this.end = end;
+ this.line = line;
+ this.column = column;
++ this.endLine = line;
++ this.endColumn = column + end - start;
+ }
+
+ @Override
+ public int getStart()
+ {
+ return start;
+ }
+
+ public void setStart(int start)
+ {
+ this.start = start;
+ }
+
+ @Override
+ public int getEnd()
+ {
+ return end;
+ }
+
+ public void setEnd(int end)
+ {
+ this.end = end;
+ }
+
+ @Override
+ public int getLine()
+ {
+ return line;
+ }
+
+ @Override
+ public void setLine(int line)
+ {
+ this.line = line;
+ }
+
+ public final boolean matchesLine(final TokenBase other)
+ {
+ return other != null && other.line == line;
+ }
+
+ @Override
+ public int getColumn()
+ {
+ return column;
+ }
+
+ @Override
+ public void setColumn(int column)
+ {
+ this.column = column;
+ }
+
++ @Override
++ public int getEndLine()
++ {
++ return endLine;
++ }
++
++ public void setEndLine(int line)
++ {
++ endLine = line;
++ }
++
++ @Override
++ public int getEndColumn()
++ {
++ return endColumn;
++ }
++
++ public void setEndColumn(int column)
++ {
++ endColumn = column;
++ }
++
+ /**
+ * Determine whether or not this token is bogus (i.e. the start and end
+ * offsets are the same, which implies that it was inserted from an included
+ * file or during token fixup)
+ *
+ * @return true iff the token is bogus
+ */
+ @Override
+ public boolean isImplicit()
+ {
+ return start == end;
+ }
+
+ /**
+ * For debugging only.
+ */
+ private String getEscapedText()
+ {
+ String text = getText();
+
+ text = text.replaceAll("\n", "\\\\n");
+ text = text.replaceAll("\r", "\\\\r");
+ text = text.replaceAll("\t", "\\\\t");
+
+ return text;
+ }
+
+ /**
+ * For debugging only. This format is nice in the Eclipse debugger.
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append('|');
+ sb.append(getEscapedText());
+ sb.append('|');
+
+ sb.append(' ');
+
+ sb.append(getTypeString());
+
+ sb.append(' ');
+
+ if (locked)
+ sb.append("locked ");
+
+ int line = getLine();
+ if (line != UNKNOWN)
+ sb.append(line + 1);
+ else
+ sb.append('?');
+ sb.append(':');
+ int column = getColumn();
+ if (column != UNKNOWN)
+ sb.append(column + 1);
+ else
+ sb.append('?');
+
+ sb.append(' ');
+
+ int start = getStart();
+ if (start != UNKNOWN)
+ sb.append(start);
+ else
+ sb.append('?');
+ sb.append('-');
+ int end = getEnd();
+ if (end != UNKNOWN)
+ sb.append(end);
+ else
+ sb.append('?');
+
+ sb.append(' ');
+ String sourcePath = getSourcePath();
+ if (sourcePath != null)
+ {
+ sb.append('"');
+ sb.append(sourcePath);
+ sb.append('"');
+ }
+ else
+ {
+ sb.append('?');
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * For debugging only. This format is nice in a text file.
+ */
+ public String toDumpString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(getLine() + 1);
+ sb.append('\t');
+ sb.append(getColumn() + 1);
+ sb.append('\t');
+ sb.append(getStart());
+ sb.append('\t');
+ sb.append(getEnd());
+ sb.append('\t');
+
+ String typeString = getTypeString();
+ sb.append(typeString);
+ int n = 28 - typeString.length();
+ for (int i = 0; i < n; i++)
+ sb.append(' ');
+ sb.append('\t');
+
+ sb.append('|');
+ sb.append(getEscapedText());
+ sb.append('|');
+
+ return sb.toString();
+ }
+
+ /**
+ * Reduce the span of the token by removing characters from the beginning
+ * and end. This is used to remove quote characters and such from tokens.
+ *
+ * @param trimLeft number of characters to remove from the left of the token
+ * @param trimRight number of characters to remove from the right of the
+ * token
+ */
+ public void truncate(int trimLeft, int trimRight)
+ {
+ String text = getText();
+ if (trimLeft + trimRight <= text.length())
+ {
+ text = text.substring(trimLeft, text.length() - trimRight);
+ setText(text);
+ start += trimLeft;
+ end -= trimRight;
+ }
+ }
+
+ /**
+ * Adjust all associated offsets by the adjustment amount
+ *
+ * @param offsetAdjustment amount to add to offsets
+ */
+ public void adjustOffsets(int offsetAdjustment)
+ {
+ start += offsetAdjustment;
+ end += offsetAdjustment;
+ }
+
+ /**
+ * Adjust all associated offsets by the adjustment amount
+ *
+ * @param offsetAdjustment amount to add to offsets
+ * @param lineAdjustment amount to add to the line number
+ * @param columnAdjustment amount to add to the column number
+ */
+ public void adjustLocation(int offsetAdjustment, int lineAdjustment, int columnAdjustment)
+ {
+ start += offsetAdjustment;
+ end += offsetAdjustment;
+ line += lineAdjustment;
+ column += columnAdjustment;
++ endLine += lineAdjustment;
++ endColumn += columnAdjustment;
+ }
+
+ /**
+ * Capture the current start/end offsets as this token's local offsets. This
+ * method is called in {@code StreamingASTokenizer#nextTokenFromReader()}
+ * after the token is initialized, and before being updated by
+ * {@link IncludeHandler#onNextToken}.
+ */
+ public final void storeLocalOffset()
+ {
+ this.localStart = start;
+ this.localEnd = end;
+ }
+
+ private String sourcePath;
+
+ @Override
+ public final String getSourcePath()
+ {
+ return sourcePath;
+ }
+
+ public final void setSourcePath(String path)
+ {
+ this.sourcePath = path;
+ }
+
+ /**
+ * Verifies that this token has its type and location information set.
+ * <p>
+ * This is used only in asserts.
+ */
+ public boolean verify()
+ {
+ // Verify the token type.
+ int type = getType();
+ assert type != 0 : "Token has no type: " + toString();
+
+ // Verify the source location (except for EOF tokens,
+ // which are special and don't have a source location).
+ if (type != ASTokenTypes.EOF)
+ {
+ assert getStart() != UNKNOWN : "Token has unknown start: " + toString();
+ assert getEnd() != UNKNOWN : "Token has unknown end: " + toString();
+ assert getLine() != UNKNOWN : "Token has an unknown line: " + toString();
+ assert getColumn() != UNKNOWN : "Token has an unknown column: " + toString();
++ assert getEndLine() != UNKNOWN : "Token has an unknown end line: " + toString();
++ assert getEndColumn() != UNKNOWN : "Token has an unknown end column: " + toString();
+ }
+
+ return true;
+ }
+
+ /**
+ * Counts various types of tokens that are created, as well as the total
+ * number of tokens.
+ */
+ private void countTokens()
+ {
+ Counter counter = Counter.getInstance();
+ counter.incrementCount(getClass().getSimpleName());
+ counter.incrementCount("tokens");
+ }
+
+ @Override
+ public int getAbsoluteEnd()
+ {
+ return getEnd();
+ }
+
+ @Override
+ public int getAbsoluteStart()
+ {
+ return getStart();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/NodeBase.java
----------------------------------------------------------------------
diff --cc compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/NodeBase.java
index be0510d,0000000..8dd4fb6
mode 100644,000000..100644
--- a/compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/NodeBase.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/NodeBase.java
@@@ -1,1038 -1,0 +1,1049 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.tree.as;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+
+import antlr.Token;
+
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.common.SourceLocation;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.common.Counter;
+import org.apache.flex.compiler.internal.definitions.DefinitionBase;
+import org.apache.flex.compiler.internal.parsing.as.OffsetLookup;
+import org.apache.flex.compiler.internal.scopes.ASFileScope;
+import org.apache.flex.compiler.internal.scopes.ASScope;
+import org.apache.flex.compiler.internal.scopes.TypeScope;
+import org.apache.flex.compiler.internal.semantics.PostProcessStep;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.scopes.IASScope;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IFileNode;
+import org.apache.flex.compiler.tree.as.IImportNode;
+import org.apache.flex.compiler.tree.as.IPackageNode;
+import org.apache.flex.compiler.tree.as.IScopedNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLClassDefinitionNode;
+import org.apache.flex.compiler.workspaces.IWorkspace;
+
+/**
+ * Base class for ActionScript parse tree nodes
+ */
+public abstract class NodeBase extends SourceLocation implements IASNode
+{
+ /**
+ * Used in calls to CheapArray functions. It represents the type of objects
+ * that appear in fSymbols.
+ */
+ protected static final IASNode[] emptyNodeArray = new IASNode[0];
+
+
+ /**
+ * Combine the attributes from the base class with the attributes specific
+ * to this class
+ *
+ * @param superAttributes The attributes of the base class.
+ * @param myAttributes The attributes of this class.
+ * @return attribute value
+ */
+ public static String[] combineAttributes(String[] superAttributes, String[] myAttributes)
+ {
+ String[] combinedAttributes = new String[superAttributes.length + myAttributes.length];
+ for (int i = 0; i < superAttributes.length; i++)
+ {
+ combinedAttributes[i] = superAttributes[i];
+ }
+ for (int i = 0; i < myAttributes.length; i++)
+ {
+ combinedAttributes[superAttributes.length + i] = myAttributes[i];
+ }
+ return combinedAttributes;
+ }
+
+ /**
+ * Constructor.
+ */
+ public NodeBase()
+ {
+ super();
+ parent = null;
+
+ if (Counter.COUNT_NODES)
+ countNodes();
+ }
+
+ /**
+ * Parent node.
+ * <p>
+ * Methods (even in NodeBase itself) should use getParent() instead of
+ * accessing this member directly. getParent() is overridden in FileNode to
+ * do something special when the FileNode represents a shared file.
+ */
+ protected IASNode parent;
+
+ @Override
+ public IASNode getParent()
+ {
+ return parent;
+ }
+
+ @Override
+ public int getChildCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public IASNode getChild(int i)
+ {
+ return null;
+ }
+
+ @Override
+ public IFileSpecification getFileSpecification()
+ {
+ // TODO Make sure this works with include processing!!!
+ ASFileScope fileScope = getFileScope();
+ IWorkspace w = fileScope.getWorkspace();
+ return w.getFileSpecification(fileScope.getContainingPath());
+ }
+
+ @Override
+ public int getSpanningStart()
+ {
+ return getStart();
+ }
+
+ /**
+ * Get the node type as a string. For example, this will return
+ * "IdentifierNode" for an IdentifierNode.
+ *
+ * @return the node type
+ */
+ public String getNodeKind()
+ {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public boolean contains(int offset)
+ {
+ return getAbsoluteStart() < offset && getAbsoluteEnd() >= offset;
+ }
+
+ /**
+ * Determine whether the offset "loosely" fits within this node. With normal
+ * nodes, this will return true if the offset matches fLocation.fStart or
+ * fLocation.fEnd or anything in between. With bogus nodes (which have
+ * fStart == fEnd), this will return true if the offset comes after fStart
+ * and before any other nodes in the parse tree
+ *
+ * @param offset the offset to test
+ * @return true if the offset is "loosely" contained within this node
+ */
+ public boolean looselyContains(int offset)
+ {
+ if (getAbsoluteStart() == getAbsoluteEnd())
+ {
+ // This is a bogus placeholder node (generally an identifier that's been inserted to complete an expression).
+ // We'll pretend that it extends all the way to the start offset of the next node. Now to find that next node...
+ if (getAbsoluteStart() <= offset)
+ {
+ NodeBase containingNode = (NodeBase)getParent();
+ // Step 1: Find a node that extends beyond the target offset
+ while (containingNode != null && containingNode.getAbsoluteEnd() <= getAbsoluteEnd())
+ containingNode = (NodeBase)containingNode.getParent();
+ // If no such node exists, we know that there aren't any tokens in the parse
+ // tree that end after this bogus token. So we can go ahead and pretend this node
+ // extends all the way out.
+ if (containingNode == null)
+ return true;
+ // Step 2: Find a node that starts after the target offset
+ IASNode succeedingNode = containingNode.getSucceedingNode(getAbsoluteEnd());
+ // If no such node exists, we know that there aren't any tokens in the parse
+ // tree that start after this bogus token. So we can go ahead and pretend this
+ // node extends all the way out.
+ if (succeedingNode == null)
+ return true;
+ // Otherwise, pretend this node extends all the way to the next token.
+ if (succeedingNode.getAbsoluteStart() >= offset)
+ return true;
+ }
+ }
+ else
+ {
+ // This is a real token. See if the test offset fits within (including the boundaries, since we're looking
+ // at "loose" containment.
+ return getAbsoluteStart() <= offset && getAbsoluteEnd() >= offset;
+ }
+ return false;
+ }
+
+ @Override
+ public IASNode getSucceedingNode(int offset)
+ {
+ // This node ends before the offset is even reached. This is hopeless.
+ if (getAbsoluteEnd() <= offset)
+ return null;
+
+ // See if one of our children starts after the offset
+ for (int i = 0; i < getChildCount(); i++)
+ {
+ IASNode child = getChild(i);
+
+ if (child.getAbsoluteStart() > offset)
+ return child;
+ else if (child.getAbsoluteEnd() > offset)
+ return child.getSucceedingNode(offset);
+ }
+
+ return null;
+ }
+
+ /**
+ * Determine whether this node is transparent. If a node is transparent, it
+ * can never be returned from getContainingNode... the offset will be
+ * considered part of the parent node instead.
+ *
+ * @return true if the node is transparent
+ */
+ public boolean isTransparent()
+ {
+ return false;
+ }
+
+ @Override
+ public IASNode getContainingNode(int offset)
+ {
+ // This node doesn't even contain the offset. This is hopeless.
+ if (!contains(offset))
+ {
+ return null;
+ }
+ IASNode containingNode = this;
+ int childCount = getChildCount();
+ // See if the offset is contained within one of our children.
+ for (int i = 0; i < childCount; i++)
+ {
+ IASNode child = getChild(i);
+ if (child.getAbsoluteStart() <= offset)
+ {
+ if (child.contains(offset))
+ {
+ containingNode = child.getContainingNode(offset);
+ if (child instanceof NodeBase && ((NodeBase)child).canContinueContainmentSearch(containingNode, this, i, true))
+ continue;
+ break;
+ }
+ }
+ else
+ {
+ if (child instanceof NodeBase && ((NodeBase)child).canContinueContainmentSearch(containingNode, this, i, false))
+ continue;
+ // We've passed this offset without finding a child that contains it. This is
+ // the nearest enclosing node.
+ break;
+ }
+ }
+ // Make sure we don't return a transparent node
+ while (containingNode != null && containingNode instanceof NodeBase && ((NodeBase)containingNode).isTransparent())
+ {
+ containingNode = containingNode.getParent();
+ }
+ return containingNode;
+ }
+
+ @Override
+ public boolean isTerminal()
+ {
+ return false;
+ }
+
+ @Override
+ public IScopedNode getContainingScope()
+ {
+ return (IScopedNode)getAncestorOfType(IScopedNode.class);
+ }
+
+ // TODO Can probably eliminate this.
+ protected boolean canContinueContainmentSearch(IASNode containingNode, IASNode currentNode, int childOffset, boolean offsetsStillValid)
+ {
+ return false;
+ }
+
+ @Override
+ public IASNode getAncestorOfType(Class<? extends IASNode> nodeType)
+ {
+ IASNode current = getParent();
+ while (current != null && !(nodeType.isInstance(current)))
+ current = current.getParent();
+ if (current != null)
+ return current;
+ return null;
+ }
+
+ @Override
+ public String getPackageName()
+ {
+ // Starting with this node's parent, walk up the parent chain
+ // looking for a package node or an MXML class definition node.
+ // These two types of nodes understand what their package is.
+ IASNode current = getParent();
+ while (current != null &&
+ !(current instanceof IPackageNode ||
+ current instanceof IMXMLClassDefinitionNode))
+ {
+ current = current.getParent();
+ }
+
+ if (current instanceof IPackageNode)
+ return ((IPackageNode)current).getPackageName();
+ else if (current instanceof IMXMLClassDefinitionNode)
+ return ((IMXMLClassDefinitionNode)current).getPackageName();
+
+ return null;
+ }
+
+ /**
+ * Set the start offset of the node to fall just after the token. Used
+ * during parsing.
+ *
+ * @param token start this node after this token
+ */
+ public void startAfter(Token token)
+ {
+ if (token instanceof ISourceLocation)
+ {
+ startAfter((ISourceLocation) token);
- setColumn(getColumn() + token.getText().length());
+ }
+ }
+
+ /**
+ * Set the start offset of the node to fall just after the token. Used
+ * during parsing.
+ *
+ * @param location start this node after this token
+ */
+ public final void startAfter(ISourceLocation location)
+ {
+ final int end = location.getEnd();
+ if (end != UNKNOWN)
+ {
+ setSourcePath(location.getSourcePath());
+ setStart(end);
- setLine(location.getLine());
- setColumn(location.getColumn());
++ setLine(location.getEndLine());
++ setColumn(location.getEndColumn());
+ }
+ }
+
+ /**
+ * Set the start offset of the node to fall just before the token. Used
+ * during parsing.
+ *
+ * @param token start this node before this token
+ */
+ public final void startBefore(Token token)
+ {
+ if (token instanceof ISourceLocation)
+ startBefore((ISourceLocation)token);
+ }
+
+ /**
+ * Set the start offset of the node to fall just before the token. Used
+ * during parsing.
+ *
+ * @param location start this node before this token
+ */
+ public final void startBefore(ISourceLocation location)
+ {
+ final int start = location.getStart();
+ if (start != UNKNOWN)
+ {
+ setSourcePath(location.getSourcePath());
+ setStart(start);
+ setLine(location.getLine());
+ setColumn(location.getColumn());
+ }
+ }
+
+ /**
+ * Set the end offset of the node to fall just after the token. Used during
+ * parsing.
+ *
+ * @param token end this node after this token
+ */
+ public final void endAfter(Token token)
+ {
+ if (token instanceof ISourceLocation)
+ endAfter((ISourceLocation)token);
+ }
+
+ /**
+ * Set the end offset of the node to fall just after the token. Used during
+ * parsing.
+ *
+ * @param location end this node after this token
+ */
+ public final void endAfter(ISourceLocation location)
+ {
+ final int end = location.getEnd();
+ if (end != UNKNOWN)
++ {
+ setEnd(end);
++ setEndLine(location.getEndLine());
++ setEndColumn(location.getEndColumn());
++ }
+ }
+
+ /**
+ * Set the end offset of the node to fall just before the token. Used during
+ * parsing.
+ *
+ * @param token start this node before this token
+ */
+ public final void endBefore(Token token)
+ {
+ if (token instanceof ISourceLocation)
+ endBefore((ISourceLocation)token);
+ }
+
+ /**
+ * Set the end offset of the node to fall just before the token. Used during
+ * parsing.
+ *
+ * @param location start this node before this token
+ */
+ public final void endBefore(ISourceLocation location)
+ {
+ final int start = location.getStart();
+ if (start != UNKNOWN)
++ {
+ setEnd(start);
++ setEndLine(location.getLine());
++ setEndColumn(location.getColumn());
++ }
+ }
+
+ /**
+ * Set the start and end offsets of the node to coincide with the token's
+ * offsets. Used during parsing.
+ *
+ * @param token the token to take the offsets from
+ */
+ public final void span(Token token)
+ {
+ if (token instanceof ISourceLocation)
+ span((ISourceLocation)token);
+ }
+
+ /**
+ * Set the start and end offsets of the node to coincide with the tokens'
+ * offsets. Used during parsing.
+ *
+ * @param firstToken the token to take the start offset and line number from
+ * @param lastToken the token to take the end offset from
+ */
+ public final void span(Token firstToken, Token lastToken)
+ {
+ if (firstToken instanceof ISourceLocation && lastToken instanceof ISourceLocation)
+ span((ISourceLocation)firstToken, (ISourceLocation)lastToken);
+ }
+
+ /**
+ * Set the start and end offsets of the node. Used during parsing.
+ *
+ * @param start start offset for the node
+ * @param end end offset for the node
+ * @param line line number for the node
+ */
+ public final void span(int start, int end, int line, int column)
+ {
+ setStart(start);
+ setEnd(end);
+ setLine(line);
+ setColumn(column);
+ }
+
+ public Collection<ICompilerProblem> runPostProcess(EnumSet<PostProcessStep> set, ASScope containingScope)
+ {
+ ArrayList<ICompilerProblem> problems = new ArrayList<ICompilerProblem>(10);
+ normalize(set.contains(PostProcessStep.CALCULATE_OFFSETS));
+ if (set.contains(PostProcessStep.POPULATE_SCOPE) || set.contains(PostProcessStep.RECONNECT_DEFINITIONS))
+ analyze(set, containingScope, problems);
+ return problems;
+ }
+
+ protected void analyze(EnumSet<PostProcessStep> set, ASScope scope, Collection<ICompilerProblem> problems)
+ {
+ int childrenSize = getChildCount();
+ // Populate this scope with definitions found among the children
+ for (int i = 0; i < childrenSize; i++)
+ {
+ IASNode child = getChild(i);
+ if (child instanceof NodeBase)
+ {
+ if (child.getParent() == null)
+ ((NodeBase)child).setParent(this);
+ ((NodeBase)child).analyze(set, scope, problems);
+ }
+ }
+ }
+
+ /**
+ * Changes the position of two children in our tree. Neither child can be
+ * null and both must have the same parent
+ *
+ * @param child the child to replace target
+ * @param target the child to replace child
+ */
+ protected void swapChildren(NodeBase child, NodeBase target)
+ {
+ //no op in this impl
+ }
+
+ /**
+ * Replaces the child with the given target. The child will be removed from
+ * the tree, and its parentage will be updated
+ *
+ * @param child the {@link NodeBase} to replace
+ * @param target the {@link NodeBase} to replace the replaced
+ */
+ protected void replaceChild(NodeBase child, NodeBase target)
+ {
+ //no op
+ }
+
+ /**
+ * Normalize the tree. Move custom children into the real child list and
+ * fill in missing offsets so that offset lookup will work. Used during
+ * parsing.
+ */
+ public void normalize(boolean fillInOffsets)
+ {
+ // The list of children doesn't change, so the child count should be constant throughout the loop
+ int childrenSize = getChildCount();
+ // Normalize the regular children
+ for (int i = 0; i < childrenSize; i++)
+ {
+ IASNode child = getChild(i);
+ if (child instanceof NodeBase)
+ {
+ ((NodeBase)child).setParent(this);
+ ((NodeBase)child).normalize(fillInOffsets);
+ }
+ }
+ // Add the special children (which get normalized as they're added)
+ if (childrenSize == 0)
+ setChildren(fillInOffsets);
+ // Fill in offsets based on the child nodes
+ if (fillInOffsets)
+ fillInOffsets();
+ // fill in any dangling ends
+ //fillEndOffsets();
+ // get rid of unused child space
+ }
+
+ /**
+ * Allow various subclasses to do special kludgy things like identify
+ * mx.core.Application.application
+ */
+ protected void connectedToProjectScope()
+ {
+ // The list of children doesn't change, so the child count should be constant throughout the loop
+ int childrenSize = getChildCount();
+ for (int i = 0; i < childrenSize; i++)
+ {
+ IASNode child = getChild(i);
+ if (child instanceof NodeBase)
+ ((NodeBase)child).connectedToProjectScope();
+ }
+ }
+
+ /**
+ * If this node has custom children (names, arguments, etc), shove them into
+ * the list of children. Used during parsing.
+ */
+ protected void setChildren(boolean fillInOffsets)
+ {
+ //nothing in this class
+ }
+
+ /**
+ * If the start and end offsets haven't been set explicitly, fill them in
+ * based on the offsets of the children. Used during parsing. If the end
+ * offset is less than any of the kids' offsets, change fLocation.fEnd to
+ * encompass kids.
+ */
+ protected void fillInOffsets()
+ {
+ int numChildren = getChildCount();
+ if (numChildren > 0)
+ {
+ int start = getAbsoluteStart();
+ int end = getAbsoluteEnd();
+ if (start == -1)
+ {
+ for (int i = 0; i < numChildren; i++)
+ {
+ IASNode child = getChild(i);
+ int childStart = child.getAbsoluteStart();
+ if (childStart != -1)
+ {
+ if (getSourcePath() == null)
+ setSourcePath(child.getSourcePath());
+ setStart(childStart);
+ setLine(child.getLine());
+ setColumn(child.getColumn());
+ break;
+ }
+ }
+ }
+ for (int i = numChildren - 1; i >= 0; i--)
+ {
+ IASNode child = getChild(i);
+ int childEnd = child.getAbsoluteEnd();
+ if (childEnd != -1)
+ {
+ if (end < childEnd)
++ {
+ setEnd(childEnd);
++ setEndLine(child.getEndLine());
++ setEndColumn(child.getEndColumn());
++ }
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the parent node. Used during parsing.
+ *
+ * @param parent parent node
+ */
+ public void setParent(NodeBase parent)
+ {
+ this.parent = parent;
+ }
+
+ /**
+ * Get the nearest containing scope for this node. Used during type
+ * decoration.
+ *
+ * @return nearest containing scope for this node
+ */
+ // TODO Make this more efficient using overrides on BlockNode and FileNode.
+ public IScopedNode getScopeNode()
+ {
+ if (this instanceof IScopedNode && ((IScopedNode)this).getScope() != null)
+ return (IScopedNode)this;
+ IASNode parent = getParent();
+ if (parent != null && parent instanceof NodeBase)
+ return ((NodeBase)parent).getScopeNode();
+ return null;
+ }
+
+ /**
+ * Get the path of the file in which this parse tree node resides.
+ * <p>
+ * The tree builder can set a node's origin source file using
+ * {@link #setSourcePath(String)}. If the source path was set, return the
+ * source path; Otherwise, use root {@link FileNode}'s path.
+ *
+ * @return file path that contains this node
+ */
+ public String getContainingFilePath()
+ {
+ String path = getSourcePath();
+ if (path != null)
+ return path;
+
+ final FileNode fileNode = (FileNode)getAncestorOfType(FileNode.class);
+ if (fileNode != null)
+ return fileNode.getSourcePath();
+ return null;
+ }
+
+ /**
+ * For debugging only. Displays this node and its children in a form like
+ * this:
+ *
+ * <pre>
+ * FileNode "D:\tests\UIComponent.as" 0:0 0-467464 D:\tests\UIComponent.as
+ * PackageNode "mx.core" 12:1 436-465667 D:\tests\UIComponent.as
+ * FullNameNode "mx.core" 0:0 444-451 null
+ * IdentifierNode "mx" 12:9 444-446 D:\tests\UIComponent.as
+ * IdentifierNode "core" 12:12 447-451 D:\tests\UIComponent.as
+ * ScopedBlockNode 13:1 454-465667 D:\tests\UIComponent.as
+ * ImportNode "flash.accessibility.Accessibility" 14:1 457-497 D:\tests\UIComponent.as
+ * FullNameNode "flash.accessibility.Accessibility" 0:0 464-497 null
+ * FullNameNode "flash.accessibility" 0:0 464-483 null
+ * IdentifierNode "flash" 14:8 464-469 D:\tests\UIComponent.as
+ * IdentifierNode "accessibility" 14:14 470-483 D:\tests\UIComponent.as
+ * IdentifierNode "Accessibility" 14:28 484-497 D:\tests\UIComponent.as
+ * ...
+ * </pre>
+ * <p>
+ * Subclasses may not override this, because we want to maintain regularity
+ * for how all nodes display.
+ */
+ @Override
+ public final String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ buildStringRecursive(sb, 0, false);
+ return sb.toString();
+ }
+
+ /**
+ * For debugging only. Called by {@code toString()}, and recursively by
+ * itself, to display this node on one line and each descendant node on
+ * subsequent indented lines.
+ *
+ * * */
+ public void buildStringRecursive(StringBuilder sb, int level, boolean skipSrcPath)
+ {
+ // Indent two spaces for each nesting level.
+ for (int i = 0; i < level; i++)
+ {
+ sb.append(" ");
+ }
+
+ // Build the string that represents this node.
+ buildOuterString(sb, skipSrcPath);
+
+ sb.append('\n');
+
+ //To test scopes in ParserSuite
+ if(skipSrcPath && (this instanceof IScopedNode)) {
+ for (int i = 0; i < level+1; i++)
+ sb.append(" ");
+ sb.append("[Scope]");
+ sb.append("\n");
+ IScopedNode scopedNode = (IScopedNode)this;
+ IASScope scope = scopedNode.getScope();
+ Collection<IDefinition> definitions = scope.getAllLocalDefinitions();
+ for(IDefinition def : definitions) {
+ for (int i = 0; i < level+2; i++)
+ sb.append(" ");
+ ((DefinitionBase)def).buildString(sb, false);
+ sb.append('\n');
+ }
+ }
+
+ // Recurse over the child nodes.
+ int n = getChildCount();
+ for (int i = 0; i < n; i++)
+ {
+ NodeBase child = (NodeBase)getChild(i);
+ // The child can be null if we're toString()'ing
+ // in the debugger during tree building.
+ if (child != null)
+ child.buildStringRecursive(sb, level + 1, skipSrcPath);
+ }
+ }
+
+ /**
+ * For debugging only. Called by {@code buildStringRecursive()} to display
+ * information for this node only.
+ * <p>
+ * An example is
+ *
+ * <pre>
+ * PackageNode "mx.core" 12:1 436-465667 D:\tests\UIComponent.as
+ * </pre>.
+ * <p>
+ * The type of node (PackageNode) is displayed first, followed by
+ * node-specific information ("mx.core") followed by location information in
+ * the form
+ *
+ * <pre>
+ * line:column start-end sourcepath
+ * </pre>
+ *
+ */
+ private void buildOuterString(StringBuilder sb, boolean skipSrcPath)
+ {
+ // First display the type of node, as represented by
+ // the short name of the node class.
+ sb.append(getNodeKind());
+
+ sb.append("(").append(getNodeID().name()).append(")");
+
+ sb.append(' ');
+
+ // Display optional node-specific information in the middle.
+ if (buildInnerString(sb))
+ sb.append(' ');
+
+ // The SourceLocation superclass handles producing a string such as
+ // "17:5 160-188" C:/test.as".
+ if(skipSrcPath)
+ sb.append(getOffsetsString());
+ else
+ sb.append(super.toString());
+ }
+
+ /**
+ * For debugging only. This method is called by {@code buildOuterString()}.
+ * It is overridden by subclasses to display optional node-specific
+ * information in the middle of the string, between the node type and the
+ * location information.
+ */
+ protected boolean buildInnerString(StringBuilder sb)
+ {
+ return false;
+ }
+
+ /**
+ * For debugging only.
+ */
+ public String getInnerString()
+ {
+ StringBuilder sb = new StringBuilder();
+ buildInnerString(sb);
+ return sb.toString();
+ }
+
+ public ASFileScope getFileScope()
+ {
+ ASScope scope = getASScope();
+ assert scope != null;
+ while (!(scope instanceof ASFileScope))
+ {
+ scope = scope.getContainingScope();
+ assert scope != null;
+ }
+ return (ASFileScope)scope;
+ }
+
+ /**
+ * @return {@link OffsetLookup} object for the current tree or null.
+ */
+ protected final OffsetLookup tryGetOffsetLookup()
+ {
+ // Try FileNode.getOffsetLookup()
+ final IASNode fileNode = getAncestorOfType(IFileNode.class);
+ if (fileNode != null)
+ return ((IFileNode)fileNode).getOffsetLookup();
+ else
+ return null;
+ }
+
+ /**
+ * Get's the {@link IWorkspace} in which this {@link NodeBase} lives.
+ *
+ * @return The {@link IWorkspace} in which this {@link NodeBase} lives.
+ */
+ public IWorkspace getWorkspace()
+ {
+ return getFileScope().getWorkspace();
+ }
+
+ /**
+ * Get the scope this Node uses for name resolution as an ASScope.
+ *
+ * @return the ASScope for this node, or null if there isn't one.
+ */
+ public ASScope getASScope()
+ {
+ IScopedNode scopeNode = getContainingScope();
+ IASScope scope = scopeNode != null ? scopeNode.getScope() : null;
+
+ // If the ScopedNode had a null scope, keep looking up the tree until we
+ // find one with a non-null scope.
+ // TODO: Is it a bug that an IScopedNode returns null for it's scope?
+ // TODO: this seems like a leftover from block scoping - for example, a
+ // TODO: ForLoopNode is an IScopedNode, but it doesn't really have a scope
+ while (scope == null && scopeNode != null)
+ {
+ scopeNode = scopeNode.getContainingScope();
+ scope = scopeNode != null ? scopeNode.getScope() : null;
+ }
+
+ if (scope instanceof TypeScope)
+ {
+ TypeScope typeScope = (TypeScope)scope;
+ if (this instanceof BaseDefinitionNode)
+ {
+ if (((BaseDefinitionNode)this).hasModifier(ASModifier.STATIC))
+ scope = typeScope.getStaticScope();
+ else
+ scope = typeScope.getInstanceScope();
+ }
+ else
+ {
+ // Do we need the class or instance scope?
+ BaseDefinitionNode bdn = (BaseDefinitionNode)this.getAncestorOfType(BaseDefinitionNode.class);
+ if (bdn instanceof ClassNode)
+ {
+ // We must be loose code in a class
+ scope = typeScope.getStaticScope();
+ }
+ else
+ {
+ if (bdn != null && bdn.hasModifier(ASModifier.STATIC)
+ // Namespaces are always static
+ || bdn instanceof NamespaceNode)
+ scope = typeScope.getStaticScope();
+ else
+ scope = typeScope.getInstanceScope();
+ }
+ }
+ }
+ ASScope asScope = scope instanceof ASScope ? (ASScope)scope : null;
+ return asScope;
+ }
+
+ /**
+ * Get the node's local start offset.
+ */
+ @Override
+ public int getStart()
+ {
+ final OffsetLookup offsetLookup = tryGetOffsetLookup();
+ if (offsetLookup != null)
+ {
+ // to handle start offset in an included file
+ int absoluteOffset = getAbsoluteStart();
+ final String pathBeforeCaret = offsetLookup.getFilename(absoluteOffset - 1);
+ // if the offset is the first offset in the included file return without adjustment
+ if (pathBeforeCaret != null && pathBeforeCaret.equals(getSourcePath()))
+ return offsetLookup.getLocalOffset(absoluteOffset-1)+1;
+
+ return offsetLookup.getLocalOffset(absoluteOffset);
+ }
+
+ return super.getStart();
+ }
+
+ /**
+ * Get the node's local end offset.
+ */
+ @Override
+ public int getEnd()
+ {
+ final OffsetLookup offsetLookup = tryGetOffsetLookup();
+ return offsetLookup != null ?
+ // to handle end offset in an included file
+ offsetLookup.getLocalOffset(super.getEnd() - 1) + 1 :
+ super.getEnd();
+ }
+
+ /**
+ * @return The node's absolute start offset.
+ */
+ @Override
+ public int getAbsoluteStart()
+ {
+ return super.getStart();
+ }
+
+ /**
+ * @return The node's absolute end offset.
+ */
+ @Override
+ public int getAbsoluteEnd()
+ {
+ return super.getEnd();
+ }
+
+ /**
+ * Collects the import nodes that are descendants of this node
+ * but which are not contained within a scoped node.
+ * <p>
+ * This is a helper method for {@link IScopedNode#getAllImportNodes}().
+ * Since that method walks up the chain of scoped nodes, we don't want
+ * to look inside scoped nodes that were already processed.
+ *
+ * @param importNodes The collection of import nodes being built.
+ */
+ public void collectImportNodes(Collection<IImportNode> importNodes)
+ {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; ++i)
+ {
+ IASNode child = getChild(i);
+
+ if (child instanceof IImportNode)
+ importNodes.add((IImportNode)child);
+
+ else if (!(child instanceof IScopedNode))
+ ((NodeBase)child).collectImportNodes(importNodes);
+ }
+ }
+
+ /**
+ * Used only in asserts.
+ */
+ public boolean verify()
+ {
+ // Verify the id.
+ ASTNodeID id = getNodeID();
+ assert id != null &&
+ id != ASTNodeID.InvalidNodeID &&
+ id != ASTNodeID.UnknownID : "Definition has bad id";
+
+ // TODO: Verify the source location eventually.
+ // assert getSourcePath() != null : "Node has null source path:\n" + toString();
+ // assert getStart() != UNKNOWN : "Node has unknown start:\n" + toString();
+ // assert getEnd() != UNKNOWN : "Node has unknown end:\n" + toString();
+ // assert getLine() != UNKNOWN : "Node has unknown line:\n" + toString();
+ // assert getColumn() != UNKNOWN : "Node has unknown column:\n" + toString();
+
+ // Verify the children.
+ int n = getChildCount();
+ for (int i = 0; i < n; i++)
+ {
+ // Any null children?
+ NodeBase child = (NodeBase)getChild(i);
+ assert child != null : "Node has null child";
+
+ // Does each child have this node as its parent?
+ // (Note: Two node classes override getParent() to not return the parent,
+ // so exclude these for now.)
+ if (!(child instanceof NamespaceIdentifierNode || child instanceof QualifiedNamespaceExpressionNode))
+ {
+ assert child.getParent() == this : "Child node has bad parent";
+ }
+
+ // Recurse on each child.
+ child.verify();
+ }
+
+ return true;
+ }
+
+ /**
+ * Counts various types of nodes that are created,
+ * as well as the total number of nodes.
+ */
+ private void countNodes()
+ {
+ Counter counter = Counter.getInstance();
+ counter.incrementCount(getClass().getSimpleName());
+ counter.incrementCount("nodes");
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
----------------------------------------------------------------------
diff --cc compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
index 5de6521,0000000..51eb0fc
mode 100644,000000..100644
--- a/compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
@@@ -1,130 -1,0 +1,132 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.tree.as;
+
+import org.apache.flex.compiler.internal.parsing.as.OffsetLookup;
+import org.apache.flex.compiler.parsing.IASToken;
+import org.apache.flex.compiler.tree.as.IOperatorNode;
+
+/**
+ * ActionScript parse tree node representing a binary operator expression (e.g.
+ * x + 2 or var1 == var2)
+ */
+public abstract class OperatorNodeBase extends ExpressionNodeBase implements IOperatorNode
+{
+ /**
+ * Constructor.
+ *
+ * @param operator ASToken holding the operator itself
+ */
+ public OperatorNodeBase(IASToken operator)
+ {
+ if (operator != null)
+ {
+ operatorStart = operator.getStart();
+ setLine(operator.getLine());
+ setColumn(operator.getColumn());
++ setEndLine(operator.getEndLine());
++ setEndColumn(operator.getEndColumn());
+ setSourcePath(operator.getSourcePath());
+ }
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param other The node to copy.
+ */
+ protected OperatorNodeBase(OperatorNodeBase other)
+ {
+ super(other);
+
+ this.operatorStart = other.operatorStart;
+ }
+
+ /**
+ * Offset where the operator starts
+ */
+ protected int operatorStart = UNKNOWN;
+
+ //
+ // NodeBase overrides
+ //
+
+ @Override
+ public boolean isTerminal()
+ {
+ return false;
+ }
+
+ /*
+ * For debugging only. Builds a string such as <code>"+"</code> from the
+ * operator.
+ */
+ @Override
+ protected boolean buildInnerString(StringBuilder sb)
+ {
+ sb.append('"');
+ sb.append(getOperatorText());
+ sb.append('"');
+
+ return true;
+ }
+
+ //
+ // IOperatorNode implementations
+ //
+
+ @Override
+ public int getOperatorStart()
+ {
+ final OffsetLookup offsetLookup = tryGetOffsetLookup();
+ return offsetLookup != null ?
+ offsetLookup.getLocalOffset(operatorStart) :
+ operatorStart;
+ }
+
+ @Override
+ public int getOperatorEnd()
+ {
+ int operatorStart = getOperatorStart();
+ return operatorStart != -1 ? operatorStart + getOperatorText().length() : operatorStart;
+ }
+
+ @Override
+ public int getOperatorAbsoluteStart()
+ {
+ return operatorStart;
+ }
+
+ @Override
+ public int getOperatorAbsoluteEnd()
+ {
+ return operatorStart != -1 ? operatorStart + getOperatorText().length() : operatorStart;
+ }
+
+ //
+ // Other methods
+ //
+
+ public String getOperatorText()
+ {
+ OperatorType operator = getOperator();
+ return operator != null ? operator.getOperatorText() : "";
+ }
+}
[06/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - ASParser: array contents start
after [ and before ], and ArrayLiteralNode includes them
Posted by cd...@apache.org.
ASParser: array contents start after [ and before ], and ArrayLiteralNode includes them
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/b2bfa2c9
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/b2bfa2c9
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/b2bfa2c9
Branch: refs/heads/feature/maven-migration-test
Commit: b2bfa2c9a6a7da9ebe5363117f6e6438e5ddc6a4
Parents: c22e5a0
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 19:39:31 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 19:39:31 2016 -0700
----------------------------------------------------------------------
.../src/org/apache/flex/compiler/internal/parsing/as/ASParser.g | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/b2bfa2c9/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g b/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g
index 34cb240..4d4936b 100644
--- a/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g
+++ b/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g
@@ -2481,9 +2481,9 @@ arrayInitializer [ArrayLiteralNode node]
{
final ContainerNode contents = node.getContentsNode();
}
- : open:TOKEN_SQUARE_OPEN { contents.startBefore(open); }
+ : open:TOKEN_SQUARE_OPEN { node.startBefore(open); contents.startAfter(open); }
arrayElements[contents]
- close:TOKEN_SQUARE_CLOSE { contents.endAfter(close); }
+ close:TOKEN_SQUARE_CLOSE { node.endAfter(close); contents.endBefore(close); }
;
exception catch [RecognitionException ex]
{
[09/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - compiler.jx.tests: expanded
source map tests to include some missing mappings
Posted by cd...@apache.org.
compiler.jx.tests: expanded source map tests to include some missing mappings
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/e9fd628e
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/e9fd628e
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/e9fd628e
Branch: refs/heads/feature/maven-migration-test
Commit: e9fd628e5305a651f4cf0be0b744b885aee68b39
Parents: 01629b2
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 23:27:10 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 23:27:10 2016 -0700
----------------------------------------------------------------------
.../js/sourcemaps/TestSourceMapExpressions.java | 181 +++++++++++--------
.../js/sourcemaps/TestSourceMapStatements.java | 19 +-
2 files changed, 124 insertions(+), 76 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e9fd628e/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
index 57ab17b..90aab08 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
@@ -31,7 +31,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a + b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // +
}
@Test
@@ -39,7 +39,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a - b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // -
}
@Test
@@ -47,7 +47,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a / b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // /
}
@Test
@@ -55,7 +55,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a % b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // %
}
@Test
@@ -63,7 +63,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a * b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // *
}
@Test
@@ -71,7 +71,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("a++");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 3);
+ assertMapping(node, 0, 1, 0, 1, 0, 3); // ++
}
@Test
@@ -79,7 +79,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("++a");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 2);
+ assertMapping(node, 0, 0, 0, 0, 0, 2); // +
}
@Test
@@ -87,7 +87,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("a--");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 3);
+ assertMapping(node, 0, 1, 0, 1, 0, 3); // --
}
@Test
@@ -95,7 +95,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("--a");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 2);
+ assertMapping(node, 0, 0, 0, 0, 0, 2); // --
}
//----------------------------------
@@ -151,7 +151,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a = b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // =
}
//----------------------------------
@@ -163,7 +163,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a & b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // &
}
@Test
@@ -171,7 +171,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a << b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // <<
}
@Test
@@ -179,7 +179,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("~a");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 1);
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // ~
}
@Test
@@ -187,7 +187,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a | b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // |
}
@Test
@@ -195,7 +195,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a >> b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // >>
}
@Test
@@ -203,7 +203,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a >>> b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 6);
+ assertMapping(node, 0, 1, 0, 1, 0, 6); // >>>
}
@Test
@@ -211,7 +211,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a ^ b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // ^
}
//----------------------------------
@@ -275,7 +275,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a == b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // ==
}
@Test
@@ -283,7 +283,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a > b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // >
}
@Test
@@ -291,7 +291,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a >= b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // >=
}
@Test
@@ -299,7 +299,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a != b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // !=
}
@Test
@@ -307,7 +307,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a < b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // <
}
@Test
@@ -315,7 +315,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a <= b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // <=
}
@Test
@@ -323,7 +323,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a === b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 6);
+ assertMapping(node, 0, 1, 0, 1, 0, 6); // ===
}
@Test
@@ -331,7 +331,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a !== b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 6);
+ assertMapping(node, 0, 1, 0, 1, 0, 6); // !==
}
//----------------------------------
@@ -343,7 +343,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a && b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // &&
}
@Test
@@ -352,8 +352,8 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IBinaryOperatorNode node = getBinaryNode("a &&= b");
asBlockWalker.visitBinaryOperator(node);
//a = a && b
- assertMapping(node, 0, 1, 0, 1, 0, 4);
- assertMapping(node, 0, 1, 0, 5, 0, 9);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // =
+ assertMapping(node, 0, 1, 0, 5, 0, 9); // &&
}
@Test
@@ -361,7 +361,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("!a");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 1);
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // !
}
@Test
@@ -369,7 +369,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a || b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // ||
}
@Test
@@ -378,8 +378,8 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IBinaryOperatorNode node = getBinaryNode("a ||= b");
asBlockWalker.visitBinaryOperator(node);
//a = a || b
- assertMapping(node, 0, 1, 0, 1, 0, 4);
- assertMapping(node, 0, 1, 0, 5, 0, 9);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // =
+ assertMapping(node, 0, 1, 0, 5, 0, 9); // ||
}
//----------------------------------
@@ -391,8 +391,10 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IDynamicAccessNode node = getDynamicAccessNode("a[b]");
asBlockWalker.visitDynamicAccess(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // [
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
+ assertMapping(node, 0, 3, 0, 3, 0, 4); // ]
}
@Test
@@ -400,12 +402,16 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IDynamicAccessNode node = getDynamicAccessNode("a[b[c][d]]");
asBlockWalker.visitDynamicAccess(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
- assertMapping(node, 0, 5, 0, 5, 0, 6);
- assertMapping(node, 0, 6, 0, 6, 0, 7);
- assertMapping(node, 0, 8, 0, 8, 0, 9);
- assertMapping(node, 0, 9, 0, 9, 0, 10);
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // [
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
+ assertMapping(node, 0, 3, 0, 3, 0, 4); // [
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // c
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // ]
+ assertMapping(node, 0, 6, 0, 6, 0, 7); // [
+ assertMapping(node, 0, 7, 0, 7, 0, 8); // d
+ assertMapping(node, 0, 8, 0, 8, 0, 9); // ]
+ assertMapping(node, 0, 9, 0, 9, 0, 10); // ]
}
@Test
@@ -413,7 +419,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a, b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 3);
+ assertMapping(node, 0, 1, 0, 1, 0, 3); // ,
}
@Test
@@ -422,8 +428,8 @@ public class TestSourceMapExpressions extends SourceMapTestBase
ITernaryOperatorNode node = (ITernaryOperatorNode) getExpressionNode(
"a ? b : c", ITernaryOperatorNode.class);
asBlockWalker.visitTernaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
- assertMapping(node, 0, 5, 0, 5, 0, 8);
+ assertMapping(node, 0, 1, 0, 1, 0, 4); // ?
+ assertMapping(node, 0, 5, 0, 5, 0, 8); // :
}
@Test
@@ -431,7 +437,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("delete a");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
+ assertMapping(node, 0, 0, 0, 0, 0, 7); // delete
}
@Test
@@ -440,7 +446,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IMemberAccessExpressionNode node = (IMemberAccessExpressionNode) getExpressionNode(
"a.b", IMemberAccessExpressionNode.class);
asBlockWalker.visitMemberAccessExpression(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // .
}
@Test
@@ -449,9 +455,9 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IMemberAccessExpressionNode node = (IMemberAccessExpressionNode) getExpressionNode(
"a.b.c.d", IMemberAccessExpressionNode.class);
asBlockWalker.visitMemberAccessExpression(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
- assertMapping(node, 0, 5, 0, 5, 0, 6);
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // .
+ assertMapping(node, 0, 3, 0, 3, 0, 4); // .
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // .
}
@Test
@@ -459,7 +465,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a in b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
+ assertMapping(node, 0, 1, 0, 1, 0, 5); // in
}
@Test
@@ -467,7 +473,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IBinaryOperatorNode node = getBinaryNode("a instanceof b");
asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 13);
+ assertMapping(node, 0, 1, 0, 1, 0, 13); // instanceof
}
@Test
@@ -476,7 +482,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IFunctionCallNode node = (IFunctionCallNode) getExpressionNode(
"new Object()", IFunctionCallNode.class);
asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 0, 0, 0, 0, 4);
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // new
}
@Test
@@ -485,6 +491,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
ObjectLiteralNode node = (ObjectLiteralNode) getExpressionNode(
"a = {a:1}", ObjectLiteralNode.class);
asBlockWalker.visitLiteral(node);
+ //{a: 1}
assertMapping(node, 0, 0, 0, 0, 0, 1); // {
assertMapping(node, 0, 1, 0, 1, 0, 2); // a
assertMapping(node, 0, 2, 0, 2, 0, 3); // :
@@ -536,6 +543,24 @@ public class TestSourceMapExpressions extends SourceMapTestBase
}
@Test
+ public void testVisitObjectLiteral_4()
+ {
+ ObjectLiteralNode node = (ObjectLiteralNode) getExpressionNode(
+ "a = {a:1,\nb:2}", ObjectLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
+ //{a:1, b:2}
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // {
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // a
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // :
+ assertMapping(node, 0, 3, 0, 3, 0, 4); // 1
+ assertMapping(node, 0, 4, 0, 4, 0, 6); // ,
+ assertMapping(node, 1, 0, 0, 6, 0, 7); // b
+ assertMapping(node, 1, 1, 0, 7, 0, 8); // :
+ assertMapping(node, 1, 2, 0, 8, 0, 9); // 2
+ assertMapping(node, 1, 3, 0, 9, 0, 10); // }
+ }
+
+ @Test
public void testVisitArrayLiteral_1()
{
ArrayLiteralNode node = (ArrayLiteralNode) getExpressionNode(
@@ -543,8 +568,11 @@ public class TestSourceMapExpressions extends SourceMapTestBase
asBlockWalker.visitLiteral(node);
//[0, 1, 2]
assertMapping(node, 0, 0, 0, 0, 0, 1); // [
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // 0
assertMapping(node, 0, 2, 0, 2, 0, 4); // ,
+ assertMapping(node, 0, 3, 0, 4, 0, 5); // 1
assertMapping(node, 0, 4, 0, 5, 0, 7); // ,
+ assertMapping(node, 0, 5, 0, 7, 0, 8); // 2
assertMapping(node, 0, 6, 0, 8, 0, 9); // ]
}
@@ -598,8 +626,8 @@ public class TestSourceMapExpressions extends SourceMapTestBase
assertMapping(node, 0, 2, 0, 2, 0, 4); // ,
assertMapping(node, 1, 0, 0, 4, 0, 7); // 123
assertMapping(node, 1, 3, 0, 7, 0, 9); // ,
- assertMapping(node, 1, 5, 0, 9, 0, 11); // 45
- //TODO: figure out how to place the ]
+ assertMapping(node, 1, 5, 0, 9, 0, 11); // 45
+ assertMapping(node, 1, 7, 0, 11, 0, 12); // 45
}
@Test
@@ -607,8 +635,9 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("typeof(a)");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
- assertMapping(node, 0, 0, 0, 8, 0, 9);
+ //typeof(a)
+ assertMapping(node, 0, 0, 0, 0, 0, 7); // typeof(
+ assertMapping(node, 0, 0, 0, 8, 0, 9); // )
}
@Test
@@ -617,8 +646,9 @@ public class TestSourceMapExpressions extends SourceMapTestBase
// TODO (mschmalle) the notation without parenthesis is also valid in AS/JS
IUnaryOperatorNode node = getUnaryNode("typeof a");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
- assertMapping(node, 0, 0, 0, 8, 0, 9);
+ //typeof(a)
+ assertMapping(node, 0, 0, 0, 0, 0, 7); // typeof(
+ assertMapping(node, 0, 0, 0, 8, 0, 9); // )
}
@Test
@@ -626,7 +656,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IUnaryOperatorNode node = getUnaryNode("void a");
asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 5);
+ assertMapping(node, 0, 0, 0, 0, 0, 5); // void
}
@Test
@@ -635,7 +665,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IIterationFlowNode node = (IIterationFlowNode) getNode("break",
IIterationFlowNode.class);
asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 5);
+ assertMapping(node, 0, 0, 0, 0, 0, 5); // break
}
@Test
@@ -644,7 +674,8 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IIterationFlowNode node = (IIterationFlowNode) getNode("break label",
IIterationFlowNode.class);
asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 6);
+ assertMapping(node, 0, 0, 0, 0, 0, 6); // break
+ assertMapping(node, 0, 6, 0, 6, 0, 11); // label
}
@Test
@@ -653,7 +684,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IIterationFlowNode node = (IIterationFlowNode) getNode("continue",
IIterationFlowNode.class);
asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 8);
+ assertMapping(node, 0, 0, 0, 0, 0, 8); // continue
}
@Test
@@ -662,7 +693,8 @@ public class TestSourceMapExpressions extends SourceMapTestBase
IIterationFlowNode node = (IIterationFlowNode) getNode("continue label",
IIterationFlowNode.class);
asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 9);
+ assertMapping(node, 0, 0, 0, 0, 0, 9); // continue
+ assertMapping(node, 0, 9, 0, 9, 0, 14); // label
}
@Test
@@ -670,7 +702,7 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IReturnNode node = (IReturnNode) getNode("return", IReturnNode.class);
asBlockWalker.visitReturn(node);
- assertMapping(node, 0, 0, 0, 0, 0, 6);
+ assertMapping(node, 0, 0, 0, 0, 0, 6); // return
}
@Test
@@ -678,7 +710,8 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IReturnNode node = (IReturnNode) getNode("return 0", IReturnNode.class);
asBlockWalker.visitReturn(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
+ assertMapping(node, 0, 0, 0, 0, 0, 7); // return
+ assertMapping(node, 0, 7, 0, 7, 0, 8); // 0
}
@Test
@@ -686,8 +719,9 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IFunctionCallNode node = (IFunctionCallNode) getNode("a()", IFunctionCallNode.class);
asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 2, 0, 2, 0, 3);
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // (
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // )
}
@Test
@@ -695,8 +729,10 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IFunctionCallNode node = (IFunctionCallNode) getNode("a(b)", IFunctionCallNode.class);
asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // (
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
+ assertMapping(node, 0, 3, 0, 3, 0, 4); // )
}
@Test
@@ -704,9 +740,12 @@ public class TestSourceMapExpressions extends SourceMapTestBase
{
IFunctionCallNode node = (IFunctionCallNode) getNode("a(b, c)", IFunctionCallNode.class);
asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 5);
- assertMapping(node, 0, 6, 0, 6, 0, 7);
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // (
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
+ assertMapping(node, 0, 3, 0, 3, 0, 5); // ,
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // c
+ assertMapping(node, 0, 6, 0, 6, 0, 7); // )
}
protected IBackend createBackend()
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e9fd628e/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
index 436ee15..265b94c 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
@@ -128,6 +128,7 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 27, 0, 45, 0, 47); // ;
assertMapping(node, 0, 32, 0, 50, 0, 52); // )
assertMapping(node, 0, 34, 0, 52, 0, 53); // {
+ assertMapping(node, 0, 43, 2, 0, 2, 1); // }
}
@Test
@@ -150,11 +151,12 @@ public class TestSourceMapStatements extends SourceMapTestBase
IForLoopNode.class);
asBlockWalker.visitForLoop(node);
//for (;;) {\n break;\n}
- assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
- assertMapping(node, 0, 5, 0, 5, 0, 6); // ;
- assertMapping(node, 0, 6, 0, 6, 0, 7); // ;
- assertMapping(node, 0, 7, 0, 7, 0, 9); // )
+ assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
+ assertMapping(node, 0, 5, 0, 5, 0, 6); // ;
+ assertMapping(node, 0, 6, 0, 6, 0, 7); // ;
+ assertMapping(node, 0, 7, 0, 7, 0, 9); // )
assertMapping(node, 0, 9, 0, 9, 0, 10); // {
+ assertMapping(node, 0, 18, 2, 0, 2, 1); // }
}
@Test
@@ -168,6 +170,7 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 14, 0, 32, 0, 36); // in
assertMapping(node, 0, 21, 0, 39, 0, 41); // )
assertMapping(node, 0, 23, 0, 41, 0, 42); // {
+ assertMapping(node, 0, 32, 2, 0, 2, 1); // }
}
@Test
@@ -239,6 +242,7 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 4, 0, 4, 0, 5); // a
assertMapping(node, 0, 5, 0, 5, 0, 7); // )
assertMapping(node, 0, 7, 0, 7, 0, 8); // {
+ assertMapping(node, 0, 14, 2, 0, 2, 1); // }
}
@Test
@@ -252,8 +256,10 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 4, 0, 4, 0, 5); // a
assertMapping(node, 0, 5, 0, 5, 0, 7); // )
assertMapping(node, 0, 7, 0, 7, 0, 8); // {
+ assertMapping(node, 0, 14, 2, 0, 2, 1); // }
assertMapping(node, 0, 16, 2, 2, 2, 7); // else
assertMapping(node, 0, 21, 2, 7, 2, 8); // {
+ assertMapping(node, 0, 28, 4, 0, 4, 1); // }
}
@Test
@@ -268,11 +274,14 @@ public class TestSourceMapStatements extends SourceMapTestBase
assertMapping(node, 0, 4, 0, 4, 0, 5); // a
assertMapping(node, 0, 5, 0, 5, 0, 7); // )
assertMapping(node, 0, 7, 0, 7, 0, 8); // {
+ assertMapping(node, 0, 14, 2, 0, 2, 1); // }
assertMapping(node, 0, 16, 2, 2, 2, 11); // else if(
assertMapping(node, 0, 26, 2, 12, 2, 14); // )
assertMapping(node, 0, 28, 2, 14, 2, 15); // {
+ assertMapping(node, 0, 35, 4, 0, 4, 1); // }
assertMapping(node, 0, 37, 4, 2, 4, 7); // else
- assertMapping(node, 0, 42, 4, 7, 4, 8); // {
+ assertMapping(node, 0, 42, 4, 7, 4, 8); // {
+ assertMapping(node, 0, 49, 6, 0, 6, 1); // {
}
@Test
[10/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - Merge branches 'develop' and
'feature/maven-migration-test' of
https://git-wip-us.apache.org/repos/asf/flex-falcon into
feature/maven-migration-test
Posted by cd...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/java/org/apache/flex/compiler/problems/CompilerProblem.java
----------------------------------------------------------------------
diff --cc compiler/src/main/java/org/apache/flex/compiler/problems/CompilerProblem.java
index ee9c9a1,0000000..d2e9366
mode 100644,000000..100644
--- a/compiler/src/main/java/org/apache/flex/compiler/problems/CompilerProblem.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/problems/CompilerProblem.java
@@@ -1,222 -1,0 +1,234 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.problems;
+
+import org.apache.flex.compiler.clients.problems.ProblemFormatter;
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.internal.parsing.as.ASToken;
+import org.apache.flex.compiler.problems.annotations.DefaultSeverity;
+import org.apache.flex.compiler.problems.annotations.ProblemClassification;
+import org.apache.flex.utils.FilenameNormalization;
+
+/**
+ * CompilerProblem is the base class for all error and warning classes in the compiler,
+ * which are collectively called "problems".
+ *
+ * Each problem has
+ * 1) source location information (file/start/end/line/column);
+ * 2) a description with named placeholders which get filled in
+ * from the public fields of the problem class;
+ * 3) the ability to compare itself to other problems,
+ * to produce a nicely sorted list of problems;
+ * 4) the ability to toString() itself for command-line output such as
+ *
+ * C:\Faramir\compiler\trunk\tests\resources\milestones\m1\M1.as:4
+ * Syntax error: '+' is not allowed here
+ * import flash.display.+Sprite;
+ * ^
+ * where a caret marks the offending spot in the offending line.
+ */
+@ProblemClassification(CompilerProblemClassification.DEFAULT)
+@DefaultSeverity(CompilerProblemSeverity.ERROR)
+public abstract class CompilerProblem implements ICompilerProblem
+{
+ /**
+ * Constructor.
+ *
+ * @param sourcePath The path of the file in which the problem occurred.
+ * @param start The offset within the source buffer at which the problem starts.
+ * @param end The offset within the source buffer at which the problem ends.
+ * @param line The line number within the source buffer at which the problem starts.
+ * @param column The column number within the source buffer at which the problem starts.
+ * @param normalizeFilePath true if the path can be normalized. This is needed
+ * by configuration problems that have the "command line" as there source.
+ */
+ public CompilerProblem(String sourcePath, int start, int end, int line, int column,
+ boolean normalizeFilePath)
+ {
+ if (sourcePath != null && normalizeFilePath)
+ sourcePath = FilenameNormalization.normalize(sourcePath);
+
+ this.sourcePath = sourcePath;
+ this.start = start;
+ this.end = end;
+ this.line = line;
+ this.column = column;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param sourcePath The normalized path of the file in which the problem occurred.
+ * @param start The offset within the source buffer at which the problem starts.
+ * @param end The offset within the source buffer at which the problem ends.
+ * @param line The line number within the source buffer at which the problem starts.
+ * @param column The column number within the source buffer at which the problem starts.
+ */
+ public CompilerProblem(String sourcePath, int start, int end, int line, int column)
+ {
+ this(sourcePath, start, end, line, column, true);
+ }
+
+ /**
+ * Constructor for a problem whose only source-location information
+ * is a source path.
+ *
+ * @param sourcePath The normalized path of the file
+ * in which the problem occurred.
+ */
+ public CompilerProblem(String sourcePath)
+ {
+ this(sourcePath, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, true);
+ }
+
+ /**
+ * Constructor for a problem with no source-location information.
+ */
+ public CompilerProblem()
+ {
+ this(null, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, true);
+ }
+
+ /**
+ * Constructor for a problem associated with an object
+ * implementing {@link ISourceLocation}.
+ *
+ * @param site The {@link ISourceLocation} where the problem occurred.
+ */
+ public CompilerProblem(ISourceLocation site)
+ {
+ this(site.getSourcePath(),
+ site.getStart(), site.getEnd(),
+ site.getLine(), site.getColumn());
+ }
+
+ /**
+ * Constructor for a problem associated with an {@link IDefinition}.
+ *
+ * @param site The {@link IDefinition} where the problem occurred.
+ */
+ public CompilerProblem(IDefinition site)
+ {
+ this(site.getSourcePath(),
+ site.getNameStart(), site.getNameEnd(),
+ site.getNameLine(), site.getNameColumn());
+ }
+
+ /**
+ * Constructor for a problem associated with an {@link ASToken}.
+ *
+ * @param site The {@link ASToken} where the problem occurred.
+ */
+ public CompilerProblem(ASToken site)
+ {
+ this(site.getSourcePath(),
+ site.getLocalStart(), site.getLocalEnd(),
+ site.getLine(), site.getColumn());
+ }
+
+ private final String sourcePath;
+ private final int start;
+ private final int end;
+ private final int line;
+ private final int column;
+
+ @Override
+ public String getID()
+ {
+ // Return the fully-qualified classname of the CompilerProblem subclass
+ // as a String to identify the type of problem that occurred.
+ return getClass().getName();
+ }
+
+ @Override
+ public String getSourcePath()
+ {
+ return sourcePath;
+ }
+
+ @Override
+ public int getStart()
+ {
+ return start;
+ }
+
+ @Override
+ public int getEnd()
+ {
+ return end;
+ }
+
+ @Override
+ public int getLine()
+ {
+ return line;
+ }
+
+ @Override
+ public int getColumn()
+ {
+ return column;
+ }
+
+ @Override
++ public int getEndLine()
++ {
++ return line;
++ }
++
++ @Override
++ public int getEndColumn()
++ {
++ return column;
++ }
++
++ @Override
+ public int getAbsoluteStart()
+ {
+ return start;
+ }
+
+ @Override
+ public int getAbsoluteEnd()
+ {
+ return end;
+ }
+
+ /**
+ * Returns a String for displaying this compiler problem in a console window.
+ *
+ * This is for debugging purposes, therefore no non-test code should call this.
+ *
+ * There are typically four lines output for each problem:
+ * location (file and line number)
+ * description
+ *
+ * For example:
+ *
+ * C:\Faramir\compiler\trunk\tests\resources\milestones\m1\M1.as:4
+ * Syntax error: '+' not allowed here.
+ */
+ @Override
+ public String toString()
+ {
+ return ProblemFormatter.DEFAULT_FORMATTER.format(this);
+ }
+}
[08/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - compiler.jx: updated JSEmitter to
support new getEndLine() and getEndColumn(),
and tweaked some sub-emitters to use this change
Posted by cd...@apache.org.
compiler.jx: updated JSEmitter to support new getEndLine() and getEndColumn(), and tweaked some sub-emitters to use this change
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/01629b23
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/01629b23
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/01629b23
Branch: refs/heads/feature/maven-migration-test
Commit: 01629b238544b16f934a91e863f0300956ba6d94
Parents: af3e883
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 22:46:54 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 22:46:54 2016 -0700
----------------------------------------------------------------------
.../org/apache/flex/compiler/codegen/js/IJSEmitter.java | 2 +-
.../flex/compiler/internal/codegen/js/JSEmitter.java | 10 +++++-----
.../flex/compiler/internal/codegen/js/JSSubEmitter.java | 4 ++--
.../internal/codegen/js/jx/BlockCloseEmitter.java | 2 +-
.../internal/codegen/js/jx/LiteralContainerEmitter.java | 2 +-
.../codegen/js/jx/ObjectLiteralValuePairEmitter.java | 6 +++---
6 files changed, 13 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/01629b23/compiler.jx/src/org/apache/flex/compiler/codegen/js/IJSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/codegen/js/IJSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/codegen/js/IJSEmitter.java
index 218b5be..287b8c8 100644
--- a/compiler.jx/src/org/apache/flex/compiler/codegen/js/IJSEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/codegen/js/IJSEmitter.java
@@ -59,7 +59,7 @@ public interface IJSEmitter extends IASEmitter
* Adds a node to the source map after a particular node instead using the
* node's own line and column.
*/
- void startMapping(ISourceLocation node, ISourceLocation nodeBeforeMapping);
+ void startMapping(ISourceLocation node, ISourceLocation afterNode);
/**
* Commits a mapping to the source map.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/01629b23/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
index 1a73cf6..d0a4aa8 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
@@ -366,11 +366,6 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
{
startMapping(node, node.getLine(), node.getColumn());
}
-
- public void startMapping(ISourceLocation node, ISourceLocation nodeBeforeMapping)
- {
- startMapping(node, nodeBeforeMapping.getLine(), nodeBeforeMapping.getColumn() + nodeBeforeMapping.getAbsoluteEnd() - nodeBeforeMapping.getAbsoluteStart());
- }
public void startMapping(ISourceLocation node, int line, int column)
{
@@ -414,6 +409,11 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
lastMapping = mapping;
}
+ public void startMapping(ISourceLocation node, ISourceLocation afterNode)
+ {
+ startMapping(node, afterNode.getEndLine(), afterNode.getEndColumn());
+ }
+
public void endMapping(ISourceLocation node)
{
if (lastMapping == null)
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/01629b23/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
index be0b9d1..f947af6 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
@@ -114,9 +114,9 @@ public class JSSubEmitter
emitter.startMapping(node, line, column);
}
- protected void startMapping(ISourceLocation node, ISourceLocation nodeBeforeMapping)
+ protected void startMapping(ISourceLocation node, ISourceLocation afterNode)
{
- emitter.startMapping(node, nodeBeforeMapping);
+ emitter.startMapping(node, afterNode);
}
protected void endMapping(ISourceLocation node)
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/01629b23/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java
index 3099eda..058d132 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/BlockCloseEmitter.java
@@ -36,7 +36,7 @@ public class BlockCloseEmitter extends JSSubEmitter implements
@Override
public void emit(IContainerNode node)
{
- startMapping(node);
+ startMapping(node, node);
write(ASEmitterTokens.BLOCK_CLOSE);
endMapping(node);
}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/01629b23/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
index d1d24fd..5e0fdce 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
@@ -88,7 +88,7 @@ public class LiteralContainerEmitter extends JSSubEmitter implements
if (postFix != null)
{
- startMapping(node, node.getLine(), node.getColumn() + node.getAbsoluteEnd() - node.getAbsoluteStart() - 1);
+ startMapping(node, node.getEndLine(), node.getEndColumn() - postFix.length());
write(postFix);
endMapping(node);
}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/01629b23/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
index d93d701..ad12b77 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
@@ -38,14 +38,14 @@ public class ObjectLiteralValuePairEmitter extends JSSubEmitter implements
@Override
public void emit(IObjectLiteralValuePairNode node)
{
- ISourceLocation sourceLocationNode = (ISourceLocation) node;
+ ISourceLocation location = (ISourceLocation) node;
IExpressionNode nameNode = node.getNameNode();
getWalker().walk(nameNode);
- startMapping(sourceLocationNode, nameNode);
+ startMapping(location, nameNode);
write(ASEmitterTokens.COLON);
- endMapping(sourceLocationNode);
+ endMapping(location);
IExpressionNode valueNode = node.getValueNode();
getWalker().walk(valueNode);
[13/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - Merge branches 'develop' and
'feature/maven-migration-test' of
https://git-wip-us.apache.org/repos/asf/flex-falcon into
feature/maven-migration-test
Posted by cd...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
index a50e288,0000000..d0a4aa8
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
@@@ -1,453 -1,0 +1,471 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.js;
+
+import java.io.FilterWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitter;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
++import org.apache.flex.compiler.internal.codegen.js.jx.BlockCloseEmitter;
++import org.apache.flex.compiler.internal.codegen.js.jx.BlockOpenEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.DoWhileLoopEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.DynamicAccessEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ForLoopEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.FunctionCallArgumentsEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.IfEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.IterationFlowEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.LanguageIdentifierEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.LiteralContainerEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.MemberKeywordEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.NumericLiteralEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ObjectLiteralValuePairEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ParameterEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ParametersEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ReturnEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.SourceMapDirectiveEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.StatementEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.TernaryOperatorEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.UnaryOperatorEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.WhileLoopEmitter;
+import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
+import org.apache.flex.compiler.tree.as.IForLoopNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IFunctionObjectNode;
+import org.apache.flex.compiler.tree.as.IIfNode;
+import org.apache.flex.compiler.tree.as.IIterationFlowNode;
+import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.flex.compiler.tree.as.ILiteralContainerNode;
+import org.apache.flex.compiler.tree.as.INumericLiteralNode;
+import org.apache.flex.compiler.tree.as.IObjectLiteralValuePairNode;
+import org.apache.flex.compiler.tree.as.IPackageNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.IReturnNode;
+import org.apache.flex.compiler.tree.as.ITernaryOperatorNode;
+import org.apache.flex.compiler.tree.as.ITypeNode;
+import org.apache.flex.compiler.tree.as.ITypedExpressionNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IWhileLoopNode;
+
+import com.google.debugging.sourcemap.FilePosition;
+
+/**
+ * @author Michael Schmalle
+ */
+public class JSEmitter extends ASEmitter implements IJSEmitter
+{
+ private JSSessionModel model;
+
++ public BlockOpenEmitter blockOpenEmitter;
++ public BlockCloseEmitter blockCloseEmitter;
+ public NumericLiteralEmitter numericLiteralEmitter;
+ public ParametersEmitter parametersEmitter;
+ public ParameterEmitter parameterEmitter;
+ public FunctionCallArgumentsEmitter functionCallArgumentsEmitter;
+ public LiteralContainerEmitter literalContainerEmitter;
+ public ObjectLiteralValuePairEmitter objectLiteralValuePairEmitter;
+ public ReturnEmitter returnEmitter;
+ public DynamicAccessEmitter dynamicAccessEmitter;
+ public UnaryOperatorEmitter unaryOperatorEmitter;
+ public TernaryOperatorEmitter ternaryOperatorEmitter;
+ public MemberKeywordEmitter memberKeywordEmitter;
+ public IfEmitter ifEmitter;
+ public WhileLoopEmitter whileLoopEmitter;
+ public DoWhileLoopEmitter doWhileLoopEmitter;
+ public ForLoopEmitter forLoopEmitter;
+ public IterationFlowEmitter interationFlowEmitter;
+ public StatementEmitter statementEmitter;
+ public LanguageIdentifierEmitter languageIdentifierEmitter;
+ public SourceMapDirectiveEmitter sourceMapDirectiveEmitter;
+
+ @Override
+ public JSSessionModel getModel()
+ {
+ return model;
+ }
+
+ private SourceMapMapping lastMapping;
+
+ private Stack<String> nameStack = new Stack<String>();
+
+ private List<SourceMapMapping> sourceMapMappings;
+
+ public List<SourceMapMapping> getSourceMapMappings()
+ {
+ return sourceMapMappings;
+ }
+
+ public JSEmitter(FilterWriter out)
+ {
+ super(out);
+
+ model = new JSSessionModel();
+ sourceMapMappings = new ArrayList<SourceMapMapping>();
+
++ blockOpenEmitter = new BlockOpenEmitter(this);
++ blockCloseEmitter = new BlockCloseEmitter(this);
+ numericLiteralEmitter = new NumericLiteralEmitter(this);
+ parametersEmitter = new ParametersEmitter(this);
+ parameterEmitter = new ParameterEmitter(this);
+ functionCallArgumentsEmitter = new FunctionCallArgumentsEmitter(this);
+ literalContainerEmitter = new LiteralContainerEmitter(this);
+ objectLiteralValuePairEmitter = new ObjectLiteralValuePairEmitter(this);
+ returnEmitter = new ReturnEmitter(this);
+ dynamicAccessEmitter = new DynamicAccessEmitter(this);
+ unaryOperatorEmitter = new UnaryOperatorEmitter(this);
+ ternaryOperatorEmitter = new TernaryOperatorEmitter(this);
+ memberKeywordEmitter = new MemberKeywordEmitter(this);
+ ifEmitter = new IfEmitter(this);
+ whileLoopEmitter = new WhileLoopEmitter(this);
+ doWhileLoopEmitter = new DoWhileLoopEmitter(this);
+ forLoopEmitter = new ForLoopEmitter(this);
+ interationFlowEmitter = new IterationFlowEmitter(this);
+ statementEmitter = new StatementEmitter(this);
+ languageIdentifierEmitter = new LanguageIdentifierEmitter(this);
+ sourceMapDirectiveEmitter = new SourceMapDirectiveEmitter(this);
+ }
+
+ @Override
+ public String formatQualifiedName(String name)
+ {
+ return name;
+ }
+
+ @Override
+ public void emitLocalNamedFunction(IFunctionNode node)
+ {
+ startMapping(node);
+ FunctionNode fnode = (FunctionNode)node;
+ write(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.SPACE);
+ write(fnode.getName());
+ endMapping(node);
+ emitParameters(fnode.getParametersContainerNode());
+ emitFunctionScope(fnode.getScopedNode());
+ }
+
+ @Override
+ public void emitFunctionObject(IFunctionObjectNode node)
+ {
+ startMapping(node);
+ FunctionNode fnode = node.getFunctionNode();
+ write(ASEmitterTokens.FUNCTION);
+ endMapping(node);
+ emitParameters(fnode.getParametersContainerNode());
+ emitFunctionScope(fnode.getScopedNode());
+ }
+
+ public void emitClosureStart()
+ {
+
+ }
+
+ public void emitClosureEnd(IASNode node)
+ {
+
+ }
+
+ public void emitSourceMapDirective(ITypeNode node)
+ {
+ sourceMapDirectiveEmitter.emit(node);
+ }
+
+ public void emitParameters(IContainerNode node)
+ {
+ parametersEmitter.emit(node);
+ }
+
+ @Override
+ public void emitParameter(IParameterNode node)
+ {
+ parameterEmitter.emit(node);
+ }
+
+ @Override
+ public void emitArguments(IContainerNode node)
+ {
+ functionCallArgumentsEmitter.emit(node);
+ }
+
+ @Override
+ public void emitNumericLiteral(INumericLiteralNode node)
+ {
+ numericLiteralEmitter.emit(node);
+ }
+
+ @Override
+ public void emitLiteralContainer(ILiteralContainerNode node)
+ {
+ literalContainerEmitter.emit(node);
+ }
+
+ @Override
+ public void emitObjectLiteralValuePair(IObjectLiteralValuePairNode node)
+ {
+ objectLiteralValuePairEmitter.emit(node);
+ }
+
+ @Override
+ public void emitReturn(IReturnNode node)
+ {
+ returnEmitter.emit(node);
+ }
+
+ @Override
+ public void emitTypedExpression(ITypedExpressionNode node)
+ {
+ write(JSEmitterTokens.ARRAY);
+ }
+
+ @Override
+ public void emitDynamicAccess(IDynamicAccessNode node)
+ {
+ dynamicAccessEmitter.emit(node);
+ }
+
+ @Override
+ public void emitMemberKeyword(IDefinitionNode node)
+ {
+ memberKeywordEmitter.emit(node);
+ }
+
+ @Override
+ public void emitUnaryOperator(IUnaryOperatorNode node)
+ {
+ unaryOperatorEmitter.emit(node);
+ }
+
+ @Override
+ public void emitTernaryOperator(ITernaryOperatorNode node)
+ {
+ ternaryOperatorEmitter.emit(node);
+ }
+
+ @Override
+ public void emitLanguageIdentifier(ILanguageIdentifierNode node)
+ {
+ languageIdentifierEmitter.emit(node);
+ }
+
+ @Override
+ public void emitStatement(IASNode node)
+ {
+ statementEmitter.emit(node);
+ }
+
+ @Override
+ public void emitIf(IIfNode node)
+ {
+ ifEmitter.emit(node);
+ }
+
+ @Override
+ public void emitWhileLoop(IWhileLoopNode node)
+ {
+ whileLoopEmitter.emit(node);
+ }
+
+ @Override
+ public void emitDoLoop(IWhileLoopNode node)
+ {
+ doWhileLoopEmitter.emit(node);
+ }
+
+ @Override
+ public void emitForLoop(IForLoopNode node)
+ {
+ forLoopEmitter.emit(node);
+ }
+
+ @Override
+ public void emitIterationFlow(IIterationFlowNode node)
+ {
+ interationFlowEmitter.emit(node);
+ }
+
++ @Override
++ public void emitBlockOpen(IContainerNode node)
++ {
++ blockOpenEmitter.emit(node);
++ }
++
++ @Override
++ public void emitBlockClose(IContainerNode node)
++ {
++ blockCloseEmitter.emit(node);
++ }
++
+ public void pushSourceMapName(ISourceLocation node)
+ {
+ boolean isValidMappingScope = node instanceof ITypeNode
+ || node instanceof IPackageNode
+ || node instanceof IFunctionNode;
+ if(!isValidMappingScope)
+ {
+ throw new IllegalStateException("A source mapping scope must be a package, type, or function.");
+ }
+
+ IDefinitionNode definitionNode = (IDefinitionNode) node;
+ String nodeName = definitionNode.getQualifiedName();
+ ITypeDefinition typeDef = EmitterUtils.getTypeDefinition(definitionNode);
+ if (typeDef != null)
+ {
+ boolean isConstructor = node instanceof IFunctionNode &&
+ ((IFunctionNode) node).isConstructor();
+ boolean isStatic = definitionNode.hasModifier(ASModifier.STATIC);
+ if (isConstructor)
+ {
+ nodeName = typeDef.getQualifiedName() + ".constructor";
+ }
+ else if (isStatic)
+ {
+ nodeName = typeDef.getQualifiedName() + "." + nodeName;
+ }
+ else
+ {
+ nodeName = typeDef.getQualifiedName() + ".prototype." + nodeName;
+ }
+ }
+ nameStack.push(nodeName);
+ }
+
+ public void popSourceMapName()
+ {
+ nameStack.pop();
+ }
+
+ public void startMapping(ISourceLocation node)
+ {
+ startMapping(node, node.getLine(), node.getColumn());
+ }
-
- public void startMapping(ISourceLocation node, ISourceLocation nodeBeforeMapping)
- {
- startMapping(node, nodeBeforeMapping.getLine(), nodeBeforeMapping.getColumn() + nodeBeforeMapping.getAbsoluteEnd() - nodeBeforeMapping.getAbsoluteStart());
- }
+
+ public void startMapping(ISourceLocation node, int line, int column)
+ {
+ if (lastMapping != null)
+ {
+ FilePosition sourceStartPosition = lastMapping.sourceStartPosition;
+ throw new IllegalStateException("Cannot start new mapping when another mapping is already started. "
+ + "Previous mapping at Line " + sourceStartPosition.getLine()
+ + " and Column " + sourceStartPosition.getColumn()
+ + " in file " + lastMapping.sourcePath);
+ }
+
+ String sourcePath = node.getSourcePath();
+ if (sourcePath == null)
+ {
+ //if the source path is null, this node may have been generated by
+ //the compiler automatically. for example, an untyped variable will
+ //have a node for the * type.
+ if (node instanceof IASNode)
+ {
+ IASNode parentNode = ((IASNode) node).getParent();
+ if (parentNode != null)
+ {
+ //try the parent node
+ startMapping(parentNode, line, column);
+ return;
+ }
+ }
+ }
+
+ String nodeName = null;
+ if (nameStack.size() > 0)
+ {
+ nodeName = nameStack.lastElement();
+ }
+ SourceMapMapping mapping = new SourceMapMapping();
+ mapping.sourcePath = sourcePath;
+ mapping.name = nodeName;
+ mapping.sourceStartPosition = new FilePosition(line, column);
+ mapping.destStartPosition = new FilePosition(getCurrentLine(), getCurrentColumn());
+ lastMapping = mapping;
+ }
+
++ public void startMapping(ISourceLocation node, ISourceLocation afterNode)
++ {
++ startMapping(node, afterNode.getEndLine(), afterNode.getEndColumn());
++ }
++
+ public void endMapping(ISourceLocation node)
+ {
+ if (lastMapping == null)
+ {
+ throw new IllegalStateException("Cannot end mapping when a mapping has not been started");
+ }
+
+ lastMapping.destEndPosition = new FilePosition(getCurrentLine(), getCurrentColumn());
+ sourceMapMappings.add(lastMapping);
+ lastMapping = null;
+ }
+
+ /**
+ * Adjusts the line numbers saved in the source map when a line should be
+ * added during post processing.
+ *
+ * @param lineIndex
+ */
+ protected void addLineToMappings(int lineIndex)
+ {
+ for (SourceMapMapping mapping : sourceMapMappings)
+ {
+ FilePosition destStartPosition = mapping.destStartPosition;
+ int startLine = destStartPosition.getLine();
+ if(startLine > lineIndex)
+ {
+ mapping.destStartPosition = new FilePosition(startLine + 1, destStartPosition.getColumn());
+ FilePosition destEndPosition = mapping.destEndPosition;
+ mapping.destEndPosition = new FilePosition(destEndPosition.getLine() + 1, destEndPosition.getColumn());
+ }
+ }
+ }
+
+ /**
+ * Adjusts the line numbers saved in the source map when a line should be
+ * removed during post processing.
+ *
+ * @param lineIndex
+ */
+ protected void removeLineFromMappings(int lineIndex)
+ {
+ for (SourceMapMapping mapping : sourceMapMappings)
+ {
+ FilePosition destStartPosition = mapping.destStartPosition;
+ int startLine = destStartPosition.getLine();
+ if(startLine > lineIndex)
+ {
+ mapping.destStartPosition = new FilePosition(startLine - 1, destStartPosition.getColumn());
+ FilePosition destEndPosition = mapping.destEndPosition;
+ mapping.destEndPosition = new FilePosition(destEndPosition.getLine() - 1, destEndPosition.getColumn());
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
index be0b9d1,0000000..f947af6
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSubEmitter.java
@@@ -1,126 -1,0 +1,126 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.js;
+
+import org.apache.flex.compiler.codegen.IEmitterTokens;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.visitor.IBlockWalker;
+
+public class JSSubEmitter
+{
+ private IJSEmitter emitter;
+
+ protected IJSEmitter getEmitter()
+ {
+ return emitter;
+ }
+
+ protected IBlockWalker getWalker()
+ {
+ return emitter.getWalker();
+ }
+
+ protected ICompilerProject getProject()
+ {
+ return emitter.getWalker().getProject();
+ }
+
+ protected JSSessionModel getModel()
+ {
+ return emitter.getModel();
+ }
+
+ public JSSubEmitter(IJSEmitter emitter)
+ {
+ this.emitter = emitter;
+ }
+
+ protected void write(IEmitterTokens value)
+ {
+ emitter.write(value);
+ }
+
+ protected void write(String value)
+ {
+ emitter.write(value);
+ }
+
+ protected void writeToken(IEmitterTokens value)
+ {
+ emitter.writeToken(value);
+ }
+
+ protected void writeToken(String value)
+ {
+ emitter.writeToken(value);
+ }
+
+ protected void writeNewline()
+ {
+ emitter.writeNewline();
+ }
+
+ protected void writeNewline(IEmitterTokens value)
+ {
+ emitter.writeNewline(value);
+ }
+
+ protected void writeNewline(String value)
+ {
+ emitter.writeNewline(value);
+ }
+
+ protected void writeNewline(String value, boolean pushIndent)
+ {
+ emitter.writeNewline(value, pushIndent);
+ }
+
+ protected void indentPush()
+ {
+ emitter.indentPush();
+ }
+
+ protected void indentPop()
+ {
+ emitter.indentPop();
+ }
+
+ protected void startMapping(ISourceLocation node)
+ {
+ emitter.startMapping(node);
+ }
+
+ protected void startMapping(ISourceLocation node, int line, int column)
+ {
+ emitter.startMapping(node, line, column);
+ }
+
- protected void startMapping(ISourceLocation node, ISourceLocation nodeBeforeMapping)
++ protected void startMapping(ISourceLocation node, ISourceLocation afterNode)
+ {
- emitter.startMapping(node, nodeBeforeMapping);
++ emitter.startMapping(node, afterNode);
+ }
+
+ protected void endMapping(ISourceLocation node)
+ {
+ emitter.endMapping(node);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
index d1d24fd,0000000..5e0fdce
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralContainerEmitter.java
@@@ -1,96 -1,0 +1,96 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.js.jx;
+
+import org.apache.flex.compiler.codegen.ISubEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.ILiteralContainerNode;
+
+public class LiteralContainerEmitter extends JSSubEmitter implements
+ ISubEmitter<ILiteralContainerNode>
+{
+ public LiteralContainerEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+ @Override
+ public void emit(ILiteralContainerNode node)
+ {
+ final IContainerNode cnode = node.getContentsNode();
+ final IContainerNode.ContainerType type = cnode.getContainerType();
+ String preFix = null;
+ String postFix = null;
+
+ if (type == IContainerNode.ContainerType.BRACES)
+ {
+ preFix = ASEmitterTokens.BLOCK_OPEN.getToken();
+ postFix = ASEmitterTokens.BLOCK_CLOSE.getToken();
+ }
+ else if (type == IContainerNode.ContainerType.BRACKETS)
+ {
+ preFix = ASEmitterTokens.SQUARE_OPEN.getToken();
+ postFix = ASEmitterTokens.SQUARE_CLOSE.getToken();
+ }
+ else if (type == IContainerNode.ContainerType.IMPLICIT)
+ {
+ // nothing to write, move along
+ }
+ else if (type == IContainerNode.ContainerType.PARENTHESIS)
+ {
+ preFix = ASEmitterTokens.PAREN_OPEN.getToken();
+ postFix = ASEmitterTokens.PAREN_CLOSE.getToken();
+ }
+
+ if (preFix != null)
+ {
+ startMapping(node);
+ write(preFix);
+ endMapping(node);
+ }
+
+ final int len = cnode.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IASNode child = cnode.getChild(i);
+ getWalker().walk(child);
+ if (i < len - 1)
+ {
+ //we're mapping the comma to the literal container, but we fill
+ //the space between the current child and the next because we
+ //don't know exactly where the comma appears in ActionScript
+ startMapping(node, child);
+ writeToken(ASEmitterTokens.COMMA);
+ endMapping(node);
+ }
+ }
+
+ if (postFix != null)
+ {
- startMapping(node, node.getLine(), node.getColumn() + node.getAbsoluteEnd() - node.getAbsoluteStart() - 1);
++ startMapping(node, node.getEndLine(), node.getEndColumn() - postFix.length());
+ write(postFix);
+ endMapping(node);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
index d93d701,0000000..ad12b77
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ObjectLiteralValuePairEmitter.java
@@@ -1,53 -1,0 +1,53 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.js.jx;
+
+import org.apache.flex.compiler.codegen.ISubEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IObjectLiteralValuePairNode;
+
+public class ObjectLiteralValuePairEmitter extends JSSubEmitter implements
+ ISubEmitter<IObjectLiteralValuePairNode>
+{
+ public ObjectLiteralValuePairEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+ @Override
+ public void emit(IObjectLiteralValuePairNode node)
+ {
- ISourceLocation sourceLocationNode = (ISourceLocation) node;
++ ISourceLocation location = (ISourceLocation) node;
+
+ IExpressionNode nameNode = node.getNameNode();
+ getWalker().walk(nameNode);
+
- startMapping(sourceLocationNode, nameNode);
++ startMapping(location, nameNode);
+ write(ASEmitterTokens.COLON);
- endMapping(sourceLocationNode);
++ endMapping(location);
+
+ IExpressionNode valueNode = node.getValueNode();
+ getWalker().walk(valueNode);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
index f43b288,0000000..911a280
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
@@@ -1,123 -1,0 +1,131 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.js.jx;
+
+import org.apache.flex.compiler.codegen.ISubEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
+import org.apache.flex.compiler.internal.tree.as.ChainedVariableNode;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IEmbedNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+
+public class VarDeclarationEmitter extends JSSubEmitter implements
+ ISubEmitter<IVariableNode>
+{
+
+ public VarDeclarationEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+ @Override
+ public void emit(IVariableNode node)
+ {
+ // TODO (mschmalle) will remove this cast as more things get abstracted
+ JSFlexJSEmitter fjs = (JSFlexJSEmitter) getEmitter();
+
+ getModel().getVars().add(node);
+
+ if (!(node instanceof ChainedVariableNode) && !node.isConst())
+ {
+ fjs.emitMemberKeyword(node);
+ }
+
+ IExpressionNode variableTypeNode = node.getVariableTypeNode();
- if(variableTypeNode.getLine() >= 0)
++ boolean hasVariableType = variableTypeNode.getLine() >= 0;
++ if(hasVariableType)
+ {
+ startMapping(variableTypeNode,
+ variableTypeNode.getLine(),
+ variableTypeNode.getColumn() - 1); //include the :
+ }
+ else
+ {
+ //the result of getVariableTypeNode() may not have a line and
+ //column. this can happen when the type is omitted in the code, and
+ //the compiler generates a node for type *.
+ //in this case, put it at the end of the name expression.
+ IExpressionNode nameExpressionNode = node.getNameExpressionNode();
+ startMapping(variableTypeNode, nameExpressionNode.getLine(),
+ nameExpressionNode.getColumn() + nameExpressionNode.getAbsoluteEnd() - nameExpressionNode.getAbsoluteStart());
+ }
+ IExpressionNode avnode = node.getAssignedValueNode();
+ if (avnode != null)
+ {
+ IDefinition def = avnode.resolveType(getWalker().getProject());
+
+ String opcode = avnode.getNodeID().getParaphrase();
+ if (opcode != "AnonymousFunction")
+ {
+ fjs.getDocEmitter().emitVarDoc(node, def, getWalker().getProject());
+ }
+ }
+ else
+ {
+ fjs.getDocEmitter().emitVarDoc(node, null, getWalker().getProject());
+ }
+ endMapping(variableTypeNode);
+
+ if (!(node instanceof ChainedVariableNode) && node.isConst())
+ {
+ fjs.emitMemberKeyword(node);
+ }
+
+ fjs.emitDeclarationName(node);
+ if (avnode != null && !(avnode instanceof IEmbedNode))
+ {
- startMapping(node, node.getVariableTypeNode());
++ if (hasVariableType)
++ {
++ startMapping(node, node.getVariableTypeNode());
++ }
++ else
++ {
++ startMapping(node, node.getNameExpressionNode());
++ }
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ endMapping(node);
+ fjs.emitAssignedValue(avnode);
+ }
+
+ if (!(node instanceof ChainedVariableNode))
+ {
+ // check for chained variables
+ int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IASNode child = node.getChild(i);
+ if (child instanceof ChainedVariableNode)
+ {
+ startMapping(node, node.getChild(i - 1));
+ writeToken(ASEmitterTokens.COMMA);
+ endMapping(node);
+ fjs.emitVarDeclaration((IVariableNode) child);
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
index 57ab17b,0000000..90aab08
mode 100644,000000..100644
--- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
+++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapExpressions.java
@@@ -1,716 -1,0 +1,755 @@@
+package org.apache.flex.compiler.internal.codegen.js.sourcemaps;
+
+import org.apache.flex.compiler.driver.IBackend;
+import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend;
+import org.apache.flex.compiler.internal.test.SourceMapTestBase;
+import org.apache.flex.compiler.internal.tree.as.ArrayLiteralNode;
+import org.apache.flex.compiler.internal.tree.as.ObjectLiteralNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
+import org.apache.flex.compiler.tree.as.IFunctionCallNode;
+import org.apache.flex.compiler.tree.as.IIterationFlowNode;
+import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.IReturnNode;
+import org.apache.flex.compiler.tree.as.ITernaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
+
+import org.junit.Test;
+
+public class TestSourceMapExpressions extends SourceMapTestBase
+{
+ //----------------------------------
+ // Primary expression keywords
+ //----------------------------------
+
+ //----------------------------------
+ // Arithmetic
+ //----------------------------------
+
+ @Test
+ public void testVisitBinaryOperatorNode_Plus()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a + b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // +
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_Minus()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a - b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // -
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_Divide()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a / b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // /
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_Modulo()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a % b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // %
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_Multiply()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a * b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // *
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_PostIncrement()
+ {
+ IUnaryOperatorNode node = getUnaryNode("a++");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 3);
++ assertMapping(node, 0, 1, 0, 1, 0, 3); // ++
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_PreIncrement()
+ {
+ IUnaryOperatorNode node = getUnaryNode("++a");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 2);
++ assertMapping(node, 0, 0, 0, 0, 0, 2); // +
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_PostDecrement()
+ {
+ IUnaryOperatorNode node = getUnaryNode("a--");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 3);
++ assertMapping(node, 0, 1, 0, 1, 0, 3); // --
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_PreDecrement()
+ {
+ IUnaryOperatorNode node = getUnaryNode("--a");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 2);
++ assertMapping(node, 0, 0, 0, 0, 0, 2); // --
+ }
+
+ //----------------------------------
+ // Arithmetic compound assignment
+ //----------------------------------
+
+ @Test
+ public void testVisitBinaryOperatorNode_PlusAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a += b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_MinusAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a -= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_DivideAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a /= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_ModuloAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a %= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_MultiplyAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a *= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ //----------------------------------
+ // Assignment
+ //----------------------------------
+
+ @Test
+ public void testVisitBinaryOperatorNode_Assignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a = b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // =
+ }
+
+ //----------------------------------
+ // Bitwise
+ //----------------------------------
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseAnd()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a & b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // &
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseLeftShift()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a << b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // <<
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_BitwiseNot()
+ {
+ IUnaryOperatorNode node = getUnaryNode("~a");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 1);
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // ~
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseOr()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a | b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // |
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseRightShift()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a >> b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // >>
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseUnsignedRightShift()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a >>> b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 6);
++ assertMapping(node, 0, 1, 0, 1, 0, 6); // >>>
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseXOR()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a ^ b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // ^
+ }
+
+ //----------------------------------
+ // Bitwise compound assignment
+ //----------------------------------
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseAndAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a &= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseLeftShiftAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a <<= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 6);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseOrAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a |= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseRightShiftAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a >>= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 6);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseUnsignedRightShiftAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a >>>= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 7);
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_BitwiseXORAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a ^= b");
+ asBlockWalker.visitBinaryOperator(node);
+ assertMapping(node, 0, 1, 0, 1, 0, 5);
+ }
+
+ //----------------------------------
+ // Comparison
+ //----------------------------------
+
+ @Test
+ public void testVisitBinaryOperatorNode_Equal()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a == b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // ==
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_GreaterThan()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a > b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // >
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_GreaterThanEqual()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a >= b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // >=
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_NotEqual()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a != b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // !=
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_LessThan()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a < b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // <
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_LessThanEqual()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a <= b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // <=
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_StrictEqual()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a === b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 6);
++ assertMapping(node, 0, 1, 0, 1, 0, 6); // ===
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_StrictNotEqual()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a !== b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 6);
++ assertMapping(node, 0, 1, 0, 1, 0, 6); // !==
+ }
+
+ //----------------------------------
+ // Logical
+ //----------------------------------
+
+ @Test
+ public void testVisitBinaryOperatorNode_LogicalAnd()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a && b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // &&
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_LogicalAndAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a &&= b");
+ asBlockWalker.visitBinaryOperator(node);
+ //a = a && b
- assertMapping(node, 0, 1, 0, 1, 0, 4);
- assertMapping(node, 0, 1, 0, 5, 0, 9);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // =
++ assertMapping(node, 0, 1, 0, 5, 0, 9); // &&
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_LogicalNot()
+ {
+ IUnaryOperatorNode node = getUnaryNode("!a");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 1);
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // !
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_LogicalOr()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a || b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // ||
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_LogicalOrAssignment()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a ||= b");
+ asBlockWalker.visitBinaryOperator(node);
+ //a = a || b
- assertMapping(node, 0, 1, 0, 1, 0, 4);
- assertMapping(node, 0, 1, 0, 5, 0, 9);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // =
++ assertMapping(node, 0, 1, 0, 5, 0, 9); // ||
+ }
+
+ //----------------------------------
+ // Other
+ //----------------------------------
+
+ @Test
+ public void testVisitDynamicAccessNode_1()
+ {
+ IDynamicAccessNode node = getDynamicAccessNode("a[b]");
+ asBlockWalker.visitDynamicAccess(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // [
++ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
++ assertMapping(node, 0, 3, 0, 3, 0, 4); // ]
+ }
+
+ @Test
+ public void testVisitDynamicAccessNode_2()
+ {
+ IDynamicAccessNode node = getDynamicAccessNode("a[b[c][d]]");
+ asBlockWalker.visitDynamicAccess(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
- assertMapping(node, 0, 5, 0, 5, 0, 6);
- assertMapping(node, 0, 6, 0, 6, 0, 7);
- assertMapping(node, 0, 8, 0, 8, 0, 9);
- assertMapping(node, 0, 9, 0, 9, 0, 10);
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // [
++ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
++ assertMapping(node, 0, 3, 0, 3, 0, 4); // [
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // c
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // ]
++ assertMapping(node, 0, 6, 0, 6, 0, 7); // [
++ assertMapping(node, 0, 7, 0, 7, 0, 8); // d
++ assertMapping(node, 0, 8, 0, 8, 0, 9); // ]
++ assertMapping(node, 0, 9, 0, 9, 0, 10); // ]
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_Comma()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a, b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 3);
++ assertMapping(node, 0, 1, 0, 1, 0, 3); // ,
+ }
+
+ @Test
+ public void testVisitTernaryOperatorNode()
+ {
+ ITernaryOperatorNode node = (ITernaryOperatorNode) getExpressionNode(
+ "a ? b : c", ITernaryOperatorNode.class);
+ asBlockWalker.visitTernaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 4);
- assertMapping(node, 0, 5, 0, 5, 0, 8);
++ assertMapping(node, 0, 1, 0, 1, 0, 4); // ?
++ assertMapping(node, 0, 5, 0, 5, 0, 8); // :
+ }
+
+ @Test
+ public void testVisitUnaryOperator_Delete()
+ {
+ IUnaryOperatorNode node = getUnaryNode("delete a");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
++ assertMapping(node, 0, 0, 0, 0, 0, 7); // delete
+ }
+
+ @Test
+ public void testVisitMemberAccess_1()
+ {
+ IMemberAccessExpressionNode node = (IMemberAccessExpressionNode) getExpressionNode(
+ "a.b", IMemberAccessExpressionNode.class);
+ asBlockWalker.visitMemberAccessExpression(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // .
+ }
+
+ @Test
+ public void testVisitMemberAccess_2()
+ {
+ IMemberAccessExpressionNode node = (IMemberAccessExpressionNode) getExpressionNode(
+ "a.b.c.d", IMemberAccessExpressionNode.class);
+ asBlockWalker.visitMemberAccessExpression(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
- assertMapping(node, 0, 5, 0, 5, 0, 6);
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // .
++ assertMapping(node, 0, 3, 0, 3, 0, 4); // .
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // .
+ }
+
+ @Test
+ public void testVisitBinaryOperator_In()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a in b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 5);
++ assertMapping(node, 0, 1, 0, 1, 0, 5); // in
+ }
+
+ @Test
+ public void testVisitBinaryOperator_Instancof()
+ {
+ IBinaryOperatorNode node = getBinaryNode("a instanceof b");
+ asBlockWalker.visitBinaryOperator(node);
- assertMapping(node, 0, 1, 0, 1, 0, 13);
++ assertMapping(node, 0, 1, 0, 1, 0, 13); // instanceof
+ }
+
+ @Test
+ public void testVisitBinaryOperator_New()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getExpressionNode(
+ "new Object()", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 0, 0, 0, 0, 4);
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // new
+ }
+
+ @Test
+ public void testVisitObjectLiteral_1()
+ {
+ ObjectLiteralNode node = (ObjectLiteralNode) getExpressionNode(
+ "a = {a:1}", ObjectLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
++ //{a: 1}
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // {
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // a
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // :
+ assertMapping(node, 0, 4, 0, 4, 0, 5); // }
+ }
+
+ @Test
+ public void testVisitObjectLiteral_2()
+ {
+ ObjectLiteralNode node = (ObjectLiteralNode) getExpressionNode(
+ "a = {a:1,b:{c:2,d:{e:4}}}", ObjectLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
+ //{a:1, b:{c:2, d:{e:4}}}
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // {
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // a
+ assertMapping(node, 0, 2, 0, 2, 0, 3); // :
+ assertMapping(node, 0, 4, 0, 4, 0, 6); // ,
+ assertMapping(node, 0, 5, 0, 6, 0, 7); // b
+ assertMapping(node, 0, 6, 0, 7, 0, 8); // :
+ assertMapping(node, 0, 7, 0, 8, 0, 9); // {
+ assertMapping(node, 0, 8, 0, 9, 0, 10); // c
+ assertMapping(node, 0, 9, 0, 10, 0, 11); // :
+ assertMapping(node, 0, 11, 0, 12, 0, 14); // ,
+ assertMapping(node, 0, 12, 0, 14, 0, 15); // d
+ assertMapping(node, 0, 13, 0, 15, 0, 16); // :
+ assertMapping(node, 0, 14, 0, 16, 0, 17); // {
+ assertMapping(node, 0, 15, 0, 17, 0, 18); // e
+ assertMapping(node, 0, 16, 0, 18, 0, 19); // :
+ assertMapping(node, 0, 18, 0, 20, 0, 21); // }
+ assertMapping(node, 0, 19, 0, 21, 0, 22); // }
+ assertMapping(node, 0, 20, 0, 22, 0, 23); // }
+
+ }
+
+ @Test
+ public void testVisitObjectLiteral_3()
+ {
+ ObjectLiteralNode node = (ObjectLiteralNode) getExpressionNode(
+ "a = { a: 12, bb: 2 \t}", ObjectLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
+ //{a:12, bb:2}
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // {
+ assertMapping(node, 0, 2, 0, 1, 0, 2); // a
+ assertMapping(node, 0, 3, 0, 2, 0, 3); // :
+ assertMapping(node, 0, 7, 0, 5, 0, 7); // ,
+ assertMapping(node, 0, 10, 0, 7, 0, 9); // bb
+ assertMapping(node, 0, 12, 0, 9, 0, 10); // :
+ assertMapping(node, 0, 19, 0, 11, 0, 12); // }
+ }
+
+ @Test
++ public void testVisitObjectLiteral_4()
++ {
++ ObjectLiteralNode node = (ObjectLiteralNode) getExpressionNode(
++ "a = {a:1,\nb:2}", ObjectLiteralNode.class);
++ asBlockWalker.visitLiteral(node);
++ //{a:1, b:2}
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // {
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // a
++ assertMapping(node, 0, 2, 0, 2, 0, 3); // :
++ assertMapping(node, 0, 3, 0, 3, 0, 4); // 1
++ assertMapping(node, 0, 4, 0, 4, 0, 6); // ,
++ assertMapping(node, 1, 0, 0, 6, 0, 7); // b
++ assertMapping(node, 1, 1, 0, 7, 0, 8); // :
++ assertMapping(node, 1, 2, 0, 8, 0, 9); // 2
++ assertMapping(node, 1, 3, 0, 9, 0, 10); // }
++ }
++
++ @Test
+ public void testVisitArrayLiteral_1()
+ {
+ ArrayLiteralNode node = (ArrayLiteralNode) getExpressionNode(
+ "a = [0,1,2]", ArrayLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
+ //[0, 1, 2]
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // [
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // 0
+ assertMapping(node, 0, 2, 0, 2, 0, 4); // ,
++ assertMapping(node, 0, 3, 0, 4, 0, 5); // 1
+ assertMapping(node, 0, 4, 0, 5, 0, 7); // ,
++ assertMapping(node, 0, 5, 0, 7, 0, 8); // 2
+ assertMapping(node, 0, 6, 0, 8, 0, 9); // ]
+ }
+
+ @Test
+ public void testVisitArrayLiteral_2()
+ {
+ ArrayLiteralNode node = (ArrayLiteralNode) getExpressionNode(
+ "a = [0,[0,1,[0,1]],2,[1,2]]", ArrayLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
+ //[0, [0, 1, [0, 1]], 2, [1, 2]]
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // [
+ assertMapping(node, 0, 2, 0, 2, 0, 4); // ,
+ assertMapping(node, 0, 3, 0, 4, 0, 5); // [
+ assertMapping(node, 0, 5, 0, 6, 0, 8); // ,
+ assertMapping(node, 0, 7, 0, 9, 0, 11); // ,
+ assertMapping(node, 0, 8, 0, 11, 0, 12); // [
+ assertMapping(node, 0, 10, 0, 13, 0, 15); // ,
+ assertMapping(node, 0, 12, 0, 16, 0, 17); // ]
+ assertMapping(node, 0, 13, 0, 17, 0, 18); // ]
+
+ assertMapping(node, 0, 14, 0, 18, 0, 20); // ,
+ assertMapping(node, 0, 16, 0, 21, 0, 23); // ,
+ assertMapping(node, 0, 17, 0, 23, 0, 24); // [
+ assertMapping(node, 0, 19, 0, 25, 0, 27); // ,
+ assertMapping(node, 0, 21, 0, 28, 0, 29); // ]
+ assertMapping(node, 0, 22, 0, 29, 0, 30); // ]
+ }
+
+ @Test
+ public void testVisitArrayLiteral_3()
+ {
+ ArrayLiteralNode node = (ArrayLiteralNode) getExpressionNode(
+ "a = [ 0, 123, 45 \t]", ArrayLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
+ //[0, 123, 45]
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // [
+ assertMapping(node, 0, 3, 0, 2, 0, 4); // ,
+ assertMapping(node, 0, 9, 0, 7, 0, 9); // ,
+ assertMapping(node, 0, 17, 0, 11, 0, 12); // ]
+ }
+
+ @Test
+ public void testVisitArrayLiteral_4()
+ {
+ ArrayLiteralNode node = (ArrayLiteralNode) getExpressionNode(
+ "a = [0,\n123, 45]", ArrayLiteralNode.class);
+ asBlockWalker.visitLiteral(node);
+ //[0, 123, 45]
+ assertMapping(node, 0, 0, 0, 0, 0, 1); // [
+ assertMapping(node, 0, 1, 0, 1, 0, 2); // 0
+ assertMapping(node, 0, 2, 0, 2, 0, 4); // ,
+ assertMapping(node, 1, 0, 0, 4, 0, 7); // 123
+ assertMapping(node, 1, 3, 0, 7, 0, 9); // ,
- assertMapping(node, 1, 5, 0, 9, 0, 11); // 45
- //TODO: figure out how to place the ]
++ assertMapping(node, 1, 5, 0, 9, 0, 11); // 45
++ assertMapping(node, 1, 7, 0, 11, 0, 12); // 45
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_Typeof()
+ {
+ IUnaryOperatorNode node = getUnaryNode("typeof(a)");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
- assertMapping(node, 0, 0, 0, 8, 0, 9);
++ //typeof(a)
++ assertMapping(node, 0, 0, 0, 0, 0, 7); // typeof(
++ assertMapping(node, 0, 0, 0, 8, 0, 9); // )
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_Typeof_NoParens()
+ {
+ // TODO (mschmalle) the notation without parenthesis is also valid in AS/JS
+ IUnaryOperatorNode node = getUnaryNode("typeof a");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
- assertMapping(node, 0, 0, 0, 8, 0, 9);
++ //typeof(a)
++ assertMapping(node, 0, 0, 0, 0, 0, 7); // typeof(
++ assertMapping(node, 0, 0, 0, 8, 0, 9); // )
+ }
+
+ @Test
+ public void testVisitUnaryOperatorNode_Void()
+ {
+ IUnaryOperatorNode node = getUnaryNode("void a");
+ asBlockWalker.visitUnaryOperator(node);
- assertMapping(node, 0, 0, 0, 0, 0, 5);
++ assertMapping(node, 0, 0, 0, 0, 0, 5); // void
+ }
+
+ @Test
+ public void testVisitIterationFlowNode_BreakWithoutLabel()
+ {
+ IIterationFlowNode node = (IIterationFlowNode) getNode("break",
+ IIterationFlowNode.class);
+ asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 5);
++ assertMapping(node, 0, 0, 0, 0, 0, 5); // break
+ }
+
+ @Test
+ public void testVisitIterationFlowNode_BreakWithLabel()
+ {
+ IIterationFlowNode node = (IIterationFlowNode) getNode("break label",
+ IIterationFlowNode.class);
+ asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 6);
++ assertMapping(node, 0, 0, 0, 0, 0, 6); // break
++ assertMapping(node, 0, 6, 0, 6, 0, 11); // label
+ }
+
+ @Test
+ public void testVisitIterationFlowNode_ContinueWithoutLabel()
+ {
+ IIterationFlowNode node = (IIterationFlowNode) getNode("continue",
+ IIterationFlowNode.class);
+ asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 8);
++ assertMapping(node, 0, 0, 0, 0, 0, 8); // continue
+ }
+
+ @Test
+ public void testVisitIterationFlowNode_ContinueWithLabel()
+ {
+ IIterationFlowNode node = (IIterationFlowNode) getNode("continue label",
+ IIterationFlowNode.class);
+ asBlockWalker.visitIterationFlow(node);
- assertMapping(node, 0, 0, 0, 0, 0, 9);
++ assertMapping(node, 0, 0, 0, 0, 0, 9); // continue
++ assertMapping(node, 0, 9, 0, 9, 0, 14); // label
+ }
+
+ @Test
+ public void testVisitReturnWithoutValue()
+ {
+ IReturnNode node = (IReturnNode) getNode("return", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
- assertMapping(node, 0, 0, 0, 0, 0, 6);
++ assertMapping(node, 0, 0, 0, 0, 0, 6); // return
+ }
+
+ @Test
+ public void testVisitReturnWithValue()
+ {
+ IReturnNode node = (IReturnNode) getNode("return 0", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
- assertMapping(node, 0, 0, 0, 0, 0, 7);
++ assertMapping(node, 0, 0, 0, 0, 0, 7); // return
++ assertMapping(node, 0, 7, 0, 7, 0, 8); // 0
+ }
+
+ @Test
+ public void testVisitFunctionCall_1()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("a()", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 2, 0, 2, 0, 3);
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // (
++ assertMapping(node, 0, 2, 0, 2, 0, 3); // )
+ }
+
+ @Test
+ public void testVisitFunctionCall_2()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("a(b)", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 4);
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // (
++ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
++ assertMapping(node, 0, 3, 0, 3, 0, 4); // )
+ }
+
+ @Test
+ public void testVisitFunctionCall_3()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("a(b, c)", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
- assertMapping(node, 0, 1, 0, 1, 0, 2);
- assertMapping(node, 0, 3, 0, 3, 0, 5);
- assertMapping(node, 0, 6, 0, 6, 0, 7);
++ assertMapping(node, 0, 0, 0, 0, 0, 1); // a
++ assertMapping(node, 0, 1, 0, 1, 0, 2); // (
++ assertMapping(node, 0, 2, 0, 2, 0, 3); // b
++ assertMapping(node, 0, 3, 0, 3, 0, 5); // ,
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // c
++ assertMapping(node, 0, 6, 0, 6, 0, 7); // )
+ }
+
+ protected IBackend createBackend()
+ {
+ return new FlexJSBackend();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
index 3c25d07,0000000..265b94c
mode 100644,000000..100644
--- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
+++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java
@@@ -1,171 -1,0 +1,307 @@@
+package org.apache.flex.compiler.internal.codegen.js.sourcemaps;
+
+import org.apache.flex.compiler.driver.IBackend;
+import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend;
+import org.apache.flex.compiler.internal.test.SourceMapTestBase;
+import org.apache.flex.compiler.tree.as.IForLoopNode;
++import org.apache.flex.compiler.tree.as.IIfNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+
+import org.junit.Test;
+
+public class TestSourceMapStatements extends SourceMapTestBase
+{
+ //----------------------------------
+ // var declaration
+ //----------------------------------
+
+ @Test
+ public void testVarDeclaration()
+ {
+ IVariableNode node = (IVariableNode) getNode("var a;",
+ IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ //var /** @type {*} */ a
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // var
+ assertMapping(node, 0, 4, 0, 21, 0, 22); // a
+ assertMapping(node, 0, 5, 0, 4, 0, 21); // (type)
+ }
+
+ @Test
++ public void testVarDeclaration_withAssignedValue()
++ {
++ IVariableNode node = (IVariableNode) getNode("var a = 42;",
++ IVariableNode.class);
++ asBlockWalker.visitVariable(node);
++ //var /** @type {*} */ a = 42
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // var
++ assertMapping(node, 0, 4, 0, 21, 0, 22); // a
++ assertMapping(node, 0, 5, 0, 4, 0, 21); // (type)
++ assertMapping(node, 0, 5, 0, 22, 0, 25); // =
++ assertMapping(node, 0, 8, 0, 25, 0, 27); // 42
++ }
++
++ @Test
+ public void testVarDeclaration_withType()
+ {
+ IVariableNode node = (IVariableNode) getNode("var a:int;",
+ IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ //var /** @type {number} */ a
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // var
+ assertMapping(node, 0, 4, 0, 26, 0, 27); // a
+ assertMapping(node, 0, 5, 0, 4, 0, 26); // :int
+ }
+
+ @Test
+ public void testVarDeclaration_withTypeAssignedValue()
+ {
+ IVariableNode node = (IVariableNode) getNode("var a:int = 42;",
+ IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ //var /** @type {number} */ a = 42
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // var
+ assertMapping(node, 0, 4, 0, 26, 0, 27); // a
+ assertMapping(node, 0, 5, 0, 4, 0, 26); // :int
+ assertMapping(node, 0, 9, 0, 27, 0, 30); // =
+ assertMapping(node, 0, 12, 0, 30, 0, 32); // 42
+ }
+
+ @Test
+ public void testVarDeclaration_withTypeAssignedValueComplex()
+ {
+ IVariableNode node = (IVariableNode) getNode(
+ "class A { public function b():void { var a:Foo = new Foo(42, 'goo');}} class Foo {}", IVariableNode.class, WRAP_LEVEL_PACKAGE);
+ asBlockWalker.visitVariable(node);
+ //var /** @type {Foo} */ a = new Foo(42, 'goo')
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // var
+ assertMapping(node, 0, 4, 0, 23, 0, 24); // a
+ assertMapping(node, 0, 5, 0, 4, 0, 23); // :Foo
+ assertMapping(node, 0, 9, 0, 24, 0, 27); // =
+ assertMapping(node, 0, 12, 0, 27, 0, 31); // new
+ assertMapping(node, 0, 16, 0, 31, 0, 34); // Foo
+ assertMapping(node, 0, 19, 0, 34, 0, 35); // (
+ assertMapping(node, 0, 20, 0, 35, 0, 37); // 42
+ assertMapping(node, 0, 22, 0, 37, 0, 39); // ,
+ assertMapping(node, 0, 24, 0, 39, 0, 44); // 'goo'
+ assertMapping(node, 0, 29, 0, 44, 0, 45); // )
+ }
+
+ @Test
+ public void testVarDeclaration_withList()
+ {
+ IVariableNode node = (IVariableNode) getNode(
+ "var a:int = 4, b:int = 11, c:int = 42;", IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ //var /** @type {number} */ a = 4, /** @type {number} */ b = 11, /** @type {number} */ c = 42
+ assertMapping(node, 0, 0, 0, 0, 0, 4); // var
+ assertMapping(node, 0, 4, 0, 26, 0, 27); // a
+ assertMapping(node, 0, 5, 0, 4, 0, 26); // :int
+ assertMapping(node, 0, 9, 0, 27, 0, 30); // =
+ assertMapping(node, 0, 12, 0, 30, 0, 31); // 4
+ assertMapping(node, 0, 13, 0, 31, 0, 33); // ,
+ assertMapping(node, 0, 15, 0, 55, 0, 56); // b
+ assertMapping(node, 0, 16, 0, 33, 0, 55); // :int
+ assertMapping(node, 0, 20, 0, 56, 0, 59); // =
+ assertMapping(node, 0, 23, 0, 59, 0, 61); // 11
+ assertMapping(node, 0, 25, 0, 61, 0, 63); // ,
+ assertMapping(node, 0, 27, 0, 85, 0, 86); // c
+ assertMapping(node, 0, 28, 0, 63, 0, 85); // :int
+ assertMapping(node, 0, 32, 0, 86, 0, 89); // =
+ assertMapping(node, 0, 35, 0, 89, 0, 91); // 42
+ }
+
+ //----------------------------------
+ // for () { }
+ //----------------------------------
+
+ @Test
+ public void testVisitFor_1a()
+ {
+ IForLoopNode node = (IForLoopNode) getNode(
+ "for (var i:int = 0; i < len; i++) { break; }",
+ IForLoopNode.class);
+ asBlockWalker.visitForLoop(node);
+ //for (var /** @type {number} */ i = 0; i < len; i++) {\n break;\n}
+ assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
+ assertMapping(node, 0, 18, 0, 36, 0, 38); // ;
+ assertMapping(node, 0, 27, 0, 45, 0, 47); // ;
+ assertMapping(node, 0, 32, 0, 50, 0, 52); // )
++ assertMapping(node, 0, 34, 0, 52, 0, 53); // {
++ assertMapping(node, 0, 43, 2, 0, 2, 1); // }
+ }
+
+ @Test
+ public void testVisitFor_1b()
+ {
+ IForLoopNode node = (IForLoopNode) getNode(
+ "for (var i:int = 0; i < len; i++) break;", IForLoopNode.class);
+ asBlockWalker.visitForLoop(node);
+ //for (var /** @type {number} */ i = 0; i < len; i++)\n break;
+ assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
+ assertMapping(node, 0, 18, 0, 36, 0, 38); // ;
+ assertMapping(node, 0, 27, 0, 45, 0, 47); // ;
+ assertMapping(node, 0, 32, 0, 50, 0, 51); // )
+ }
+
+ @Test
+ public void testVisitFor_2()
+ {
+ IForLoopNode node = (IForLoopNode) getNode("for (;;) { break; }",
+ IForLoopNode.class);
+ asBlockWalker.visitForLoop(node);
+ //for (;;) {\n break;\n}
- assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
- assertMapping(node, 0, 5, 0, 5, 0, 6); // ;
- assertMapping(node, 0, 6, 0, 6, 0, 7); // ;
- assertMapping(node, 0, 7, 0, 7, 0, 9); // )
++ assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // ;
++ assertMapping(node, 0, 6, 0, 6, 0, 7); // ;
++ assertMapping(node, 0, 7, 0, 7, 0, 9); // )
++ assertMapping(node, 0, 9, 0, 9, 0, 10); // {
++ assertMapping(node, 0, 18, 2, 0, 2, 1); // }
+ }
+
+ @Test
+ public void testVisitForIn_1()
+ {
+ IForLoopNode node = (IForLoopNode) getNode(
+ "for (var i:int in obj) { break; }", IForLoopNode.class);
+ asBlockWalker.visitForLoop(node);
+ //for (var /** @type {number} */ i in obj) {\n break;\n}
+ assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
+ assertMapping(node, 0, 14, 0, 32, 0, 36); // in
+ assertMapping(node, 0, 21, 0, 39, 0, 41); // )
++ assertMapping(node, 0, 23, 0, 41, 0, 42); // {
++ assertMapping(node, 0, 32, 2, 0, 2, 1); // }
+ }
+
+ @Test
+ public void testVisitForIn_1a()
+ {
+ IForLoopNode node = (IForLoopNode) getNode(
+ "for (var i:int in obj) break; ", IForLoopNode.class);
+ asBlockWalker.visitForLoop(node);
+ //for (var /** @type {number} */ i in obj)\n break;
+ assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
+ assertMapping(node, 0, 14, 0, 32, 0, 36); // in
+ assertMapping(node, 0, 21, 0, 39, 0, 40); // )
+ }
+
++ //----------------------------------
++ // if ()
++ //----------------------------------
++
++ @Test
++ public void testVisitIf_1()
++ {
++ IIfNode node = (IIfNode) getNode("if (a) b++;", IIfNode.class);
++ asBlockWalker.visitIf(node);
++ //if (a)\n b++;
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
++ }
++
++ @Test
++ public void testVisitIf_2()
++ {
++ IIfNode node = (IIfNode) getNode("if (a) b++; else c++;", IIfNode.class);
++ asBlockWalker.visitIf(node);
++ //if (a)\n b++;\nelse\n c++;
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
++ assertMapping(node, 0, 12, 2, 0, 2, 4); // else
++ }
++
++ @Test
++ public void testVisitIf_4()
++ {
++ IIfNode node = (IIfNode) getNode(
++ "if (a) b++; else if (c) d++; else if(e) --f;", IIfNode.class);
++ asBlockWalker.visitIf(node);
++ //if (a)\n b++;\nelse if (c)\n d++;\nelse if (e)\n --f;
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
++ assertMapping(node, 0, 12, 2, 0, 2, 9); // else if (
++ assertMapping(node, 0, 22, 2, 10, 2, 11); // )
++ assertMapping(node, 0, 29, 4, 0, 4, 9); // else if (
++ assertMapping(node, 0, 38, 4, 10, 4, 11); // )
++ }
++
++ //----------------------------------
++ // if () { }
++ //----------------------------------
++
++ @Test
++ public void testVisitIf_1a()
++ {
++ IIfNode node = (IIfNode) getNode("if (a) { b++; }", IIfNode.class);
++ asBlockWalker.visitIf(node);
++ //if (a) {\n b++;\n}
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
++ assertMapping(node, 0, 5, 0, 5, 0, 7); // )
++ assertMapping(node, 0, 7, 0, 7, 0, 8); // {
++ assertMapping(node, 0, 14, 2, 0, 2, 1); // }
++ }
++
++ @Test
++ public void testVisitIf_1b()
++ {
++ IIfNode node = (IIfNode) getNode("if (a) { b++; } else { c++; }",
++ IIfNode.class);
++ asBlockWalker.visitIf(node);
++ //if (a) {\n b++;\n} else {\n c++;\n}
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
++ assertMapping(node, 0, 5, 0, 5, 0, 7); // )
++ assertMapping(node, 0, 7, 0, 7, 0, 8); // {
++ assertMapping(node, 0, 14, 2, 0, 2, 1); // }
++ assertMapping(node, 0, 16, 2, 2, 2, 7); // else
++ assertMapping(node, 0, 21, 2, 7, 2, 8); // {
++ assertMapping(node, 0, 28, 4, 0, 4, 1); // }
++ }
++
++ @Test
++ public void testVisitIf_1c()
++ {
++ IIfNode node = (IIfNode) getNode(
++ "if (a) { b++; } else if (b) { c++; } else { d++; }",
++ IIfNode.class);
++ asBlockWalker.visitIf(node);
++ //if (a) {\n b++;\n} else if (b) {\n c++;\n} else {\n d++;\n}
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
++ assertMapping(node, 0, 5, 0, 5, 0, 7); // )
++ assertMapping(node, 0, 7, 0, 7, 0, 8); // {
++ assertMapping(node, 0, 14, 2, 0, 2, 1); // }
++ assertMapping(node, 0, 16, 2, 2, 2, 11); // else if(
++ assertMapping(node, 0, 26, 2, 12, 2, 14); // )
++ assertMapping(node, 0, 28, 2, 14, 2, 15); // {
++ assertMapping(node, 0, 35, 4, 0, 4, 1); // }
++ assertMapping(node, 0, 37, 4, 2, 4, 7); // else
++ assertMapping(node, 0, 42, 4, 7, 4, 8); // {
++ assertMapping(node, 0, 49, 6, 0, 6, 1); // {
++ }
++
++ @Test
++ public void testVisitIf_3()
++ {
++ IIfNode node = (IIfNode) getNode(
++ "if (a) b++; else if (c) d++; else --e;", IIfNode.class);
++ asBlockWalker.visitIf(node);
++ //if (a)\n b++;\nelse if (c)\n d++;\nelse\n --e;
++ assertMapping(node, 0, 0, 0, 0, 0, 4); // if (
++ assertMapping(node, 0, 4, 0, 4, 0, 5); // a
++ assertMapping(node, 0, 5, 0, 5, 0, 6); // )
++ assertMapping(node, 0, 12, 2, 0, 2, 9); // else if (
++ assertMapping(node, 0, 21, 2, 9, 2, 10); // c
++ assertMapping(node, 0, 22, 2, 10, 2, 11); // )
++ assertMapping(node, 0, 29, 4, 0, 4, 4); // else
++ }
++
+ protected IBackend createBackend()
+ {
+ return new FlexJSBackend();
+ }
+}
[07/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - compiler: added getEndLine() and
getEndColumn() to ISourceLocation
Posted by cd...@apache.org.
compiler: added getEndLine() and getEndColumn() to ISourceLocation
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/af3e883d
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/af3e883d
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/af3e883d
Branch: refs/heads/feature/maven-migration-test
Commit: af3e883d75a1e270d2174e35007f48698822085c
Parents: b2bfa2c
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 22:44:59 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 22:44:59 2016 -0700
----------------------------------------------------------------------
.../flex/compiler/common/ISourceLocation.java | 10 ++++
.../flex/compiler/common/SourceLocation.java | 54 ++++++++++++++++++++
.../internal/definitions/metadata/MetaTag.java | 12 +++++
.../compiler/internal/parsing/TokenBase.java | 44 ++++++++++++++++
.../compiler/internal/tree/as/NodeBase.java | 17 ++++--
.../internal/tree/as/OperatorNodeBase.java | 2 +
.../flex/compiler/problems/CompilerProblem.java | 12 +++++
7 files changed, 148 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/af3e883d/compiler/src/org/apache/flex/compiler/common/ISourceLocation.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/common/ISourceLocation.java b/compiler/src/org/apache/flex/compiler/common/ISourceLocation.java
index 738bdf3..25f6b6d 100644
--- a/compiler/src/org/apache/flex/compiler/common/ISourceLocation.java
+++ b/compiler/src/org/apache/flex/compiler/common/ISourceLocation.java
@@ -64,6 +64,16 @@ public interface ISourceLocation
int getColumn();
/**
+ * Gets the local line number at the end. It is zero-based.
+ */
+ int getEndLine();
+
+ /**
+ * Gets the local column number at the end. It is zero-based.
+ */
+ int getEndColumn();
+
+ /**
* Gets the absolute starting offset. It is zero-based.
*/
int getAbsoluteStart();
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/af3e883d/compiler/src/org/apache/flex/compiler/common/SourceLocation.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/common/SourceLocation.java b/compiler/src/org/apache/flex/compiler/common/SourceLocation.java
index 88998b7..0d0e1b0 100644
--- a/compiler/src/org/apache/flex/compiler/common/SourceLocation.java
+++ b/compiler/src/org/apache/flex/compiler/common/SourceLocation.java
@@ -37,6 +37,8 @@ public class SourceLocation implements ISourceLocation
this.end = end;
this.line = line;
this.column = column;
+ this.endLine = UNKNOWN;
+ this.endColumn = UNKNOWN;
}
/**
@@ -93,6 +95,16 @@ public class SourceLocation implements ISourceLocation
* Corresponds to start, not end.
*/
private int column;
+
+ /**
+ * Zero-based line number that corresponds to end.
+ */
+ private int endLine;
+
+ /**
+ * Zero-based column number that corresponds to end.
+ */
+ private int endColumn;
/**
* Copies source location information from another instance
@@ -106,6 +118,8 @@ public class SourceLocation implements ISourceLocation
this.end = src.getEnd();
this.line = src.getLine();
this.column = src.getColumn();
+ this.endLine = src.getEndLine();
+ this.endColumn = src.getEndColumn();
this.sourcePath = src.getSourcePath();
}
@@ -212,6 +226,44 @@ public class SourceLocation implements ISourceLocation
}
/**
+ * Get the line number where this node ends.
+ * Line numbers start at 0, not 1.
+ * @return The line number
+ */
+ public int getEndLine()
+ {
+ return endLine;
+ }
+
+ /**
+ * Set the line number where this node ends.
+ * Column numbers start at 0, not 1.
+ * @param line The line number
+ */
+ public void setEndLine(int line)
+ {
+ this.endLine = line;
+ }
+
+ /**
+ * Get the column number where this node ends.
+ * @return The column number
+ */
+ public int getEndColumn()
+ {
+ return endColumn;
+ }
+
+ /**
+ * Set the column number where this node ends.
+ * @param column The column number
+ */
+ public void setEndColumn(int column)
+ {
+ this.endColumn = column;
+ }
+
+ /**
* Get the source path for this node.
* @return The source path for this node
*/
@@ -346,6 +398,8 @@ public class SourceLocation implements ISourceLocation
setEnd(end.getEnd());
setLine(start.getLine());
setColumn(start.getColumn());
+ setEndLine(end.getEndLine());
+ setEndColumn(end.getEndColumn());
}
/**
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/af3e883d/compiler/src/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java b/compiler/src/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
index 92b9350..5b0b18e 100644
--- a/compiler/src/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
+++ b/compiler/src/org/apache/flex/compiler/internal/definitions/metadata/MetaTag.java
@@ -230,6 +230,18 @@ public class MetaTag implements IMetaTag
}
@Override
+ public int getEndLine()
+ {
+ return line;
+ }
+
+ @Override
+ public int getEndColumn()
+ {
+ return column;
+ }
+
+ @Override
public int getAbsoluteStart()
{
return absoluteStart;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/af3e883d/compiler/src/org/apache/flex/compiler/internal/parsing/TokenBase.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/parsing/TokenBase.java b/compiler/src/org/apache/flex/compiler/internal/parsing/TokenBase.java
index 68a76eb..ff726da 100644
--- a/compiler/src/org/apache/flex/compiler/internal/parsing/TokenBase.java
+++ b/compiler/src/org/apache/flex/compiler/internal/parsing/TokenBase.java
@@ -50,6 +50,8 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
this.line = line;
this.column = column;
this.text = text;
+ this.endLine = line;
+ this.endColumn = column + end - start;
if (Counter.COUNT_TOKENS)
countTokens();
@@ -67,6 +69,8 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
end = o.end;
line = o.line;
column = o.column;
+ endLine = o.endLine;
+ endColumn = o.endColumn;
text = o.text;
localStart = o.localStart;
@@ -103,6 +107,16 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
private int column;
/**
+ * End line of this token
+ */
+ private int endLine;
+
+ /**
+ * End column of this token
+ */
+ private int endColumn;
+
+ /**
* Flag to determine if this token is locked
*/
private boolean locked;
@@ -143,6 +157,8 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
this.end = end;
this.line = line;
this.column = column;
+ this.endLine = line;
+ this.endColumn = column + end - start;
this.text = text;
}
@@ -222,6 +238,8 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
this.end = end;
this.line = line;
this.column = column;
+ this.endLine = line;
+ this.endColumn = column + end - start;
}
@Override
@@ -275,6 +293,28 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
this.column = column;
}
+ @Override
+ public int getEndLine()
+ {
+ return endLine;
+ }
+
+ public void setEndLine(int line)
+ {
+ endLine = line;
+ }
+
+ @Override
+ public int getEndColumn()
+ {
+ return endColumn;
+ }
+
+ public void setEndColumn(int column)
+ {
+ endColumn = column;
+ }
+
/**
* Determine whether or not this token is bogus (i.e. the start and end
* offsets are the same, which implies that it was inserted from an included
@@ -439,6 +479,8 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
end += offsetAdjustment;
line += lineAdjustment;
column += columnAdjustment;
+ endLine += lineAdjustment;
+ endColumn += columnAdjustment;
}
/**
@@ -485,6 +527,8 @@ public abstract class TokenBase extends Token implements ICMToken, ISourceLocati
assert getEnd() != UNKNOWN : "Token has unknown end: " + toString();
assert getLine() != UNKNOWN : "Token has an unknown line: " + toString();
assert getColumn() != UNKNOWN : "Token has an unknown column: " + toString();
+ assert getEndLine() != UNKNOWN : "Token has an unknown end line: " + toString();
+ assert getEndColumn() != UNKNOWN : "Token has an unknown end column: " + toString();
}
return true;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/af3e883d/compiler/src/org/apache/flex/compiler/internal/tree/as/NodeBase.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/tree/as/NodeBase.java b/compiler/src/org/apache/flex/compiler/internal/tree/as/NodeBase.java
index be0510d..8dd4fb6 100644
--- a/compiler/src/org/apache/flex/compiler/internal/tree/as/NodeBase.java
+++ b/compiler/src/org/apache/flex/compiler/internal/tree/as/NodeBase.java
@@ -337,7 +337,6 @@ public abstract class NodeBase extends SourceLocation implements IASNode
if (token instanceof ISourceLocation)
{
startAfter((ISourceLocation) token);
- setColumn(getColumn() + token.getText().length());
}
}
@@ -354,8 +353,8 @@ public abstract class NodeBase extends SourceLocation implements IASNode
{
setSourcePath(location.getSourcePath());
setStart(end);
- setLine(location.getLine());
- setColumn(location.getColumn());
+ setLine(location.getEndLine());
+ setColumn(location.getEndColumn());
}
}
@@ -411,7 +410,11 @@ public abstract class NodeBase extends SourceLocation implements IASNode
{
final int end = location.getEnd();
if (end != UNKNOWN)
+ {
setEnd(end);
+ setEndLine(location.getEndLine());
+ setEndColumn(location.getEndColumn());
+ }
}
/**
@@ -436,7 +439,11 @@ public abstract class NodeBase extends SourceLocation implements IASNode
{
final int start = location.getStart();
if (start != UNKNOWN)
+ {
setEnd(start);
+ setEndLine(location.getLine());
+ setEndColumn(location.getColumn());
+ }
}
/**
@@ -620,7 +627,11 @@ public abstract class NodeBase extends SourceLocation implements IASNode
if (childEnd != -1)
{
if (end < childEnd)
+ {
setEnd(childEnd);
+ setEndLine(child.getEndLine());
+ setEndColumn(child.getEndColumn());
+ }
break;
}
}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/af3e883d/compiler/src/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java b/compiler/src/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
index 5de6521..51eb0fc 100644
--- a/compiler/src/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
+++ b/compiler/src/org/apache/flex/compiler/internal/tree/as/OperatorNodeBase.java
@@ -41,6 +41,8 @@ public abstract class OperatorNodeBase extends ExpressionNodeBase implements IOp
operatorStart = operator.getStart();
setLine(operator.getLine());
setColumn(operator.getColumn());
+ setEndLine(operator.getEndLine());
+ setEndColumn(operator.getEndColumn());
setSourcePath(operator.getSourcePath());
}
}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/af3e883d/compiler/src/org/apache/flex/compiler/problems/CompilerProblem.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/problems/CompilerProblem.java b/compiler/src/org/apache/flex/compiler/problems/CompilerProblem.java
index ee9c9a1..d2e9366 100644
--- a/compiler/src/org/apache/flex/compiler/problems/CompilerProblem.java
+++ b/compiler/src/org/apache/flex/compiler/problems/CompilerProblem.java
@@ -189,6 +189,18 @@ public abstract class CompilerProblem implements ICompilerProblem
}
@Override
+ public int getEndLine()
+ {
+ return line;
+ }
+
+ @Override
+ public int getEndColumn()
+ {
+ return column;
+ }
+
+ @Override
public int getAbsoluteStart()
{
return start;
[14/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - Merge branches 'develop' and
'feature/maven-migration-test' of
https://git-wip-us.apache.org/repos/asf/flex-falcon into
feature/maven-migration-test
Posted by cd...@apache.org.
Merge branches 'develop' and 'feature/maven-migration-test' of https://git-wip-us.apache.org/repos/asf/flex-falcon into feature/maven-migration-test
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/beaf5b63
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/beaf5b63
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/beaf5b63
Branch: refs/heads/feature/maven-migration-test
Commit: beaf5b63a28777f160c801babaef7ce44cf87336
Parents: 316710d e9fd628
Author: Christofer Dutz <ch...@codecentric.de>
Authored: Mon Apr 18 15:31:26 2016 +0200
Committer: Christofer Dutz <ch...@codecentric.de>
Committed: Mon Apr 18 15:31:26 2016 +0200
----------------------------------------------------------------------
.../flex/compiler/codegen/as/IASEmitter.java | 6 +-
.../flex/compiler/codegen/js/IJSEmitter.java | 2 +-
.../codegen/as/ASAfterNodeStrategy.java | 4 +-
.../codegen/as/ASBeforeNodeStrategy.java | 4 +-
.../compiler/internal/codegen/as/ASEmitter.java | 12 ++
.../compiler/internal/codegen/js/JSEmitter.java | 28 ++-
.../internal/codegen/js/JSSubEmitter.java | 4 +-
.../codegen/js/jx/LiteralContainerEmitter.java | 2 +-
.../js/jx/ObjectLiteralValuePairEmitter.java | 6 +-
.../codegen/js/jx/VarDeclarationEmitter.java | 12 +-
.../js/sourcemaps/TestSourceMapExpressions.java | 181 +++++++++++--------
.../js/sourcemaps/TestSourceMapStatements.java | 144 ++++++++++++++-
.../codegen/js/jx/BlockCloseEmitter.java | 43 +++++
.../codegen/js/jx/BlockOpenEmitter.java | 43 +++++
.../compiler/internal/parsing/as/ASParser.g | 4 +-
.../flex/compiler/common/ISourceLocation.java | 10 +
.../flex/compiler/common/SourceLocation.java | 54 ++++++
.../internal/definitions/metadata/MetaTag.java | 12 ++
.../compiler/internal/parsing/TokenBase.java | 44 +++++
.../compiler/internal/tree/as/NodeBase.java | 17 +-
.../internal/tree/as/OperatorNodeBase.java | 2 +
.../flex/compiler/problems/CompilerProblem.java | 12 ++
22 files changed, 547 insertions(+), 99 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/codegen/as/IASEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/codegen/as/IASEmitter.java
index bd0d1eb,0000000..2fe9eea
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/codegen/as/IASEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/codegen/as/IASEmitter.java
@@@ -1,369 -1,0 +1,373 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.codegen.as;
+
+import java.io.Writer;
+
+import org.apache.flex.compiler.codegen.IDocEmitter;
+import org.apache.flex.compiler.codegen.IEmitter;
+import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.internal.tree.as.LabeledStatementNode;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IBlockNode;
+import org.apache.flex.compiler.tree.as.ICatchNode;
+import org.apache.flex.compiler.tree.as.IClassNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
+import org.apache.flex.compiler.tree.as.IForLoopNode;
+import org.apache.flex.compiler.tree.as.IFunctionCallNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IFunctionObjectNode;
+import org.apache.flex.compiler.tree.as.IGetterNode;
+import org.apache.flex.compiler.tree.as.IIdentifierNode;
+import org.apache.flex.compiler.tree.as.IIfNode;
+import org.apache.flex.compiler.tree.as.IImportNode;
+import org.apache.flex.compiler.tree.as.IInterfaceNode;
+import org.apache.flex.compiler.tree.as.IIterationFlowNode;
+import org.apache.flex.compiler.tree.as.IKeywordNode;
+import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.flex.compiler.tree.as.ILiteralContainerNode;
+import org.apache.flex.compiler.tree.as.ILiteralNode;
+import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.INamespaceAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.INamespaceNode;
+import org.apache.flex.compiler.tree.as.INumericLiteralNode;
+import org.apache.flex.compiler.tree.as.IObjectLiteralValuePairNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.IReturnNode;
+import org.apache.flex.compiler.tree.as.ISetterNode;
+import org.apache.flex.compiler.tree.as.ISwitchNode;
+import org.apache.flex.compiler.tree.as.ITernaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IThrowNode;
+import org.apache.flex.compiler.tree.as.ITryNode;
+import org.apache.flex.compiler.tree.as.ITypedExpressionNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IUseNamespaceNode;
+import org.apache.flex.compiler.tree.as.IVariableExpressionNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.apache.flex.compiler.tree.as.IWhileLoopNode;
+import org.apache.flex.compiler.tree.as.IWithNode;
+import org.apache.flex.compiler.tree.metadata.IMetaTagNode;
+import org.apache.flex.compiler.visitor.IASNodeStrategy;
+import org.apache.flex.compiler.visitor.IBlockWalker;
+
+/**
+ * The {@link IASEmitter} interface allows abstraction between the
+ * {@link IASNodeStrategy} and the current output buffer {@link Writer}.
+ *
+ * @author Michael Schmalle
+ */
+public interface IASEmitter extends IEmitter
+{
+ IBlockWalker getWalker();
+
+ void setWalker(IBlockWalker asBlockWalker);
+
+ IDocEmitter getDocEmitter();
+
+ void setDocEmitter(IDocEmitter value);
+
+ String postProcess(String output);
-
++
+ void emitImport(IImportNode node);
+
+ void emitPackageHeader(IPackageDefinition definition);
+
+ void emitPackageHeaderContents(IPackageDefinition definition);
+
+ void emitPackageContents(IPackageDefinition definition);
+
+ void emitPackageFooter(IPackageDefinition definition);
+
+ /**
+ * Emit a Class.
+ *
+ * @param node The {@link IClassNode} class.
+ */
+ void emitClass(IClassNode node);
+
+ /**
+ * Emit an Interface.
+ *
+ * @param node The {@link IInterfaceNode} class.
+ */
+ void emitInterface(IInterfaceNode node);
+
+ /**
+ * Emit a documentation comment for a Class field or constant
+ * {@link IVariableNode}.
+ *
+ * @param node The {@link IVariableNode} class field member.
+ */
+ void emitFieldDocumentation(IVariableNode node);
+
+ /**
+ * Emit a full Class field member.
+ *
+ * @param node The {@link IVariableNode} class field member.
+ */
+ void emitField(IVariableNode node);
+
+ /**
+ * Emit a documentation comment for a Class method {@link IFunctionNode}.
+ *
+ * @param node The {@link IFunctionNode} class method member.
+ */
+ void emitMethodDocumentation(IFunctionNode node);
+
+ /**
+ * Emit a full Class or Interface method member.
+ *
+ * @param node The {@link IFunctionNode} class method member.
+ */
+ void emitMethod(IFunctionNode node);
+
+ /**
+ * Emit a documentation comment for a Class method {@link IGetterNode}.
+ *
+ * @param node The {@link IGetterNode} class accessor member.
+ */
+ void emitGetAccessorDocumentation(IGetterNode node);
+
+ /**
+ * Emit a full Class getter member.
+ *
+ * @param node The {@link IVariableNode} class getter member.
+ */
+ void emitGetAccessor(IGetterNode node);
+
+ /**
+ * Emit a documentation comment for a Class accessor {@link IGetterNode}.
+ *
+ * @param node The {@link ISetterNode} class accessor member.
+ */
+ void emitSetAccessorDocumentation(ISetterNode node);
+
+ /**
+ * Emit a full Class setter member.
+ *
+ * @param node The {@link ISetterNode} class setter member.
+ */
+ void emitSetAccessor(ISetterNode node);
+
+ void emitParameter(IParameterNode node);
+
+ /**
+ * Emit a namespace member.
+ *
+ * @param node The {@link INamespaceNode} class member.
+ */
+ void emitNamespace(INamespaceNode node);
+
+ //--------------------------------------------------------------------------
+ // Statements
+ //--------------------------------------------------------------------------
+
+ /**
+ * Emit a statement found within an {@link IBlockNode}.
+ *
+ * @param node The {@link IASNode} statement.
+ */
+ void emitStatement(IASNode node);
+
+ /**
+ * Emit a <code>if(){}else if(){}else{}</code> statement.
+ *
+ * @param node The {@link IIfNode} node.
+ */
+ void emitIf(IIfNode node);
+
+ /**
+ * Emit a <code>for each</code> statement.
+ *
+ * @param node The {@link IForLoopNode} node.
+ */
+ void emitForEachLoop(IForLoopNode node);
+
+ /**
+ * Emit a <code>for</code> statement.
+ *
+ * @param node The {@link IForLoopNode} node.
+ */
+ void emitForLoop(IForLoopNode node);
+
+ /**
+ * Emit a <code>switch(){}</code> statement.
+ *
+ * @param node The {@link ISwitchNode} node.
+ */
+ void emitSwitch(ISwitchNode node);
+
+ /**
+ * Emit a <code>while(){}</code> statement.
+ *
+ * @param node The {@link IWhileLoopNode} node.
+ */
+ void emitWhileLoop(IWhileLoopNode node);
+
+ /**
+ * Emit a <code>do{}while()</code> statement.
+ *
+ * @param node The {@link IWhileLoopNode} node.
+ */
+ void emitDoLoop(IWhileLoopNode node);
+
+ /**
+ * Emit a <code>with(){}</code> statement.
+ *
+ * @param node The {@link IWithNode} node.
+ */
+ void emitWith(IWithNode node);
+
+ /**
+ * Emit a <code>throw</code> statement.
+ *
+ * @param node The {@link IThrowNode} node.
+ */
+ void emitThrow(IThrowNode node);
+
+ /**
+ * Emit a <code>try{}</code> statement.
+ *
+ * @param node The {@link ITryNode} node.
+ */
+ void emitTry(ITryNode node);
+
+ /**
+ * Emit a <code>catch(){}</code> statement.
+ *
+ * @param node The {@link ICatchNode} node.
+ */
+ void emitCatch(ICatchNode node);
+
+ /**
+ * Emit a <code>foo:{}</code> statement.
+ *
+ * @param node The {@link LabeledStatementNode} node.
+ */
+ void emitLabelStatement(LabeledStatementNode node);
+
+ void emitReturn(IReturnNode node);
+
+ //--------------------------------------------------------------------------
+ // Expressions
+ //--------------------------------------------------------------------------
+
+ /**
+ * Emit a variable declaration found in expression statements within scoped
+ * blocks.
+ *
+ * @param node The {@link IVariableNode} or chain of variable nodes.
+ */
+ void emitVarDeclaration(IVariableNode node);
+
+ /**
+ * Emit an anonymous {@link IFunctionObjectNode}.
+ *
+ * @param node The anonymous {@link IFunctionObjectNode}.
+ */
+ void emitFunctionObject(IFunctionObjectNode node);
+
+ /**
+ * Emit an local named function {@link IFunctionNode}.
+ *
+ * @param node The local named function {@link IFunctionNode}.
+ */
+ void emitLocalNamedFunction(IFunctionNode node);
+
+ /**
+ * Emit a header at the start of a function block.
+ *
+ * @param node The {@link IFunctionNode} node.
+ */
+ void emitFunctionBlockHeader(IFunctionNode node);
+
+ /**
+ * Emit a function call like <code>new Foo()</code> or <code>foo(42)</code>.
+ *
+ * @param node The {@link IFunctionCallNode} node.
+ */
+ void emitFunctionCall(IFunctionCallNode node);
+
+ void emitArguments(IContainerNode node);
+
+ void emitIterationFlow(IIterationFlowNode node);
+
+ void emitNamespaceAccessExpression(INamespaceAccessExpressionNode node);
+
+ void emitMemberAccessExpression(IMemberAccessExpressionNode node);
+
+ void emitVariableExpression(IVariableExpressionNode node);
+
+ void emitDynamicAccess(IDynamicAccessNode node);
+
+ void emitTypedExpression(ITypedExpressionNode node);
+
+ void emitObjectLiteralValuePair(IObjectLiteralValuePairNode node);
+
+ void emitIdentifier(IIdentifierNode node);
+
+ void emitLiteral(ILiteralNode node);
+
+ void emitLiteralContainer(ILiteralContainerNode node);
+
+ void emitNumericLiteral(INumericLiteralNode node);
+
+ //--------------------------------------------------------------------------
+ // Operators
+ //--------------------------------------------------------------------------
+
+ void emitUnaryOperator(IUnaryOperatorNode node);
+
+ void emitAsOperator(IBinaryOperatorNode node);
+
+ void emitIsOperator(IBinaryOperatorNode node);
+
+ /**
+ * Emit an operator statement.
+ *
+ * @param node The {@link IBinaryOperatorNode} or chain of variable nodes.
+ */
+ void emitBinaryOperator(IBinaryOperatorNode node);
+
+ void emitTernaryOperator(ITernaryOperatorNode node);
+
+ //--------------------------------------------------------------------------
+ // Node
+ //--------------------------------------------------------------------------
+
+ void emitKeyword(IKeywordNode node);
+
+ void emitLanguageIdentifier(ILanguageIdentifierNode node);
+
+ void emitMetaTag(IMetaTagNode node);
+
+ void emitContainer(IContainerNode node);
+
+ void emitE4XFilter(IMemberAccessExpressionNode node);
+
+ void emitUseNamespace(IUseNamespaceNode node);
+
++ void emitBlockOpen(IContainerNode node);
++
++ void emitBlockClose(IContainerNode node);
++
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/codegen/js/IJSEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/codegen/js/IJSEmitter.java
index 218b5be,0000000..287b8c8
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/codegen/js/IJSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/codegen/js/IJSEmitter.java
@@@ -1,85 -1,0 +1,85 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.codegen.js;
+
+import java.io.Writer;
+import java.util.List;
+
+import com.google.debugging.sourcemap.FilePosition;
+import org.apache.flex.compiler.codegen.as.IASEmitter;
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.internal.codegen.js.JSSessionModel;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.ITypeNode;
+import org.apache.flex.compiler.visitor.IASNodeStrategy;
+
+/**
+ * The {@link IJSEmitter} interface allows abstraction between the
+ * {@link IASNodeStrategy} and the current output buffer {@link Writer}.
+ *
+ * @author Michael Schmalle
+ */
+public interface IJSEmitter extends IASEmitter
+{
+ JSSessionModel getModel();
+ List<SourceMapMapping> getSourceMapMappings();
+
+ String formatQualifiedName(String name);
+
+ /**
+ * Adds a node to the source map.
+ */
+ void startMapping(ISourceLocation node);
+
+ /**
+ * Adds a node to the source map using custom line and column values,
+ * instead of the node's own line and column. Useful for starting a mapping
+ * in the middle of the node.
+ */
+ void startMapping(ISourceLocation node, int line, int column);
+
+ /**
+ * Adds a node to the source map after a particular node instead using the
+ * node's own line and column.
+ */
- void startMapping(ISourceLocation node, ISourceLocation nodeBeforeMapping);
++ void startMapping(ISourceLocation node, ISourceLocation afterNode);
+
+ /**
+ * Commits a mapping to the source map.
+ */
+ void endMapping(ISourceLocation node);
+
+ void pushSourceMapName(ISourceLocation node);
+ void popSourceMapName();
+
+ void emitSourceMapDirective(ITypeNode node);
+
+ void emitClosureStart();
+ void emitClosureEnd(IASNode node);
+
+ class SourceMapMapping
+ {
+ public String sourcePath;
+ public String name;
+ public FilePosition sourceStartPosition;
+ public FilePosition destStartPosition;
+ public FilePosition destEndPosition;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
index 1ac85f7,0000000..b274b57
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
@@@ -1,77 -1,0 +1,77 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.as;
+
+import org.apache.flex.compiler.codegen.IEmitter;
+import org.apache.flex.compiler.codegen.as.IASEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IContainerNode.ContainerType;
+import org.apache.flex.compiler.visitor.IASNodeStrategy;
+
+/**
+ * A concrete implementation of the {@link IASNodeStrategy} that allows
+ * {@link IASNode} processing after the current node handler.
+ * <p>
+ * The class has access to the current {@link IJSEmitter} instance being used to
+ * output source code to the current output buffer.
+ *
+ * @author Michael Schmalle
+ */
+public class ASAfterNodeStrategy implements IASNodeStrategy
+{
+ private final IASEmitter emitter;
+
+ public ASAfterNodeStrategy(IASEmitter emitter)
+ {
+ this.emitter = emitter;
+ }
+
+ @Override
+ public void handle(IASNode node)
+ {
+ if (node.getNodeID() == ASTNodeID.BlockID)
+ {
+ IContainerNode container = (IContainerNode) node;
+ ContainerType type = container.getContainerType();
+ if (type != ContainerType.IMPLICIT
+ && type != ContainerType.SYNTHESIZED)
+ {
+ if (node.getChildCount() != 0)
+ {
+ emitter.indentPop();
- ((IEmitter) emitter).writeNewline();
++ emitter.writeNewline();
+ }
+
- ((IEmitter) emitter).write(ASEmitterTokens.BLOCK_CLOSE);
++ emitter.emitBlockClose(container);
+ }
+ else if (type == ContainerType.IMPLICIT
+ || type == ContainerType.SYNTHESIZED)
+ {
+ if (node.getChildCount() != 0)
+ {
+ emitter.indentPop();
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
index d481573,0000000..d960057
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
@@@ -1,74 -1,0 +1,74 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.as;
+
+import org.apache.flex.compiler.codegen.IEmitter;
+import org.apache.flex.compiler.codegen.as.IASEmitter;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IContainerNode.ContainerType;
+import org.apache.flex.compiler.visitor.IASNodeStrategy;
+
+/**
+ * A concrete implementation of the {@link IASNodeStrategy} that allows
+ * {@link IASNode} processing before the current node handler.
+ *
+ * @author Michael Schmalle
+ */
+public class ASBeforeNodeStrategy implements IASNodeStrategy
+{
+ private final IASEmitter emitter;
+
+ public ASBeforeNodeStrategy(IASEmitter emitter)
+ {
+ this.emitter = emitter;
+ }
+
+ @Override
+ public void handle(IASNode node)
+ {
+ if (node.getNodeID() == ASTNodeID.BlockID)
+ {
+ IASNode parent = node.getParent();
+ IContainerNode container = (IContainerNode) node;
+ ContainerType type = container.getContainerType();
+
+ if (parent.getNodeID() != ASTNodeID.LabledStatementID)
+ {
+ if (node.getChildCount() != 0)
+ emitter.indentPush();
+ }
+
+ // switch cases are SYNTHESIZED
+ if (type != ContainerType.IMPLICIT
+ && type != ContainerType.SYNTHESIZED)
+ {
- ((IEmitter) emitter).write(ASEmitterTokens.BLOCK_OPEN);
++ emitter.emitBlockOpen(container);
+ }
+
+ if (parent.getNodeID() != ASTNodeID.LabledStatementID)
+ {
- ((IEmitter) emitter).writeNewline();
++ emitter.writeNewline();
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
index 875d1d2,0000000..6f48f8e
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
@@@ -1,1540 -1,0 +1,1552 @@@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.flex.compiler.internal.codegen.as;
+
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.flex.compiler.codegen.IDocEmitter;
+import org.apache.flex.compiler.codegen.IEmitter;
+import org.apache.flex.compiler.codegen.IEmitterTokens;
+import org.apache.flex.compiler.codegen.as.IASEmitter;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.IImportTarget;
+import org.apache.flex.compiler.common.ModifiersSet;
+import org.apache.flex.compiler.constants.IASKeywordConstants;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.definitions.IVariableDefinition;
+import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
+import org.apache.flex.compiler.internal.tree.as.ChainedVariableNode;
+import org.apache.flex.compiler.internal.tree.as.ContainerNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.LabeledStatementNode;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IAccessorNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.ICatchNode;
+import org.apache.flex.compiler.tree.as.IClassNode;
+import org.apache.flex.compiler.tree.as.IConditionalNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IContainerNode.ContainerType;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IForLoopNode;
+import org.apache.flex.compiler.tree.as.IFunctionCallNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IFunctionObjectNode;
+import org.apache.flex.compiler.tree.as.IGetterNode;
+import org.apache.flex.compiler.tree.as.IIdentifierNode;
+import org.apache.flex.compiler.tree.as.IIfNode;
+import org.apache.flex.compiler.tree.as.IImportNode;
+import org.apache.flex.compiler.tree.as.IInterfaceNode;
+import org.apache.flex.compiler.tree.as.IIterationFlowNode;
+import org.apache.flex.compiler.tree.as.IKeywordNode;
+import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.flex.compiler.tree.as.ILiteralContainerNode;
+import org.apache.flex.compiler.tree.as.ILiteralNode;
+import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.INamespaceAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.INamespaceNode;
+import org.apache.flex.compiler.tree.as.INumericLiteralNode;
+import org.apache.flex.compiler.tree.as.IObjectLiteralValuePairNode;
+import org.apache.flex.compiler.tree.as.IOperatorNode;
+import org.apache.flex.compiler.tree.as.IPackageNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.IReturnNode;
+import org.apache.flex.compiler.tree.as.IScopedNode;
+import org.apache.flex.compiler.tree.as.ISetterNode;
+import org.apache.flex.compiler.tree.as.IStatementNode;
+import org.apache.flex.compiler.tree.as.ISwitchNode;
+import org.apache.flex.compiler.tree.as.ITerminalNode;
+import org.apache.flex.compiler.tree.as.ITernaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IThrowNode;
+import org.apache.flex.compiler.tree.as.ITryNode;
+import org.apache.flex.compiler.tree.as.ITypeNode;
+import org.apache.flex.compiler.tree.as.ITypedExpressionNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IUseNamespaceNode;
+import org.apache.flex.compiler.tree.as.IVariableExpressionNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.apache.flex.compiler.tree.as.IWhileLoopNode;
+import org.apache.flex.compiler.tree.as.IWithNode;
+import org.apache.flex.compiler.tree.metadata.IMetaTagNode;
+import org.apache.flex.compiler.utils.ASNodeUtils;
+import org.apache.flex.compiler.visitor.IBlockWalker;
+import org.apache.flex.compiler.visitor.as.IASBlockWalker;
+
+/**
+ * The base implementation for an ActionScript emitter.
+ *
+ * @author Michael Schmalle
+ */
+public class ASEmitter implements IASEmitter, IEmitter
+{
+ private final FilterWriter out;
+
+ private boolean bufferWrite;
+
+ protected boolean isBufferWrite()
+ {
+ return bufferWrite;
+ }
+
+ public void setBufferWrite(boolean value)
+ {
+ bufferWrite = value;
+ }
+
+ private StringBuilder builder;
+
+ protected StringBuilder getBuilder()
+ {
+ return builder;
+ }
+
+ protected void setBuilder(StringBuilder sb)
+ {
+ builder = sb;
+ }
+
+ protected void flushBuilder()
+ {
+ setBufferWrite(false);
+ write(builder.toString());
+ builder.setLength(0);
+ }
+
+ // (mschmalle) think about how this should be implemented, we can add our
+ // own problems to this, they don't just have to be parse problems
+ public List<ICompilerProblem> getProblems()
+ {
+ return walker.getErrors();
+ }
+
+ private int currentIndent = 0;
+
+ protected int getCurrentIndent()
+ {
+ return currentIndent;
+ }
+
+ protected void writeIndent()
+ {
+ write(ASEmitterTokens.INDENT);
+ }
+
+ private IASBlockWalker walker;
+
+ @Override
+ public IBlockWalker getWalker()
+ {
+ return walker;
+ }
+
+ @Override
+ public void setWalker(IBlockWalker value)
+ {
+ walker = (IASBlockWalker) value;
+ }
+
+ @Override
+ public IDocEmitter getDocEmitter()
+ {
+ return null;
+ }
+
+ @Override
+ public void setDocEmitter(IDocEmitter value)
+ {
+ }
+
+ private int currentLine = 0;
+
+ protected int getCurrentLine()
+ {
+ return currentLine;
+ }
+
+ private int currentColumn = 0;
+
+ protected int getCurrentColumn()
+ {
+ return currentColumn;
+ }
+
+ public ASEmitter(FilterWriter out)
+ {
+ this.out = out;
+ builder = new StringBuilder();
+ }
+
+ @Override
+ public String postProcess(String output)
+ {
+ return output;
+ }
+
+ @Override
+ public void write(IEmitterTokens value)
+ {
+ write(value.getToken());
+ }
+
+ @Override
+ public void write(String value)
+ {
+ try
+ {
+ int newLineCount = value.length() - value.replace("\n", "").length();
+ currentLine += newLineCount;
+ if (newLineCount > 0)
+ {
+ currentColumn = value.length() - value.lastIndexOf("\n") - 1;
+ }
+ else
+ {
+ currentColumn += value.length();
+ }
+ if (!bufferWrite)
+ out.write(value);
+ else
+ builder.append(value);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected String getIndent(int numIndent)
+ {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < numIndent; i++)
+ sb.append(ASEmitterTokens.INDENT.getToken());
+ return sb.toString();
+ }
+
+ @Override
+ public void indentPush()
+ {
+ currentIndent++;
+ }
+
+ @Override
+ public void indentPop()
+ {
+ currentIndent--;
+ }
+
+ @Override
+ public void writeNewline()
+ {
+ write(ASEmitterTokens.NEW_LINE);
+ write(getIndent(currentIndent));
+ }
+
+ @Override
+ public void writeNewline(IEmitterTokens value)
+ {
+ writeNewline(value.getToken());
+ }
+
+ @Override
+ public void writeNewline(String value)
+ {
+ write(value);
+ writeNewline();
+ }
+
+ @Override
+ public void writeNewline(IEmitterTokens value, boolean pushIndent)
+ {
+ writeNewline(value.getToken(), pushIndent);
+ }
+
+ @Override
+ public void writeNewline(String value, boolean pushIndent)
+ {
+ if (pushIndent)
+ indentPush();
+ else
+ indentPop();
+ write(value);
+ writeNewline();
+ }
+
+ public void writeSymbol(String value)
+ {
+ write(value);
+ }
+
+ @Override
+ public void writeToken(IEmitterTokens value)
+ {
+ writeToken(value.getToken());
+ }
+
+ @Override
+ public void writeToken(String value)
+ {
+ write(value);
+ write(ASEmitterTokens.SPACE);
+ }
+
+ //--------------------------------------------------------------------------
+ // IPackageNode
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitImport(IImportNode node)
+ {
+ IImportTarget target = node.getImportTarget();
+ writeToken(ASEmitterTokens.IMPORT);
+ write(target.toString());
+ }
+
+ @Override
+ public void emitPackageHeader(IPackageDefinition definition)
+ {
+ write(ASEmitterTokens.PACKAGE);
+
+ IPackageNode node = definition.getNode();
+ String name = node.getQualifiedName();
+ if (name != null && !name.equals(""))
+ {
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(node.getNameExpressionNode());
+ }
+
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ }
+
+ @Override
+ public void emitPackageHeaderContents(IPackageDefinition definition)
+ {
+ }
+
+ @Override
+ public void emitPackageContents(IPackageDefinition definition)
+ {
+ IPackageNode node = definition.getNode();
+ ITypeNode tnode = EmitterUtils.findTypeNode(node);
+ if (tnode != null)
+ {
+ indentPush();
+ writeNewline();
+ getWalker().walk(tnode); // IClassNode | IInterfaceNode
+ }
+ }
+
+ @Override
+ public void emitPackageFooter(IPackageDefinition definition)
+ {
+ indentPop();
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitClass(IClassNode node)
+ {
+ writeToken(node.getNamespace());
+
+ if (node.hasModifier(ASModifier.FINAL))
+ {
+ writeToken(ASEmitterTokens.FINAL);
+ }
+ else if (node.hasModifier(ASModifier.DYNAMIC))
+ {
+ writeToken(ASEmitterTokens.DYNAMIC);
+ }
+
+ writeToken(ASEmitterTokens.CLASS);
+ getWalker().walk(node.getNameExpressionNode());
+ write(ASEmitterTokens.SPACE);
+
+ IExpressionNode bnode = node.getBaseClassExpressionNode();
+ if (bnode != null)
+ {
+ writeToken(ASEmitterTokens.EXTENDS);
+ getWalker().walk(bnode);
+ write(ASEmitterTokens.SPACE);
+ }
+
+ IExpressionNode[] inodes = node.getImplementedInterfaceNodes();
+ final int ilen = inodes.length;
+ if (ilen != 0)
+ {
+ writeToken(ASEmitterTokens.IMPLEMENTS);
+ for (int i = 0; i < ilen; i++)
+ {
+ getWalker().walk(inodes[i]);
+ if (i < ilen - 1)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ }
+ write(ASEmitterTokens.SPACE);
+ }
+
+ write(ASEmitterTokens.BLOCK_OPEN);
+
+ // fields, methods, namespaces
+ final IDefinitionNode[] members = node.getAllMemberNodes();
+ if (members.length > 0)
+ {
+ indentPush();
+ writeNewline();
+
+ final int len = members.length;
+ int i = 0;
+ for (IDefinitionNode mnode : members)
+ {
+ getWalker().walk(mnode);
+ if (mnode.getNodeID() == ASTNodeID.VariableID)
+ {
+ write(ASEmitterTokens.SEMICOLON);
+ if (i < len - 1)
+ writeNewline();
+ }
+ else if (mnode.getNodeID() == ASTNodeID.FunctionID)
+ {
+ if (i < len - 1)
+ writeNewline();
+ }
+ else if (mnode.getNodeID() == ASTNodeID.GetterID
+ || mnode.getNodeID() == ASTNodeID.SetterID)
+ {
+ if (i < len - 1)
+ writeNewline();
+ }
+ i++;
+ }
+
+ indentPop();
+ }
+
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ @Override
+ public void emitInterface(IInterfaceNode node)
+ {
+ writeToken(node.getNamespace());
+
+ writeToken(ASEmitterTokens.INTERFACE);
+ getWalker().walk(node.getNameExpressionNode());
+ write(ASEmitterTokens.SPACE);
+
+ IExpressionNode[] inodes = node.getExtendedInterfaceNodes();
+ final int ilen = inodes.length;
+ if (ilen != 0)
+ {
+ writeToken(ASEmitterTokens.EXTENDS);
+ for (int i = 0; i < ilen; i++)
+ {
+ getWalker().walk(inodes[i]);
+ if (i < ilen - 1)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ }
+ write(ASEmitterTokens.SPACE);
+ }
+
+ write(ASEmitterTokens.BLOCK_OPEN);
+
+ final IDefinitionNode[] members = node.getAllMemberDefinitionNodes();
+ if (members.length > 0)
+ {
+ indentPush();
+ writeNewline();
+
+ final int len = members.length;
+ int i = 0;
+ for (IDefinitionNode mnode : members)
+ {
+ getWalker().walk(mnode);
+ write(ASEmitterTokens.SEMICOLON);
+ if (i < len - 1)
+ writeNewline();
+ i++;
+ }
+
+ indentPop();
+ }
+
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitVarDeclaration(IVariableNode node)
+ {
+ if (!(node instanceof ChainedVariableNode))
+ {
+ emitMemberKeyword(node);
+ }
+
+ emitDeclarationName(node);
+ emitType(node.getVariableTypeNode());
+
+ IExpressionNode avnode = node.getAssignedValueNode();
+ if (avnode != null)
+ {
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ emitAssignedValue(avnode);
+ }
+
+ if (!(node instanceof ChainedVariableNode))
+ {
+ // check for chained variables
+ int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IASNode child = node.getChild(i);
+ if (child instanceof ChainedVariableNode)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ emitVarDeclaration((IVariableNode) child);
+ }
+ }
+ }
+
+ // the client such as IASBlockWalker is responsible for the
+ // semi-colon and newline handling
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitFieldDocumentation(IVariableNode node)
+ {
+ }
+
+ @Override
+ public void emitField(IVariableNode node)
+ {
+ emitFieldDocumentation(node);
+
+ IVariableDefinition definition = (IVariableDefinition) node
+ .getDefinition();
+
+ if (!(node instanceof ChainedVariableNode))
+ {
+ emitNamespaceIdentifier(node);
+ emitModifiers(definition);
+ emitMemberKeyword(node);
+ }
+
+ emitMemberName(node);
+ emitType(node.getVariableTypeNode());
+
+ IExpressionNode avnode = node.getAssignedValueNode();
+ if (avnode != null)
+ {
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ emitAssignedValue(avnode);
+ }
+
+ if (!(node instanceof ChainedVariableNode))
+ {
+ // check for chained variables
+ int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IASNode child = node.getChild(i);
+ if (child instanceof ChainedVariableNode)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ emitField((IVariableNode) child);
+ }
+ }
+ }
+
+ // the client such as IASBlockWalker is responsible for the
+ // semi-colon and newline handling
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitMethodDocumentation(IFunctionNode node)
+ {
+ }
+
+ @Override
+ public void emitMethod(IFunctionNode node)
+ {
+ // see below, this is temp, I don't want a bunch of duplicated code
+ // at them moment, subclasses can refine anyways, we are generalizing
+ if (node instanceof IGetterNode)
+ {
+ emitGetAccessorDocumentation((IGetterNode) node);
+ }
+ else if (node instanceof ISetterNode)
+ {
+ emitSetAccessorDocumentation((ISetterNode) node);
+ }
+ else
+ {
+ emitMethodDocumentation(node);
+ }
+
+ FunctionNode fn = (FunctionNode) node;
+ fn.parseFunctionBody(getProblems());
+
+ IFunctionDefinition definition = node.getDefinition();
+
+ emitNamespaceIdentifier(node);
+ emitModifiers(definition);
+ emitMemberKeyword(node);
+
+ // I'm cheating right here, I haven't "seen" the light
+ // on how to properly and efficiently deal with accessors since they are SO alike
+ // I don't want to lump them in with methods because implementations in the
+ // future need to know the difference without loopholes
+ if (node instanceof IAccessorNode)
+ {
+ emitAccessorKeyword(((IAccessorNode) node).getAccessorKeywordNode());
+ }
+
+ emitMemberName(node);
+ emitParameters(node.getParametersContainerNode());
+ emitType(node.getReturnTypeNode());
+ if (node.getParent().getParent().getNodeID() == ASTNodeID.ClassID)
+ {
+ emitMethodScope(node.getScopedNode());
+ }
+
+ // the client such as IASBlockWalker is responsible for the
+ // semi-colon and newline handling
+ }
+
+ @Override
+ public void emitGetAccessorDocumentation(IGetterNode node)
+ {
+ }
+
+ @Override
+ public void emitGetAccessor(IGetterNode node)
+ {
+ // just cheat for now, IGetterNode is a IFunctionNode
+ emitMethod(node);
+ }
+
+ @Override
+ public void emitSetAccessorDocumentation(ISetterNode node)
+ {
+ }
+
+ @Override
+ public void emitSetAccessor(ISetterNode node)
+ {
+ // just cheat for now, ISetterNode is a IFunctionNode
+ emitMethod(node);
+ }
+
+ @Override
+ public void emitLocalNamedFunction(IFunctionNode node)
+ {
+ FunctionNode fnode = (FunctionNode) node;
+ write(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.SPACE);
+ write(fnode.getName());
+ emitParameters(fnode.getParametersContainerNode());
+ emitType(fnode.getTypeNode());
+ emitFunctionScope(fnode.getScopedNode());
+ }
+
+ @Override
+ public void emitFunctionObject(IFunctionObjectNode node)
+ {
+ FunctionNode fnode = node.getFunctionNode();
+ write(ASEmitterTokens.FUNCTION);
+ emitParameters(fnode.getParametersContainerNode());
+ emitType(fnode.getTypeNode());
+ emitFunctionScope(fnode.getScopedNode());
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitNamespace(INamespaceNode node)
+ {
+ emitNamespaceIdentifier(node);
+ writeToken(ASEmitterTokens.NAMESPACE);
+ emitMemberName(node);
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ getWalker().walk(node.getNamespaceURINode());
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ //--------------------------------------------------------------------------
+
+ protected void emitNamespaceIdentifier(IDefinitionNode node)
+ {
+ String namespace = node.getNamespace();
+ if (namespace != null
+ && !namespace.equals(IASKeywordConstants.INTERNAL))
+ {
+ writeToken(namespace);
+ }
+ }
+
+ protected void emitModifiers(IDefinition definition)
+ {
+ ModifiersSet modifierSet = definition.getModifiers();
+ if (modifierSet.hasModifiers())
+ {
+ for (ASModifier modifier : modifierSet.getAllModifiers())
+ {
+ writeToken(modifier.toString());
+ }
+ }
+ }
+
+ public void emitMemberKeyword(IDefinitionNode node)
+ {
+ if (node instanceof IFunctionNode)
+ {
+ writeToken(ASEmitterTokens.FUNCTION);
+ }
+ else if (node instanceof IVariableNode)
+ {
+ writeToken(((IVariableNode) node).isConst() ? ASEmitterTokens.CONST
+ : ASEmitterTokens.VAR);
+ }
+ }
+
+ protected void emitMemberName(IDefinitionNode node)
+ {
+ getWalker().walk(node.getNameExpressionNode());
+ }
+
+ public void emitDeclarationName(IDefinitionNode node)
+ {
+ getWalker().walk(node.getNameExpressionNode());
+ }
+
+ public void emitParameters(IContainerNode node)
+ {
+ write(ASEmitterTokens.PAREN_OPEN);
+ int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IParameterNode parameterNode = (IParameterNode) node.getChild(i);
+ getWalker().walk(parameterNode); //emitParameter
+ if (i < len - 1)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ }
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ @Override
+ public void emitParameter(IParameterNode node)
+ {
+ if (node.isRest())
+ {
+ write(ASEmitterTokens.ELLIPSIS);
+ write(node.getName());
+ }
+ else
+ {
+ getWalker().walk(node.getNameExpressionNode());
+ write(ASEmitterTokens.COLON);
+ getWalker().walk(node.getVariableTypeNode());
+ IExpressionNode anode = node.getAssignedValueNode();
+ if (anode != null)
+ {
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ getWalker().walk(anode);
+ }
+ }
+ }
+
+ protected void emitType(IExpressionNode node)
+ {
+ // TODO (mschmalle) node.getVariableTypeNode() will return "*" if undefined, what to use?
+ // or node.getReturnTypeNode()
+ if (node != null)
+ {
+ write(ASEmitterTokens.COLON);
+ getWalker().walk(node);
+ }
+ }
+
+ protected void emitAssignedValue(IExpressionNode node)
+ {
+ if (node == null)
+ {
+ return;
+ }
+ getWalker().walk(node);
+ }
+
+ @Override
+ public void emitFunctionBlockHeader(IFunctionNode node)
+ {
+ // nothing to do in AS
+ }
+
+ public void emitMethodScope(IScopedNode node)
+ {
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(node);
+ }
+
+ protected void emitAccessorKeyword(IKeywordNode node)
+ {
+ getWalker().walk(node);
+ write(ASEmitterTokens.SPACE);
+ }
+
+ protected void emitFunctionScope(IScopedNode node)
+ {
+ emitMethodScope(node);
+ }
+
+ //--------------------------------------------------------------------------
+ // Statements
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitStatement(IASNode node)
+ {
+ getWalker().walk(node);
+ // XXX (mschmalle) this should be in the after handler?
+ if (node.getParent().getNodeID() != ASTNodeID.LabledStatementID
+ && node.getNodeID() != ASTNodeID.ConfigBlockID
+ && !(node instanceof IStatementNode))
+ {
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ if (!isLastStatement(node))
+ writeNewline();
+ }
+
+ @Override
+ public void emitIf(IIfNode node)
+ {
+ IConditionalNode conditional = (IConditionalNode) node.getChild(0);
+
+ IContainerNode xnode = (IContainerNode) conditional
+ .getStatementContentsNode();
+
+ writeToken(ASEmitterTokens.IF);
+ //write(SPACE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(conditional.getChild(0)); // conditional expression
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (!isImplicit(xnode))
+ write(ASEmitterTokens.SPACE);
+
+ getWalker().walk(conditional.getChild(1)); // BlockNode
+ IConditionalNode[] nodes = node.getElseIfNodes();
+ if (nodes.length > 0)
+ {
+ for (int i = 0; i < nodes.length; i++)
+ {
+ IConditionalNode enode = nodes[i];
+ IContainerNode snode = (IContainerNode) enode
+ .getStatementContentsNode();
+
+ final boolean isImplicit = isImplicit(snode);
+ if (isImplicit)
+ writeNewline();
+ else
+ write(ASEmitterTokens.SPACE);
+
+ writeToken(ASEmitterTokens.ELSE);
+ writeToken(ASEmitterTokens.IF);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(enode.getChild(0));
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (!isImplicit)
+ write(ASEmitterTokens.SPACE);
+
+ getWalker().walk(enode.getChild(1)); // ConditionalNode
+ }
+ }
+
+ ITerminalNode elseNode = node.getElseNode();
+ if (elseNode != null)
+ {
+ IContainerNode cnode = (IContainerNode) elseNode.getChild(0);
+ // if an implicit if, add a newline with no space
+ final boolean isImplicit = isImplicit(cnode);
+ if (isImplicit)
+ writeNewline();
+ else
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.ELSE);
+ if (!isImplicit)
+ write(ASEmitterTokens.SPACE);
+
+ getWalker().walk(elseNode); // TerminalNode
+ }
+ }
+
+ @Override
+ public void emitForEachLoop(IForLoopNode node)
+ {
+ IContainerNode xnode = (IContainerNode) node.getChild(1);
+ writeToken(ASEmitterTokens.FOR);
+ writeToken(ASEmitterTokens.EACH);
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ IContainerNode cnode = node.getConditionalsContainerNode();
+ getWalker().walk(cnode.getChild(0));
+
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (!isImplicit(xnode))
+ write(ASEmitterTokens.SPACE);
+
+ getWalker().walk(node.getStatementContentsNode());
+ }
+
+ @Override
+ public void emitForLoop(IForLoopNode node)
+ {
+ IContainerNode xnode = (IContainerNode) node.getChild(1);
+
+ writeToken(ASEmitterTokens.FOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ IContainerNode cnode = node.getConditionalsContainerNode();
+ final IASNode node0 = cnode.getChild(0);
+ if (node0.getNodeID() == ASTNodeID.Op_InID)
+ {
+ getWalker().walk(cnode.getChild(0));
+ }
+ else
+ {
+ visitForBody(cnode);
+ }
+
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (!isImplicit(xnode))
+ write(ASEmitterTokens.SPACE);
+
+ getWalker().walk(node.getStatementContentsNode());
+ }
+
+ @Override
+ public void emitSwitch(ISwitchNode node)
+ {
+ writeToken(ASEmitterTokens.SWITCH);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getChild(0));
+ writeToken(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.BLOCK_OPEN, true);
+
+ IConditionalNode[] cnodes = ASNodeUtils.getCaseNodes(node);
+ ITerminalNode dnode = ASNodeUtils.getDefaultNode(node);
+
+ for (int i = 0; i < cnodes.length; i++)
+ {
+ IConditionalNode casen = cnodes[i];
+ IContainerNode cnode = (IContainerNode) casen.getChild(1);
+ writeToken(ASEmitterTokens.CASE);
+ getWalker().walk(casen.getConditionalExpressionNode());
+ write(ASEmitterTokens.COLON);
+ if (!isImplicit(cnode))
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(casen.getStatementContentsNode());
+ if (i == cnodes.length - 1 && dnode == null)
+ {
+ indentPop();
+ writeNewline();
+ }
+ else
+ writeNewline();
+ }
+ if (dnode != null)
+ {
+ IContainerNode cnode = (IContainerNode) dnode.getChild(0);
+ write(ASEmitterTokens.DEFAULT);
+ write(ASEmitterTokens.COLON);
+ if (!isImplicit(cnode))
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(dnode);
+ indentPop();
+ writeNewline();
+ }
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ @Override
+ public void emitWhileLoop(IWhileLoopNode node)
+ {
+ IContainerNode cnode = (IContainerNode) node.getChild(1);
+ writeToken(ASEmitterTokens.WHILE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getConditionalExpressionNode());
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (!isImplicit(cnode))
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(node.getStatementContentsNode());
+ }
+
+ @Override
+ public void emitDoLoop(IWhileLoopNode node)
+ {
+ IContainerNode cnode = (IContainerNode) node.getChild(0);
+ write(ASEmitterTokens.DO);
+ if (!isImplicit(cnode))
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(node.getStatementContentsNode());
+ if (!isImplicit(cnode))
+ write(ASEmitterTokens.SPACE);
+ else
+ writeNewline(); // TODO (mschmalle) there is something wrong here, block should NL
+ write(ASEmitterTokens.WHILE);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getConditionalExpressionNode());
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ @Override
+ public void emitWith(IWithNode node)
+ {
+ IContainerNode cnode = (IContainerNode) node.getChild(1);
+ writeToken(ASEmitterTokens.WITH);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getTargetNode());
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (!isImplicit(cnode))
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(node.getStatementContentsNode());
+ }
+
+ @Override
+ public void emitThrow(IThrowNode node)
+ {
+ writeToken(ASEmitterTokens.THROW);
+ getWalker().walk(node.getThrownExpressionNode());
+ }
+
+ @Override
+ public void emitTry(ITryNode node)
+ {
+ writeToken(ASEmitterTokens.TRY);
+ getWalker().walk(node.getStatementContentsNode());
+ for (int i = 0; i < node.getCatchNodeCount(); i++)
+ {
+ getWalker().walk(node.getCatchNode(i));
+ }
+ ITerminalNode fnode = node.getFinallyNode();
+ if (fnode != null)
+ {
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.FINALLY);
+ getWalker().walk(fnode);
+ }
+ }
+
+ @Override
+ public void emitCatch(ICatchNode node)
+ {
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.CATCH);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getCatchParameterNode());
+ writeToken(ASEmitterTokens.PAREN_CLOSE);
+ getWalker().walk(node.getStatementContentsNode());
+ }
+
+ @Override
+ public void emitReturn(IReturnNode node)
+ {
+ write(ASEmitterTokens.RETURN);
+ IExpressionNode rnode = node.getReturnValueNode();
+ if (rnode != null && rnode.getNodeID() != ASTNodeID.NilID)
+ {
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(rnode);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Expressions
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitFunctionCall(IFunctionCallNode node)
+ {
+ if (node.isNewExpression())
+ {
+ writeToken(ASEmitterTokens.NEW);
+ }
+
+ getWalker().walk(node.getNameNode());
+
+ emitArguments(node.getArgumentsNode());
+ }
+
+ @Override
+ public void emitArguments(IContainerNode node)
+ {
+ write(ASEmitterTokens.PAREN_OPEN);
+ int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IExpressionNode argumentNode = (IExpressionNode) node.getChild(i);
+ getWalker().walk(argumentNode);
+ if (i < len - 1)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ }
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ //--------------------------------------------------------------------------
+ // Operators
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitAsOperator(IBinaryOperatorNode node)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+ write(ASEmitterTokens.SPACE);
+ writeToken(node.getOperator().getOperatorText());
+ getWalker().walk(node.getRightOperandNode());
+ }
+
+ @Override
+ public void emitIsOperator(IBinaryOperatorNode node)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+ write(ASEmitterTokens.SPACE);
+ writeToken(node.getOperator().getOperatorText());
+ getWalker().walk(node.getRightOperandNode());
+ }
+
+ @Override
+ public void emitBinaryOperator(IBinaryOperatorNode node)
+ {
+ if (ASNodeUtils.hasParenOpen(node))
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getLeftOperandNode());
+ if (node.getNodeID() != ASTNodeID.Op_CommaID)
+ write(ASEmitterTokens.SPACE);
+ writeToken(node.getOperator().getOperatorText());
+ getWalker().walk(node.getRightOperandNode());
+ if (ASNodeUtils.hasParenClose(node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ //--------------------------------------------------------------------------
+ // Utility
+ //--------------------------------------------------------------------------
+
+ protected ITypeNode findTypeNode(IPackageNode node)
+ {
+ IScopedNode scope = node.getScopedNode();
+ for (int i = 0; i < scope.getChildCount(); i++)
+ {
+ IASNode child = scope.getChild(i);
+ if (child instanceof ITypeNode)
+ return (ITypeNode) child;
+ }
+ return null;
+ }
+
+ protected ITypeDefinition findType(Collection<IDefinition> definitions)
+ {
+ for (IDefinition definition : definitions)
+ {
+ if (definition instanceof ITypeDefinition)
+ return (ITypeDefinition) definition;
+ }
+ return null;
+ }
+
+ //--------------------------------------------------------------------------
+ // Static Utility
+ //--------------------------------------------------------------------------
+
+ protected static IFunctionNode getConstructor(IDefinitionNode[] members)
+ {
+ for (IDefinitionNode node : members)
+ {
+ if (node instanceof IFunctionNode)
+ {
+ IFunctionNode fnode = (IFunctionNode) node;
+ if (fnode.isConstructor())
+ return fnode;
+ }
+ }
+ return null;
+ }
+
+ protected static boolean isLastStatement(IASNode node)
+ {
+ return getChildIndex(node.getParent(), node) == node.getParent()
+ .getChildCount() - 1;
+ }
+
+ // this is not fair that we have to do this if (i < len - 1)
+ private static int getChildIndex(IASNode parent, IASNode node)
+ {
+ final int len = parent.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ if (parent.getChild(i) == node)
+ return i;
+ }
+ return -1;
+ }
+
+ protected static final boolean isImplicit(IContainerNode node)
+ {
+ return EmitterUtils.isImplicit(node);
+ }
+
+ protected void visitForBody(IContainerNode node)
+ {
+ final IASNode node0 = node.getChild(0);
+ final IASNode node1 = node.getChild(1);
+ final IASNode node2 = node.getChild(2);
+
+ // initializer
+ if (node0 != null)
+ {
+ getWalker().walk(node0);
+ write(ASEmitterTokens.SEMICOLON);
+ if (node1.getNodeID() != ASTNodeID.NilID)
+ write(ASEmitterTokens.SPACE);
+ }
+ // condition or target
+ if (node1 != null)
+ {
+ getWalker().walk(node1);
+ write(ASEmitterTokens.SEMICOLON);
+ if (node2.getNodeID() != ASTNodeID.NilID)
+ write(ASEmitterTokens.SPACE);
+ }
+ // iterator
+ if (node2 != null)
+ {
+ getWalker().walk(node2);
+ }
+ }
+
+ @Override
+ public void emitLiteral(ILiteralNode node)
+ {
+ write(node.getValue(true));
+ }
+
+ @Override
+ public void emitLiteralContainer(ILiteralContainerNode node)
+ {
+ final ContainerNode cnode = node.getContentsNode();
+ final ContainerType type = cnode.getContainerType();
+ String postFix = "";
+
+ if (type == ContainerType.BRACES)
+ {
+ write(ASEmitterTokens.BLOCK_OPEN);
+ postFix = ASEmitterTokens.BLOCK_CLOSE.getToken();
+ }
+ else if (type == ContainerType.BRACKETS)
+ {
+ write(ASEmitterTokens.SQUARE_OPEN);
+ postFix = ASEmitterTokens.SQUARE_CLOSE.getToken();
+ }
+ else if (type == ContainerType.IMPLICIT)
+ {
+ // nothing to write, move along
+ }
+ else if (type == ContainerType.PARENTHESIS)
+ {
+ write(ASEmitterTokens.PAREN_OPEN);
+ postFix = ASEmitterTokens.PAREN_CLOSE.getToken();
+ }
+
+ final int len = cnode.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IASNode child = cnode.getChild(i);
+ getWalker().walk(child);
+ if (i < len - 1)
+ writeToken(ASEmitterTokens.COMMA);
+ }
+
+ if (postFix != "")
+ write(postFix);
+ }
+
+ @Override
+ public void emitIdentifier(IIdentifierNode node)
+ {
+ write(node.getName());
+ }
+
+ @Override
+ public void emitNumericLiteral(INumericLiteralNode node)
+ {
+ write(node.getNumericValue().toString());
+ }
+
+ @Override
+ public void emitKeyword(IKeywordNode node)
+ {
+ write(node.getNodeID().getParaphrase());
+ }
+
+ @Override
+ public void emitIterationFlow(IIterationFlowNode node)
+ {
+ write(node.getKind().toString().toLowerCase());
+ IIdentifierNode lnode = node.getLabelNode();
+ if (lnode != null)
+ {
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(lnode);
+ }
+ }
+
+ @Override
+ public void emitMemberAccessExpression(IMemberAccessExpressionNode node)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+ write(node.getOperator().getOperatorText());
+ getWalker().walk(node.getRightOperandNode());
+ }
+
+ @Override
+ public void emitDynamicAccess(IDynamicAccessNode node)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+ write(ASEmitterTokens.SQUARE_OPEN);
+ getWalker().walk(node.getRightOperandNode());
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ }
+
+ @Override
+ public void emitTypedExpression(ITypedExpressionNode node)
+ {
+ getWalker().walk(node.getCollectionNode());
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(ASEmitterTokens.LESS_THAN);
+ getWalker().walk(node.getTypeNode());
+ write(ASEmitterTokens.GREATER_THAN);
+ }
+
+ @Override
+ public void emitVariableExpression(IVariableExpressionNode node)
+ {
+ getWalker().walk(node.getTargetVariable());
+ }
+
+ @Override
+ public void emitTernaryOperator(ITernaryOperatorNode node)
+ {
+ if (ASNodeUtils.hasParenOpen((IOperatorNode) node))
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getConditionalNode());
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.TERNARY);
+ getWalker().walk(node.getLeftOperandNode());
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.COLON);
+ getWalker().walk(node.getRightOperandNode());
+ if (ASNodeUtils.hasParenClose((IOperatorNode) node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ @Override
+ public void emitObjectLiteralValuePair(IObjectLiteralValuePairNode node)
+ {
+ getWalker().walk(node.getNameNode());
+ write(ASEmitterTokens.COLON);
+ getWalker().walk(node.getValueNode());
+ }
+
+ @Override
+ public void emitLabelStatement(LabeledStatementNode node)
+ {
+ writeToken(node.getLabel());
+ writeToken(ASEmitterTokens.COLON);
+ getWalker().walk(node.getLabeledStatement());
+ }
+
+ @Override
+ public void emitNamespaceAccessExpression(
+ INamespaceAccessExpressionNode node)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+ write(node.getOperator().getOperatorText());
+ getWalker().walk(node.getRightOperandNode());
+ }
+
+ @Override
+ public void emitUnaryOperator(IUnaryOperatorNode node)
+ {
+ if (ASNodeUtils.hasParenOpen(node))
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ if (node.getNodeID() == ASTNodeID.Op_PreIncrID
+ || node.getNodeID() == ASTNodeID.Op_PreDecrID
+ || node.getNodeID() == ASTNodeID.Op_BitwiseNotID
+ || node.getNodeID() == ASTNodeID.Op_LogicalNotID
+ || node.getNodeID() == ASTNodeID.Op_SubtractID
+ || node.getNodeID() == ASTNodeID.Op_AddID)
+ {
+ write(node.getOperator().getOperatorText());
+ IExpressionNode opNode = node.getOperandNode();
+ getWalker().walk(opNode);
+ }
+
+ else if (node.getNodeID() == ASTNodeID.Op_PostIncrID
+ || node.getNodeID() == ASTNodeID.Op_PostDecrID)
+ {
+ getWalker().walk(node.getOperandNode());
+ write(node.getOperator().getOperatorText());
+ }
+ else if (node.getNodeID() == ASTNodeID.Op_DeleteID
+ || node.getNodeID() == ASTNodeID.Op_VoidID)
+ {
+ writeToken(node.getOperator().getOperatorText());
+ getWalker().walk(node.getOperandNode());
+ }
+ else if (node.getNodeID() == ASTNodeID.Op_TypeOfID)
+ {
+ write(node.getOperator().getOperatorText());
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getOperandNode());
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ if (ASNodeUtils.hasParenClose(node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ @Override
+ public void emitLanguageIdentifier(ILanguageIdentifierNode node)
+ {
+ if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.ANY_TYPE)
+ {
+ write(ASEmitterTokens.ANY_TYPE);
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.REST)
+ {
+ write(ASEmitterTokens.ELLIPSIS);
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.SUPER)
+ {
+ write(ASEmitterTokens.SUPER);
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS)
+ {
+ write(ASEmitterTokens.THIS);
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.VOID)
+ {
+ write(ASEmitterTokens.VOID);
+ }
+ }
+
+ @Override
+ public void emitMetaTag(IMetaTagNode node)
+ {
+ }
+
+ @Override
+ public void emitContainer(IContainerNode node)
+ {
+ }
+
+ @Override
+ public void emitE4XFilter(IMemberAccessExpressionNode node)
+ {
+ // ToDo (erikdebruin)
+ }
+
+ @Override
+ public void emitUseNamespace(IUseNamespaceNode node)
+ {
+ // ToDo (erikdebruin)
+ }
+
+ @Override
++ public void emitBlockOpen(IContainerNode node)
++ {
++ write(ASEmitterTokens.BLOCK_OPEN);
++ }
++
++ @Override
++ public void emitBlockClose(IContainerNode node)
++ {
++ write(ASEmitterTokens.BLOCK_CLOSE);
++ }
++
++ @Override
+ public String stringifyNode(IASNode node)
+ {
+ boolean oldBufferWrite = isBufferWrite();
+ StringBuilder oldBuilder = this.builder;
+ this.builder = new StringBuilder();
+ setBufferWrite(true);
+ getWalker().walk(node);
+ String result = getBuilder().toString();
+ getBuilder().setLength(0);
+ this.builder = oldBuilder;
+ setBufferWrite(oldBufferWrite);
+ return result;
+ }
+}
[03/14] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - compiler.jx: curly braces to open
and close blocks have been moved to the emitter
Posted by cd...@apache.org.
compiler.jx: curly braces to open and close blocks have been moved to the emitter
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/8c393616
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/8c393616
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/8c393616
Branch: refs/heads/feature/maven-migration-test
Commit: 8c393616b508426fa621e20c8d2b10d7a473b721
Parents: a9a399b
Author: Josh Tynjala <jo...@apache.org>
Authored: Sun Apr 17 15:17:13 2016 -0700
Committer: Josh Tynjala <jo...@apache.org>
Committed: Sun Apr 17 15:17:13 2016 -0700
----------------------------------------------------------------------
.../org/apache/flex/compiler/codegen/as/IASEmitter.java | 6 +++++-
.../internal/codegen/as/ASAfterNodeStrategy.java | 4 ++--
.../internal/codegen/as/ASBeforeNodeStrategy.java | 4 ++--
.../flex/compiler/internal/codegen/as/ASEmitter.java | 12 ++++++++++++
4 files changed, 21 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/8c393616/compiler.jx/src/org/apache/flex/compiler/codegen/as/IASEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/codegen/as/IASEmitter.java b/compiler.jx/src/org/apache/flex/compiler/codegen/as/IASEmitter.java
index bd0d1eb..2fe9eea 100644
--- a/compiler.jx/src/org/apache/flex/compiler/codegen/as/IASEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/codegen/as/IASEmitter.java
@@ -86,7 +86,7 @@ public interface IASEmitter extends IEmitter
void setDocEmitter(IDocEmitter value);
String postProcess(String output);
-
+
void emitImport(IImportNode node);
void emitPackageHeader(IPackageDefinition definition);
@@ -366,4 +366,8 @@ public interface IASEmitter extends IEmitter
void emitUseNamespace(IUseNamespaceNode node);
+ void emitBlockOpen(IContainerNode node);
+
+ void emitBlockClose(IContainerNode node);
+
}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/8c393616/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
index 1ac85f7..b274b57 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASAfterNodeStrategy.java
@@ -59,10 +59,10 @@ public class ASAfterNodeStrategy implements IASNodeStrategy
if (node.getChildCount() != 0)
{
emitter.indentPop();
- ((IEmitter) emitter).writeNewline();
+ emitter.writeNewline();
}
- ((IEmitter) emitter).write(ASEmitterTokens.BLOCK_CLOSE);
+ emitter.emitBlockClose(container);
}
else if (type == ContainerType.IMPLICIT
|| type == ContainerType.SYNTHESIZED)
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/8c393616/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
index d481573..d960057 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASBeforeNodeStrategy.java
@@ -61,12 +61,12 @@ public class ASBeforeNodeStrategy implements IASNodeStrategy
if (type != ContainerType.IMPLICIT
&& type != ContainerType.SYNTHESIZED)
{
- ((IEmitter) emitter).write(ASEmitterTokens.BLOCK_OPEN);
+ emitter.emitBlockOpen(container);
}
if (parent.getNodeID() != ASTNodeID.LabledStatementID)
{
- ((IEmitter) emitter).writeNewline();
+ emitter.writeNewline();
}
}
}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/8c393616/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
index 875d1d2..6f48f8e 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/as/ASEmitter.java
@@ -1524,6 +1524,18 @@ public class ASEmitter implements IASEmitter, IEmitter
}
@Override
+ public void emitBlockOpen(IContainerNode node)
+ {
+ write(ASEmitterTokens.BLOCK_OPEN);
+ }
+
+ @Override
+ public void emitBlockClose(IContainerNode node)
+ {
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ @Override
public String stringifyNode(IASNode node)
{
boolean oldBufferWrite = isBufferWrite();