allow keywords as identifier names
diff --git a/compiler.tests/feature-tests/as/ASKeywordTests.java b/compiler.tests/feature-tests/as/ASKeywordTests.java
new file mode 100644
index 0000000..e81e360
--- /dev/null
+++ b/compiler.tests/feature-tests/as/ASKeywordTests.java
@@ -0,0 +1,289 @@
+/*
+ *
+ * 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 as;
+
+import org.junit.Test;
+
+/**
+ * Feature tests for AS Namespaces.
+ */
+public class ASKeywordTests extends ASFeatureTestsBase
+{
+ @Test
+ public void ASKeyword_SwitchStatement()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function hasSwitch(switcher:int):Boolean {",
+ " trace('hey, a method named namespace worked');",
+ " switch (switcher) {",
+ " case 1:",
+ " foo = 'bar';",
+ " break;",
+ " default:",
+ " foo = 'baz';",
+ " break;",
+ " }",
+ " return true;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "hasSwitch(1);",
+ "assertEqual('switch worked', foo, 'bar');",
+ "hasSwitch(0);",
+ "assertEqual('switch worked', foo, 'baz');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_Namespace_as_method_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function namespace(instance:Object):Boolean {",
+ " trace('hey, a method named namespace worked');",
+ " foo = 'as';",
+ " return true;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "namespace(this);",
+ "assertEqual('method named namespace', foo, 'as');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_Default_as_method_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function default(instance:Object):Boolean {",
+ " trace('hey, a method named default worked');",
+ " foo = 'as';",
+ " return true;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "default(this);",
+ "assertEqual('method named default', foo, 'as');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_Get_as_method_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function get(instance:Object):Boolean {",
+ " trace('hey, a method named get worked');",
+ " foo = 'as';",
+ " return true;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "get(this);",
+ "assertEqual('method named get', foo, 'as');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_Get_as_getter_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function get get():Boolean {",
+ " trace('hey, a getter named get worked');",
+ " foo = 'as';",
+ " return true;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "var bar:Boolean = get;",
+ "assertEqual('getter named get', foo, 'as');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_Get_as_member_expression_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function get get():Boolean {",
+ " trace('hey, a getter named get worked');",
+ " foo = 'as';",
+ " return true;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "var bar:Boolean = this.get;",
+ "assertEqual('getter named get', foo, 'as');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_as_method_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function as(instance:Object):Boolean {",
+ " trace('hey, a method named as worked');",
+ " foo = 'as';",
+ " return true;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "as(this);",
+ "assertEqual('method named as', foo, 'as');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_as_property_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var foo:String;",
+ "public function get as():String {",
+ " return foo;",
+ "}",
+ "public function set as(value:String):void {",
+ " foo = value;",
+ "}",
+ };
+ String[] testCode = new String[]
+ {
+ "as = 'bar';",
+ "assertEqual('property named as', as, 'bar');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_as_variable_name()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var as:String;",
+ };
+ String[] testCode = new String[]
+ {
+ "as = 'bar';",
+ "assertEqual('variable named as', as, 'bar');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+ @Test
+ public void ASKeyword_as_member_expression()
+ {
+ // all tests can assume that flash.display.Sprite
+ // flash.system.System and flash.events.Event have been imported
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ "public var as:String;",
+ };
+ String[] testCode = new String[]
+ {
+ "this.as = 'bar';",
+ "assertEqual('variable named as', this.as, 'bar');",
+ };
+ String source = getAS(imports, declarations, testCode, new String[0]);
+ compileAndRun(source);
+ }
+
+}
diff --git a/compiler/src/org/apache/flex/compiler/internal/parsing/as/StreamingASTokenizer.java b/compiler/src/org/apache/flex/compiler/internal/parsing/as/StreamingASTokenizer.java
index 7f898c1..f06f68e 100644
--- a/compiler/src/org/apache/flex/compiler/internal/parsing/as/StreamingASTokenizer.java
+++ b/compiler/src/org/apache/flex/compiler/internal/parsing/as/StreamingASTokenizer.java
@@ -987,9 +987,9 @@
final ASToken maybeNS = LT(2);
final boolean foundTokenNamespace = maybeNS != null &&
maybeNS.getType() == TOKEN_RESERVED_WORD_NAMESPACE;
+ final ASToken maybeXML = LT(1);
if (foundTokenNamespace)
{
- final ASToken maybeXML = LT(1);
final boolean foundTokenXML = maybeXML != null &&
maybeXML.getType() == TOKEN_IDENTIFIER &&
XML.equals(maybeXML.getText());
@@ -1006,6 +1006,12 @@
retVal.setType(TOKEN_DIRECTIVE_DEFAULT_XML);
consume(2);
}
+ // if this isn't "default xml namespace" then
+ // see if it is the default case in a switch
+ // otherwise, assume it is an identiferName
+ else if (maybeXML != null &&
+ maybeXML.getType() != TOKEN_COLON)
+ retVal.setType(TOKEN_IDENTIFIER);
return retVal;
}
case TOKEN_KEYWORD_VOID:
@@ -1115,9 +1121,6 @@
case TOKEN_TYPED_COLLECTION_OPEN:
case TOKEN_TYPED_COLLECTION_CLOSE:
case TOKEN_OPERATOR_MEMBER_ACCESS:
- case TOKEN_KEYWORD_RETURN:
- case TOKEN_KEYWORD_THROW:
- case TOKEN_KEYWORD_NEW:
case TOKEN_RESERVED_WORD_NAMESPACE:
case TOKEN_RESERVED_WORD_GET:
case TOKEN_RESERVED_WORD_SET:
@@ -1147,6 +1150,91 @@
}
assert (false);
return null;
+ case TOKEN_KEYWORD_INSTANCEOF:
+ case TOKEN_KEYWORD_AS:
+ case TOKEN_KEYWORD_IN:
+ case TOKEN_KEYWORD_IS:
+ if (lastToken != null)
+ {
+ int lastTokenType = lastToken.getType();
+ switch (lastTokenType)
+ {
+ case TOKEN_SEMICOLON:
+ case TOKEN_BLOCK_OPEN:
+ case TOKEN_COMMA:
+ retVal.setType(TOKEN_IDENTIFIER);
+ return retVal;
+ }
+ }
+ else
+ {
+ // we are first token so assume identifier
+ retVal.setType(TOKEN_IDENTIFIER);
+ return retVal;
+ }
+ // and fall through
+ case TOKEN_KEYWORD_DELETE:
+ ASToken nextToken = LT(1);
+ if (nextToken != null)
+ {
+ int nextTokenType = nextToken.getType();
+ switch (nextTokenType)
+ {
+ // if followed by a token assume it is the
+ // keyword and not the identiferName;
+ case TOKEN_IDENTIFIER:
+ return retVal;
+ // followed by a comma or semicolon
+ // probably being used in an expression
+ case TOKEN_COMMA:
+ case TOKEN_SEMICOLON:
+ retVal.setType(TOKEN_IDENTIFIER);
+ return retVal;
+ }
+ }
+ // and fall through
+ case TOKEN_KEYWORD_BREAK:
+ case TOKEN_KEYWORD_CASE:
+ case TOKEN_KEYWORD_CATCH:
+ case TOKEN_KEYWORD_CLASS:
+ case TOKEN_KEYWORD_CONST:
+ case TOKEN_KEYWORD_CONTINUE:
+ case TOKEN_KEYWORD_DO:
+ case TOKEN_KEYWORD_ELSE:
+ case TOKEN_KEYWORD_FALSE:
+ case TOKEN_KEYWORD_FINALLY:
+ case TOKEN_KEYWORD_IF:
+ case TOKEN_KEYWORD_IMPORT:
+ case TOKEN_KEYWORD_INTERFACE:
+ case TOKEN_KEYWORD_NULL:
+ case TOKEN_KEYWORD_PACKAGE:
+ case TOKEN_KEYWORD_SUPER:
+ case TOKEN_KEYWORD_SWITCH:
+ case TOKEN_KEYWORD_THIS:
+ case TOKEN_KEYWORD_TRUE:
+ case TOKEN_KEYWORD_TRY:
+ case TOKEN_KEYWORD_TYPEOF:
+ case TOKEN_KEYWORD_USE:
+ case TOKEN_KEYWORD_VAR:
+ case TOKEN_KEYWORD_WHILE:
+ case TOKEN_KEYWORD_WITH:
+ case TOKEN_KEYWORD_RETURN:
+ case TOKEN_KEYWORD_THROW:
+ case TOKEN_KEYWORD_NEW:
+ if (lastToken != null)
+ {
+ int lastTokenType = lastToken.getType();
+ switch (lastTokenType)
+ {
+ case TOKEN_KEYWORD_VAR:
+ case TOKEN_KEYWORD_FUNCTION:
+ case TOKEN_RESERVED_WORD_GET:
+ case TOKEN_RESERVED_WORD_SET:
+ case TOKEN_OPERATOR_MEMBER_ACCESS:
+ retVal.setType(TOKEN_IDENTIFIER);
+ }
+ }
+ return retVal;
default:
if (ASToken.isE4X(tokenType))
return retVal;