You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by jo...@apache.org on 2022/10/27 22:48:47 UTC

[royale-compiler] branch develop updated (b7f3c3d05 -> f04e9788b)

This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a change to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git


    from b7f3c3d05 linter: fix FieldNameRule allowing uppercase letter after _ at start
     new b46727727 linter: start adding some tests
     new 58fb870f8 linter: add formatting/whitespace tokens to TokenQuery to support formatting rules
     new ced2dde29 SwitchNode: fix getDefaultNode() failing to get default node from inside an IBlockNode
     new 3fd41ac49 linter: more tests
     new 2b5660010 linter: EmptyStatementRule should handle block open before semicolon
     new f084dfaf1 linter: fix null results that should have been a token in TokenQuery classes
     new 4dafdbcef linter: LineCommentPositionRule fixes
     new 8aafd5bfa linter: more tests
     new f04e9788b linter: more tests

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/royale/compiler/utils/ASNodeUtils.java  |   1 -
 .../compiler/internal/tree/as/SwitchNode.java      |  13 +-
 linter/build.xml                                   |   2 +-
 .../java/org/apache/royale/linter/ASLinter.java    |  52 ++++-
 .../java/org/apache/royale/linter/MXMLLinter.java  |  37 +++-
 .../org/apache/royale/linter/MXMLTokenQuery.java   | 119 +++++++++--
 .../java/org/apache/royale/linter/TokenQuery.java  | 179 ++++++++++++++---
 .../royale/linter/rules/EmptyStatementRule.java    |  17 +-
 .../linter/rules/LineCommentPositionRule.java      |  14 +-
 .../royale/linter/rules/MissingASDocRule.java      |   2 +-
 .../org/apache/royale/linter/rules/NoWithRule.java |   1 -
 .../royale/linter/rules/StrictEqualityRule.java    |   1 -
 {formatter => linter}/src/test/build.xml           |  42 ++--
 .../royale/linter/rules/TestClassNameRule.java     | 111 +++++++++++
 .../royale/linter/rules/TestConstantNameRule.java  |  85 ++++++++
 .../royale/linter/rules/TestEmptyCommentRule.java  | 110 ++++++++++
 .../linter/rules/TestEmptyFunctionBodyRule.java    | 111 +++++++++++
 .../linter/rules/TestEmptyNestedBlockRule.java     | 109 ++++++++++
 .../linter/rules/TestEmptyStatementRule.java       |  98 +++++++++
 .../royale/linter/rules/TestFieldNameRule.java     | 123 ++++++++++++
 .../royale/linter/rules/TestFunctionNameRule.java  | 221 +++++++++++++++++++++
 .../royale/linter/rules/TestInterfaceNameRule.java | 111 +++++++++++
 .../linter/rules/TestLineCommentPositionRule.java  |  93 +++++++++
 .../rules/TestLocalVarAndParameterNameRule.java    | 201 +++++++++++++++++++
 .../linter/rules/TestLocalVarShadowsFieldRule.java |  45 ++---
 .../apache/royale/linter/rules/TestMXMLIDRule.java | 124 ++++++++++++
 .../royale/linter/rules/TestNoAnyTypeRule.java     | 109 ++++++++++
 .../linter/rules/TestNoBooleanEqualityRule.java    |  98 +++++++++
 .../rules/TestNoConstructorDispatchEventRule.java  |  59 ++++++
 .../rules/TestNoConstructorReturnTypeRule.java     |  59 ++++++
 .../rules/TestNoDuplicateObjectKeysRule.java       |  59 ++++++
 .../linter/rules/TestNoDynamicClassRule.java       |  59 ++++++
 .../linter/rules/TestNoIfBooleanLiteralRule.java   |  96 +++++++++
 .../linter/rules/TestNoLeadingZeroesRule.java      |  71 +++++++
 .../royale/linter/rules/TestNoSparseArrayRule.java |  71 +++++++
 .../linter/rules/TestNoStringEventNameRule.java    |  73 +++++++
 .../linter/rules/TestNoThisInClosureRule.java      |  59 ++++++
 .../royale/linter/rules/TestNoTraceRule.java}      |  43 ++--
 .../linter/rules/TestNoVoidOperatorRule.java       |  60 ++++++
 .../linter/rules/TestNoWildcardImportRule.java     |  59 ++++++
 .../royale/linter/rules/TestNoWithRule.java}       |  43 ++--
 .../TestOverrideContainsOnlySuperCallRule.java     |  59 ++++++
 .../royale/linter/rules/TestPackageNameRule.java   | 148 ++++++++++++++
 .../linter/rules/TestStaticConstantsRule.java      |  72 +++++++
 .../linter/rules/TestStrictEqualityRule.java       |  84 ++++++++
 .../linter/rules/TestSwitchWithoutDefaultRule.java |  59 ++++++
 .../linter/rules/TestUnsafeNegationRule.java       | 109 ++++++++++
 .../royale/linter/rules/TestValidTypeofRule.java   | 131 ++++++++++++
 .../linter/rules/TestVariablesOnTopRule.java       |  84 ++++++++
 49 files changed, 3630 insertions(+), 156 deletions(-)
 copy {formatter => linter}/src/test/build.xml (64%)
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestClassNameRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestConstantNameRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestEmptyCommentRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestEmptyFunctionBodyRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestEmptyNestedBlockRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestEmptyStatementRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestFieldNameRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestFunctionNameRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestInterfaceNameRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestLineCommentPositionRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarAndParameterNameRule.java
 copy formatter/src/test/java/org/apache/royale/formatter/BaseFormatterTests.java => linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarShadowsFieldRule.java (55%)
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestMXMLIDRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoAnyTypeRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoBooleanEqualityRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorDispatchEventRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorReturnTypeRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoDuplicateObjectKeysRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoDynamicClassRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoIfBooleanLiteralRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoLeadingZeroesRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoSparseArrayRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoStringEventNameRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoThisInClosureRule.java
 copy linter/src/{main/java/org/apache/royale/linter/internal/BaseLinter.java => test/java/org/apache/royale/linter/rules/TestNoTraceRule.java} (57%)
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoVoidOperatorRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestNoWildcardImportRule.java
 copy linter/src/{main/java/org/apache/royale/linter/internal/BaseLinter.java => test/java/org/apache/royale/linter/rules/TestNoWithRule.java} (58%)
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestOverrideContainsOnlySuperCallRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestPackageNameRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestStaticConstantsRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestStrictEqualityRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestSwitchWithoutDefaultRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestUnsafeNegationRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestValidTypeofRule.java
 create mode 100644 linter/src/test/java/org/apache/royale/linter/rules/TestVariablesOnTopRule.java


[royale-compiler] 08/09: linter: more tests

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 8aafd5bfa13e04f4a8f9be0c2da64909bc231c26
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 15:17:53 2022 -0700

    linter: more tests
---
 .../org/apache/royale/linter/rules/NoWithRule.java |   1 -
 .../royale/linter/rules/TestEmptyCommentRule.java  | 110 ++++++++++++++++++++
 .../linter/rules/TestEmptyFunctionBodyRule.java    | 111 +++++++++++++++++++++
 .../linter/rules/TestEmptyNestedBlockRule.java     | 109 ++++++++++++++++++++
 .../linter/rules/TestEmptyStatementRule.java       |  98 ++++++++++++++++++
 .../linter/rules/TestLineCommentPositionRule.java  |  93 +++++++++++++++++
 .../rules/TestLocalVarShadowsFieldRule.java}       |  51 ++++------
 .../royale/linter/rules/TestNoTraceRule.java}      |  51 ++++------
 .../linter/rules/TestNoVoidOperatorRule.java       |  60 +++++++++++
 .../linter/rules/TestNoWildcardImportRule.java     |  59 +++++++++++
 .../royale/linter/rules/TestNoWithRule.java}       |  51 ++++------
 .../TestOverrideContainsOnlySuperCallRule.java     |  59 +++++++++++
 12 files changed, 765 insertions(+), 88 deletions(-)

diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
index 5301d3c1e..dab769e9b 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
@@ -28,7 +28,6 @@ import org.apache.royale.compiler.problems.CompilerProblem;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.TokenVisitor;
 import org.apache.royale.linter.problems.ILinterProblem;
-import org.apache.royale.linter.rules.NoWithRule.NoWithLinterProblem;
 
 /**
  * Checks for uses of 'with(x)'.
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyCommentRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyCommentRule.java
new file mode 100644
index 000000000..282a58b37
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyCommentRule.java
@@ -0,0 +1,110 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestEmptyCommentRule {
+	@Test
+	public void testNonEmptyLineComment() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyCommentRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "// comment", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testEmptyLineComment() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyCommentRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "//", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyCommentRule.EmptyCommentLinterProblem);
+	}
+
+	@Test
+	public void testWhitespaceOnlyLineComment() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyCommentRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "//    ", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyCommentRule.EmptyCommentLinterProblem);
+	}
+
+	@Test
+	public void testNonEmptyBlockComment() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyCommentRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "/* comment */", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testWhitespaceOnlyBlockComment() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyCommentRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "/*    */", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyCommentRule.EmptyCommentLinterProblem);
+	}
+
+	@Test
+	public void testWhitespaceOnlyBlockComment2() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyCommentRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "/*\n\n\n\n*/", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyCommentRule.EmptyCommentLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyFunctionBodyRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyFunctionBodyRule.java
new file mode 100644
index 000000000..3af246345
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyFunctionBodyRule.java
@@ -0,0 +1,111 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestEmptyFunctionBodyRule {
+	@Test
+	public void testNonEmptyFunctionBody() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyFunctionBodyRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testEmptyFunctionBody() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyFunctionBodyRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyFunctionBodyRule.EmptyFunctionBodyLinterProblem);
+	}
+
+	@Test
+	public void testWhitespaceOnlyFunctionBody1() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyFunctionBodyRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void {    }", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyFunctionBodyRule.EmptyFunctionBodyLinterProblem);
+	}
+
+	@Test
+	public void testWhitespaceOnlyFunctionBody2() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyFunctionBodyRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void {\n\n\n\n}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyFunctionBodyRule.EmptyFunctionBodyLinterProblem);
+	}
+
+	@Test
+	public void testCommentOnlyFunctionBody1() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyFunctionBodyRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		// you need to explain why it's empty
+		linter.lint("file.as", "function myFunction():void {/* comment */}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testCommentOnlyFunctionBody2() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyFunctionBodyRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		// you need to explain why it's empty
+		linter.lint("file.as", "function myFunction():void {// comment\n}", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyNestedBlockRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyNestedBlockRule.java
new file mode 100644
index 000000000..8e6a19c30
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyNestedBlockRule.java
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestEmptyNestedBlockRule {
+	@Test
+	public void testNonEmptyNestedBlock() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyNestedBlockRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;if(true){var b:Number = 123.4}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testEmptyNestedBlock() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyNestedBlockRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;if(true){}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyNestedBlockRule.EmptyNestedBlockLinterProblem);
+	}
+
+	@Test
+	public void testEmptyNestedBlockWhitespaceOnly1() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyNestedBlockRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;if(true){    }}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyNestedBlockRule.EmptyNestedBlockLinterProblem);
+	}
+
+	@Test
+	public void testEmptyNestedBlockWhitespaceOnly2() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyNestedBlockRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;if(true){\n\n\n\n}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyNestedBlockRule.EmptyNestedBlockLinterProblem);
+	}
+
+	@Test
+	public void testEmptyNestedBlockCommentOnly1() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyNestedBlockRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;if(true){/* comment */}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testEmptyNestedBlockCommentOnly2() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyNestedBlockRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;if(true){// comment\n}}", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyStatementRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyStatementRule.java
new file mode 100644
index 000000000..889f1eb38
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestEmptyStatementRule.java
@@ -0,0 +1,98 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestEmptyStatementRule {
+	@Test
+	public void testNonEmptyStatement() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyStatementRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a;b;", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testEmptyStatement1() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyStatementRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a;;", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyStatementRule.EmptyStatementLinterProblem);
+	}
+
+	@Test
+	public void testEmptyStatement2() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyStatementRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", ";a;", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyStatementRule.EmptyStatementLinterProblem);
+	}
+
+	@Test
+	public void testEmptyStatementBlock1() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyStatementRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "{a;;}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyStatementRule.EmptyStatementLinterProblem);
+	}
+
+	@Test
+	public void testEmptyStatementBlock2() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new EmptyStatementRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "{;a;}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof EmptyStatementRule.EmptyStatementLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestLineCommentPositionRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestLineCommentPositionRule.java
new file mode 100644
index 000000000..106bf1221
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestLineCommentPositionRule.java
@@ -0,0 +1,93 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.apache.royale.linter.config.LineCommentPosition;
+import org.junit.Test;
+
+public class TestLineCommentPositionRule {
+	@Test
+	public void testBeside() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		LineCommentPositionRule rule = new LineCommentPositionRule();
+		rule.position = LineCommentPosition.BESIDE;
+		rules.add(rule);
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a; // comment", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testNotBeside() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		LineCommentPositionRule rule = new LineCommentPositionRule();
+		rule.position = LineCommentPosition.BESIDE;
+		rules.add(rule);
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "// comment\na;", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LineCommentPositionRule.LineCommentPositionLinterProblem);
+	}
+
+	@Test
+	public void testAbove() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		LineCommentPositionRule rule = new LineCommentPositionRule();
+		rule.position = LineCommentPosition.ABOVE;
+		rules.add(rule);
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "// comment\na;", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testNotAbove() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		LineCommentPositionRule rule = new LineCommentPositionRule();
+		rule.position = LineCommentPosition.ABOVE;
+		rules.add(rule);
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a; // comment", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LineCommentPositionRule.LineCommentPositionLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarShadowsFieldRule.java
similarity index 51%
copy from linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
copy to linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarShadowsFieldRule.java
index 5301d3c1e..697a68dc4 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarShadowsFieldRule.java
@@ -19,36 +19,29 @@
 
 package org.apache.royale.linter.rules;
 
-import java.util.HashMap;
-import java.util.Map;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-import org.apache.royale.compiler.internal.parsing.as.ASTokenTypes;
-import org.apache.royale.compiler.parsing.IASToken;
-import org.apache.royale.compiler.problems.CompilerProblem;
-import org.apache.royale.linter.LinterRule;
-import org.apache.royale.linter.TokenVisitor;
-import org.apache.royale.linter.problems.ILinterProblem;
-import org.apache.royale.linter.rules.NoWithRule.NoWithLinterProblem;
-
-/**
- * Checks for uses of 'with(x)'.
- */
-public class NoWithRule extends LinterRule {
-	@Override
-	public Map<Integer, TokenVisitor> getTokenVisitors() {
-		Map<Integer, TokenVisitor> result = new HashMap<>();
-		result.put(ASTokenTypes.TOKEN_KEYWORD_WITH, (token, tokenQuery, problems) -> {
-			problems.add(new NoWithLinterProblem(token));
-		});
-		return result;
-	}
+import java.util.ArrayList;
+import java.util.List;
 
-	public static class NoWithLinterProblem extends CompilerProblem implements ILinterProblem {
-		public static final String DESCRIPTION = "Must not use 'with' statement";
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
 
-		public NoWithLinterProblem(IASToken token)
-		{
-			super(token);
-		}
+public class TestLocalVarShadowsFieldRule {
+	@Test
+	public void testLocalVarShadowsField() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarShadowsFieldRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{var fieldName:String;function myFunction():void{var fieldName:Number;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarShadowsFieldRule.LocalVarShadowsFieldLinterProblem);
 	}
-}
+}
\ No newline at end of file
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoTraceRule.java
similarity index 51%
copy from linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
copy to linter/src/test/java/org/apache/royale/linter/rules/TestNoTraceRule.java
index 5301d3c1e..c08b4183c 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoTraceRule.java
@@ -19,36 +19,29 @@
 
 package org.apache.royale.linter.rules;
 
-import java.util.HashMap;
-import java.util.Map;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-import org.apache.royale.compiler.internal.parsing.as.ASTokenTypes;
-import org.apache.royale.compiler.parsing.IASToken;
-import org.apache.royale.compiler.problems.CompilerProblem;
-import org.apache.royale.linter.LinterRule;
-import org.apache.royale.linter.TokenVisitor;
-import org.apache.royale.linter.problems.ILinterProblem;
-import org.apache.royale.linter.rules.NoWithRule.NoWithLinterProblem;
-
-/**
- * Checks for uses of 'with(x)'.
- */
-public class NoWithRule extends LinterRule {
-	@Override
-	public Map<Integer, TokenVisitor> getTokenVisitors() {
-		Map<Integer, TokenVisitor> result = new HashMap<>();
-		result.put(ASTokenTypes.TOKEN_KEYWORD_WITH, (token, tokenQuery, problems) -> {
-			problems.add(new NoWithLinterProblem(token));
-		});
-		return result;
-	}
+import java.util.ArrayList;
+import java.util.List;
 
-	public static class NoWithLinterProblem extends CompilerProblem implements ILinterProblem {
-		public static final String DESCRIPTION = "Must not use 'with' statement";
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
 
-		public NoWithLinterProblem(IASToken token)
-		{
-			super(token);
-		}
+public class TestNoTraceRule {
+	@Test
+	public void testTrace() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoTraceRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "trace(a);", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoTraceRule.NoTraceLinterProblem);
 	}
-}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoVoidOperatorRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoVoidOperatorRule.java
new file mode 100644
index 000000000..fe2822b5a
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoVoidOperatorRule.java
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoVoidOperatorRule {
+	@Test
+	public void testVoidOperator() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoVoidOperatorRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "void a;", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoVoidOperatorRule.NoVoidOperatorLinterProblem);
+	}
+
+	@Test
+	public void testVoidOperatorCall() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoVoidOperatorRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "void(a);", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoVoidOperatorRule.NoVoidOperatorLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoWildcardImportRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoWildcardImportRule.java
new file mode 100644
index 000000000..cb8597c1f
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoWildcardImportRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoWildcardImportRule {
+	@Test
+	public void testWildcardImport() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoWildcardImportRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "import a.b.c.*;", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoWildcardImportRule.NoWildcardImportLinterProblem);
+	}
+
+	@Test
+	public void testNonWildcardImport() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoWildcardImportRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "import a.b.c.d;", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoWithRule.java
similarity index 51%
copy from linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
copy to linter/src/test/java/org/apache/royale/linter/rules/TestNoWithRule.java
index 5301d3c1e..6d46dd327 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoWithRule.java
@@ -19,36 +19,29 @@
 
 package org.apache.royale.linter.rules;
 
-import java.util.HashMap;
-import java.util.Map;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-import org.apache.royale.compiler.internal.parsing.as.ASTokenTypes;
-import org.apache.royale.compiler.parsing.IASToken;
-import org.apache.royale.compiler.problems.CompilerProblem;
-import org.apache.royale.linter.LinterRule;
-import org.apache.royale.linter.TokenVisitor;
-import org.apache.royale.linter.problems.ILinterProblem;
-import org.apache.royale.linter.rules.NoWithRule.NoWithLinterProblem;
-
-/**
- * Checks for uses of 'with(x)'.
- */
-public class NoWithRule extends LinterRule {
-	@Override
-	public Map<Integer, TokenVisitor> getTokenVisitors() {
-		Map<Integer, TokenVisitor> result = new HashMap<>();
-		result.put(ASTokenTypes.TOKEN_KEYWORD_WITH, (token, tokenQuery, problems) -> {
-			problems.add(new NoWithLinterProblem(token));
-		});
-		return result;
-	}
+import java.util.ArrayList;
+import java.util.List;
 
-	public static class NoWithLinterProblem extends CompilerProblem implements ILinterProblem {
-		public static final String DESCRIPTION = "Must not use 'with' statement";
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
 
-		public NoWithLinterProblem(IASToken token)
-		{
-			super(token);
-		}
+public class TestNoWithRule {
+	@Test
+	public void testWith() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoWithRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "with(a){}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoWithRule.NoWithLinterProblem);
 	}
-}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestOverrideContainsOnlySuperCallRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestOverrideContainsOnlySuperCallRule.java
new file mode 100644
index 000000000..1911a4ab1
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestOverrideContainsOnlySuperCallRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestOverrideContainsOnlySuperCallRule {
+	@Test
+	public void testOverrideContainsOnlySuperCall() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new OverrideContainsOnlySuperCallRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{override function myFunction():void{super.myFunction();}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof OverrideContainsOnlySuperCallRule.OverrideContainsOnlySuperCallLinterProblem);
+	}
+
+	@Test
+	public void testOverrideContainsOtherSuperCall() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new OverrideContainsOnlySuperCallRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{override function myFunction():void{super.anotherFunction();}}", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file


[royale-compiler] 03/09: SwitchNode: fix getDefaultNode() failing to get default node from inside an IBlockNode

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit ced2dde291e5e578ab357ac7d4176ff145238f3c
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 14:20:29 2022 -0700

    SwitchNode: fix getDefaultNode() failing to get default node from inside an IBlockNode
---
 .../java/org/apache/royale/compiler/utils/ASNodeUtils.java  |  1 -
 .../apache/royale/compiler/internal/tree/as/SwitchNode.java | 13 +++++++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/ASNodeUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/ASNodeUtils.java
index b2ea9a64c..ea3ec09cf 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/ASNodeUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/ASNodeUtils.java
@@ -51,7 +51,6 @@ public class ASNodeUtils
         return retVal.toArray(new IConditionalNode[0]);
     }
 
-    // there seems to be a bug in the ISwitchNode.getDefaultNode(), need to file a bug
     public static final ITerminalNode getDefaultNode(ISwitchNode node)
     {
         IBlockNode block = (IBlockNode) node.getChild(1);
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/SwitchNode.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/SwitchNode.java
index daf21ea2f..226146c88 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/SwitchNode.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/SwitchNode.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import org.apache.royale.compiler.parsing.IASToken;
 import org.apache.royale.compiler.tree.ASTNodeID;
 import org.apache.royale.compiler.tree.as.IASNode;
+import org.apache.royale.compiler.tree.as.IBlockNode;
 import org.apache.royale.compiler.tree.as.IConditionalNode;
 import org.apache.royale.compiler.tree.as.IExpressionNode;
 import org.apache.royale.compiler.tree.as.ISwitchNode;
@@ -94,12 +95,20 @@ public class SwitchNode extends ConditionalNode implements ISwitchNode
     @Override
     public ITerminalNode getDefaultNode()
     {
-        int childCount = getChildCount();
+        IASNode possibleBlock = getChild(1);
+        if (!(possibleBlock instanceof IBlockNode))
+        {
+            return null;
+        }
+        IBlockNode blockNode = (IBlockNode) possibleBlock;
+        int childCount = blockNode.getChildCount();
         for (int i = childCount - 1; i >= 0; i--)
         {
-            IASNode child = getChild(i);
+            IASNode child = blockNode.getChild(i);
             if (child instanceof ITerminalNode)
+            {
                 return (ITerminalNode)child;
+            }
         }
         
         return null;


[royale-compiler] 05/09: linter: EmptyStatementRule should handle block open before semicolon

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 2b5660010d4e88a4bc16c7016f0f626ff340748c
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 14:50:46 2022 -0700

    linter: EmptyStatementRule should handle block open before semicolon
---
 .../apache/royale/linter/rules/EmptyStatementRule.java    | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java b/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java
index a6c63b0cc..6308be5b7 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java
@@ -48,14 +48,13 @@ public class EmptyStatementRule extends LinterRule {
 
 	private void checkSemicolon(IASToken semicolon, TokenQuery tokenQuery, Collection<ICompilerProblem> problems) {
 		IASToken prevToken = tokenQuery.getSignificantTokenBefore(semicolon);
-		if (prevToken == null) {
-			return;
-		}
-		if (prevToken.getType() != ASTokenTypes.TOKEN_SEMICOLON) {
-			return;
-		}
-		if (prevToken.isImplicit()) {
-			return;
+		if (prevToken != null) {
+			if (prevToken.getType() != ASTokenTypes.TOKEN_SEMICOLON && prevToken.getType() != ASTokenTypes.TOKEN_BLOCK_OPEN) {
+				return;
+			}
+			if (prevToken.isImplicit()) {
+				return;
+			}
 		}
 		problems.add(new EmptyStatementLinterProblem(semicolon));
 	}


[royale-compiler] 09/09: linter: more tests

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit f04e9788b5ab9201d9c7f3bf4848d110d92167fc
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 15:48:30 2022 -0700

    linter: more tests
---
 .../royale/linter/rules/TestNoAnyTypeRule.java     | 109 +++++++++++++++++++++
 .../linter/rules/TestNoBooleanEqualityRule.java    |  98 ++++++++++++++++++
 .../rules/TestNoConstructorDispatchEventRule.java  |  59 +++++++++++
 .../rules/TestNoConstructorReturnTypeRule.java     |  59 +++++++++++
 .../rules/TestNoDuplicateObjectKeysRule.java       |  59 +++++++++++
 .../linter/rules/TestNoDynamicClassRule.java       |  59 +++++++++++
 .../linter/rules/TestNoIfBooleanLiteralRule.java   |  96 ++++++++++++++++++
 .../linter/rules/TestNoLeadingZeroesRule.java      |  71 ++++++++++++++
 .../royale/linter/rules/TestNoSparseArrayRule.java |  71 ++++++++++++++
 .../linter/rules/TestNoStringEventNameRule.java    |  73 ++++++++++++++
 .../linter/rules/TestNoThisInClosureRule.java      |  59 +++++++++++
 11 files changed, 813 insertions(+)

diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoAnyTypeRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoAnyTypeRule.java
new file mode 100644
index 000000000..e14d7da05
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoAnyTypeRule.java
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoAnyTypeRule {
+	@Test
+	public void testVariableWithoutAnyType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoAnyTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Object;", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testVariableWithAnyType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoAnyTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:*;", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoAnyTypeRule.NoAnyTypeOnVariableLinterProblem);
+	}
+
+	@Test
+	public void testParameterWithoutAnyType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoAnyTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction(a:Object):void {}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testParameterWithAnyType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoAnyTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction(a:*):void {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoAnyTypeRule.NoAnyTypeOnParameterLinterProblem);
+	}
+
+	@Test
+	public void testReturnWithoutAnyType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoAnyTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():Object{return null;}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testReturnWithAnyType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoAnyTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():*{return null;}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoAnyTypeRule.NoAnyTypeReturnLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoBooleanEqualityRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoBooleanEqualityRule.java
new file mode 100644
index 000000000..0f610f49c
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoBooleanEqualityRule.java
@@ -0,0 +1,98 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoBooleanEqualityRule {
+	@Test
+	public void testWithoutBooleanEquality() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoBooleanEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(a){}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testWithLooseEqualsTrue() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoBooleanEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(a==true){}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoBooleanEqualityRule.NoBooleanEqualityLinterProblem);
+	}
+
+	@Test
+	public void testWithLooseNotEqualsTrue() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoBooleanEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(a!=true){}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoBooleanEqualityRule.NoBooleanEqualityLinterProblem);
+	}
+
+	@Test
+	public void testWithLooseEqualsFalse() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoBooleanEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(a==false){}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoBooleanEqualityRule.NoBooleanEqualityLinterProblem);
+	}
+
+	@Test
+	public void testWithLooseNotEqualsFalse() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoBooleanEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(a!=false){}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoBooleanEqualityRule.NoBooleanEqualityLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorDispatchEventRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorDispatchEventRule.java
new file mode 100644
index 000000000..55b2bf06d
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorDispatchEventRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoConstructorDispatchEventRule {
+	@Test
+	public void testWithoutDispatchEvent() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoConstructorDispatchEventRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{function MyClass(){}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testWithDispatchEvent() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoConstructorDispatchEventRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{function MyClass():void{dispatchEvent(new Event(\"change\"));}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoConstructorDispatchEventRule.NoConstructorDispatchEventLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorReturnTypeRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorReturnTypeRule.java
new file mode 100644
index 000000000..233d3e0a1
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoConstructorReturnTypeRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoConstructorReturnTypeRule {
+	@Test
+	public void testWithoutReturnType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoConstructorReturnTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{function MyClass(){}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testWithReturnType() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoConstructorReturnTypeRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{function MyClass():void{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoConstructorReturnTypeRule.NoConstructorReturnTypeLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoDuplicateObjectKeysRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoDuplicateObjectKeysRule.java
new file mode 100644
index 000000000..12e0e0945
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoDuplicateObjectKeysRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoDuplicateObjectKeysRule {
+	@Test
+	public void testWithoutDuplicates() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoDuplicateObjectKeysRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Object = {a: 1, b: 2};", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testWithDuplicates() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoDuplicateObjectKeysRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Object = {a: 1, b: 2, a: 3};", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoDuplicateObjectKeysRule.NoDuplicateObjectKeysLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoDynamicClassRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoDynamicClassRule.java
new file mode 100644
index 000000000..a14ee0455
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoDynamicClassRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoDynamicClassRule {
+	@Test
+	public void testWithoutDynamic() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoDynamicClassRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass {}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testWithDynamic() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoDynamicClassRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "dynamic class MyClass {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoDynamicClassRule.NoDynamicClassLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoIfBooleanLiteralRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoIfBooleanLiteralRule.java
new file mode 100644
index 000000000..08b545c52
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoIfBooleanLiteralRule.java
@@ -0,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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoIfBooleanLiteralRule {
+	@Test
+	public void testIfIdentifier() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoIfBooleanLiteralRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(a){}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testIfUndefined() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoIfBooleanLiteralRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(undefined){}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testIfNull() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoIfBooleanLiteralRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(null){}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testIfTrue() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoIfBooleanLiteralRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(true){}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoIfBooleanLiteralRule.NoIfBooleanLiteralLinterProblem);
+	}
+
+	@Test
+	public void testIfFalse() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoIfBooleanLiteralRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "if(false){}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoIfBooleanLiteralRule.NoIfBooleanLiteralLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoLeadingZeroesRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoLeadingZeroesRule.java
new file mode 100644
index 000000000..dca8c46d4
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoLeadingZeroesRule.java
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoLeadingZeroesRule {
+	@Test
+	public void testNoLeadingZeroes() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoLeadingZeroesRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Number = 123.4", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testLeadingZeroes() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoLeadingZeroesRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Number = 0123", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoLeadingZeroesRule.NoLeadingZeroesLinterProblem);
+	}
+
+	@Test
+	public void testHexadecimal() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoLeadingZeroesRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Number = 0x1234", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoSparseArrayRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoSparseArrayRule.java
new file mode 100644
index 000000000..8b8701246
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoSparseArrayRule.java
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoSparseArrayRule {
+	@Test
+	public void testNonSparseArray() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoSparseArrayRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Array = [a, b, c]", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testEmptyArray() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoSparseArrayRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Array = []", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testSparseArray() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoSparseArrayRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "var a:Array = [a,,c]", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoSparseArrayRule.NoSparseArrayLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoStringEventNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoStringEventNameRule.java
new file mode 100644
index 000000000..a47f2eedc
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoStringEventNameRule.java
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoStringEventNameRule {
+	@Test
+	public void testAddEventListenerStringEventName() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoStringEventNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "addEventListener(\"change\", listener)", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoStringEventNameRule.NoStringEventNameLinterProblem);
+	}
+
+	@Test
+	public void testRemoveEventListenerStringEventName() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoStringEventNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "removeEventListener(\"change\", listener)", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoStringEventNameRule.NoStringEventNameLinterProblem);
+	}
+
+	@Test
+	public void testHasEventListenerStringEventName() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoStringEventNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "hasEventListener(\"change\", listener)", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoStringEventNameRule.NoStringEventNameLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestNoThisInClosureRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestNoThisInClosureRule.java
new file mode 100644
index 000000000..58a8d926c
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestNoThisInClosureRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestNoThisInClosureRule {
+	@Test
+	public void testThisInClosure() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoThisInClosureRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{function myClosure():void{this;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof NoThisInClosureRule.NoThisInClosureLinterProblem);
+	}
+
+	@Test
+	public void testThisInMethod() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new NoThisInClosureRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{function myMethod():void{this;}}", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file


[royale-compiler] 06/09: linter: fix null results that should have been a token in TokenQuery classes

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit f084dfaf171904c71bd1c88fc4746756809e121b
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 15:07:39 2022 -0700

    linter: fix null results that should have been a token in TokenQuery classes
---
 linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java | 6 +++---
 linter/src/main/java/org/apache/royale/linter/TokenQuery.java     | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java b/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java
index 66eec2b97..cc8f6cf37 100644
--- a/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java
+++ b/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java
@@ -63,7 +63,7 @@ public class MXMLTokenQuery {
 			}
 			result = token;
 		}
-		return null;
+		return result;
 	}
 
 	/**
@@ -113,7 +113,7 @@ public class MXMLTokenQuery {
 				result = token;
 			}
 		}
-		return null;
+		return result;
 	}
 
 	/**
@@ -150,7 +150,7 @@ public class MXMLTokenQuery {
 				result = token;
 			}
 		}
-		return null;
+		return result;
 	}
 
 	/**
diff --git a/linter/src/main/java/org/apache/royale/linter/TokenQuery.java b/linter/src/main/java/org/apache/royale/linter/TokenQuery.java
index b6c1089f4..798e49d0d 100644
--- a/linter/src/main/java/org/apache/royale/linter/TokenQuery.java
+++ b/linter/src/main/java/org/apache/royale/linter/TokenQuery.java
@@ -100,7 +100,7 @@ public class TokenQuery {
 			}
 			result = token;
 		}
-		return null;
+		return result;
 	}
 
 	/**
@@ -201,7 +201,7 @@ public class TokenQuery {
 				result = token;
 			}
 		}
-		return null;
+		return result;
 	}
 
 	/**
@@ -255,7 +255,7 @@ public class TokenQuery {
 				result = token;
 			}
 		}
-		return null;
+		return result;
 	}
 
 	/**
@@ -292,7 +292,7 @@ public class TokenQuery {
 				result = token;
 			}
 		}
-		return null;
+		return result;
 	}
 
 	/**


[royale-compiler] 07/09: linter: LineCommentPositionRule fixes

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 4dafdbcef3fec05a2000c564cf881ec20045e412
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 15:08:03 2022 -0700

    linter: LineCommentPositionRule fixes
---
 .../royale/linter/rules/LineCommentPositionRule.java       | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java b/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java
index 28d5e193b..04b448f16 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java
@@ -51,18 +51,20 @@ public class LineCommentPositionRule extends LinterRule {
 
 	private void checkSingleLineComment(IASToken comment, TokenQuery tokenQuery, Collection<ICompilerProblem> problems) {
 		IASToken prevToken = tokenQuery.getSignificantTokenBefore(comment);
-		if (prevToken == null) {
-			return;
-		}
 		if (LineCommentPosition.ABOVE.equals(position)) {
+			if (prevToken == null) {
+				return;
+			}
 			if (prevToken.getLine() == comment.getLine()) {
-				// is beside the comment
+				// the comment is on the same line as a significant token
+				// (the comment should be on its own line)
 				problems.add(new LineCommentPositionLinterProblem(comment, position));
 			}
 		}
 		else if (LineCommentPosition.BESIDE.equals(position)) {
-			if (prevToken.getLine() != comment.getLine()) {
-				// is not beside the comment
+			if (prevToken == null || prevToken.getLine() != comment.getLine()) {
+				// the comment is not on the same line as a significant token
+				// it should not be on its own line
 				problems.add(new LineCommentPositionLinterProblem(comment, position));
 			}
 		}


[royale-compiler] 04/09: linter: more tests

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 3fd41ac496d672450a1728a55fd9ef670cd361e2
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 14:24:41 2022 -0700

    linter: more tests
---
 .../royale/linter/rules/StrictEqualityRule.java    |   1 -
 .../linter/rules/TestStaticConstantsRule.java      |  72 +++++++++++
 .../linter/rules/TestStrictEqualityRule.java       |  84 +++++++++++++
 .../linter/rules/TestSwitchWithoutDefaultRule.java |  59 ++++++++++
 .../linter/rules/TestUnsafeNegationRule.java       | 109 +++++++++++++++++
 .../royale/linter/rules/TestValidTypeofRule.java   | 131 +++++++++++++++++++++
 .../linter/rules/TestVariablesOnTopRule.java       |  84 +++++++++++++
 7 files changed, 539 insertions(+), 1 deletion(-)

diff --git a/linter/src/main/java/org/apache/royale/linter/rules/StrictEqualityRule.java b/linter/src/main/java/org/apache/royale/linter/rules/StrictEqualityRule.java
index 4ba214e8a..89645c0ad 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/StrictEqualityRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/StrictEqualityRule.java
@@ -29,7 +29,6 @@ import org.apache.royale.compiler.tree.as.IOperatorNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.TokenVisitor;
 import org.apache.royale.linter.problems.ILinterProblem;
-import org.apache.royale.linter.rules.StrictEqualityRule.StrictEqualityLinterProblem;
 
 /**
  * Checks for uses of the '==' and '!='' operators instead of the stricter '==='
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestStaticConstantsRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestStaticConstantsRule.java
new file mode 100644
index 000000000..ad4476360
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestStaticConstantsRule.java
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestStaticConstantsRule {
+	@Test
+	public void testStaticConstant() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StaticConstantsRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{static const HELLO:String = \"hello\";}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testFieldConstant() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StaticConstantsRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "class MyClass{const HELLO:String = \"hello\";}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof StaticConstantsRule.StaticConstantsLinterProblem);
+	}
+
+	@Test
+	public void testLocalConstant() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StaticConstantsRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		// this rule tests only class members, and not locals
+		linter.lint("file.as", "class MyClass{function myMethod():void{const HELLO:String = \"hello\";}}", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestStrictEqualityRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestStrictEqualityRule.java
new file mode 100644
index 000000000..04aacde4d
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestStrictEqualityRule.java
@@ -0,0 +1,84 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestStrictEqualityRule {
+	@Test
+	public void testStrictEquality() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StrictEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a === b", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testStrictInquality() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StrictEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a !== b", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testLooseEquality() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StrictEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a == b", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof StrictEqualityRule.StrictEqualityLinterProblem);
+	}
+
+	@Test
+	public void testLooseInquality() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StrictEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "a != b", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof StrictEqualityRule.StrictEqualityLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestSwitchWithoutDefaultRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestSwitchWithoutDefaultRule.java
new file mode 100644
index 000000000..f23cf9fc7
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestSwitchWithoutDefaultRule.java
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestSwitchWithoutDefaultRule {
+	@Test
+	public void testSwitchWithoutDefault() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new SwitchWithoutDefaultRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "switch(a) {case 1:break;}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof SwitchWithoutDefaultRule.SwitchWithoutDefaultLinterProblem);
+	}
+
+	@Test
+	public void testSwitchWithDefault() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new SwitchWithoutDefaultRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "switch(a) {case 1:break;default:}", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestUnsafeNegationRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestUnsafeNegationRule.java
new file mode 100644
index 000000000..960b7927a
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestUnsafeNegationRule.java
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestUnsafeNegationRule {
+	@Test
+	public void testUnsafeNegationIn() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new UnsafeNegationRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "!a in b", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof UnsafeNegationRule.UnsafeNegationLinterProblem);
+	}
+
+	@Test
+	public void testUnsafeNegationIs() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new UnsafeNegationRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "!a is b", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof UnsafeNegationRule.UnsafeNegationLinterProblem);
+	}
+
+	@Test
+	public void testUnsafeNegationInstanceOf() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new UnsafeNegationRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "!a instanceof b", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof UnsafeNegationRule.UnsafeNegationLinterProblem);
+	}
+
+	@Test
+	public void testSafeNegationIn() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StrictEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "!(a in b)", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testSafeNegationIs() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StrictEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "!(a is b)", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testSafeNegationInstanceOf() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new StrictEqualityRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "!(a instanceof b)", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestValidTypeofRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestValidTypeofRule.java
new file mode 100644
index 000000000..c95c4527c
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestValidTypeofRule.java
@@ -0,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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestValidTypeofRule {
+	@Test
+	public void testInvalidTypeof() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"other\"", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ValidTypeofRule.ValidTypeofLinterProblem);
+	}
+
+	@Test
+	public void testValidTypeofBoolean() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"boolean\"", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testValidTypeofFunction() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"function\"", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testValidTypeofNumber() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"number\"", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testValidTypeofObject() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"object\"", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testValidTypeofString() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"string\"", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testValidTypeofXml() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"xml\"", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testValidTypeofUndefined() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ValidTypeofRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "typeof a == \"undefined\"", problems);
+		assertEquals(0, problems.size());
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestVariablesOnTopRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestVariablesOnTopRule.java
new file mode 100644
index 000000000..2227d3b33
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestVariablesOnTopRule.java
@@ -0,0 +1,84 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestVariablesOnTopRule {
+	@Test
+	public void testOneVariableOnTop() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new VariablesOnTopRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;while(true){}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testMultipleVariablesOnTop() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new VariablesOnTopRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;var b:Number = 123.4;while(true){}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testVariableNotOnTop() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new VariablesOnTopRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{while(true){}var a:String = null;}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof VariablesOnTopRule.VariablesOnTopLinterProblem);
+	}
+
+	@Test
+	public void testVariableOnTopAndVariableNotOnTop() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new VariablesOnTopRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "function myFunction():void{var a:String = null;while(true){}var b:Number = 123.4;}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof VariablesOnTopRule.VariablesOnTopLinterProblem);
+	}
+}
\ No newline at end of file


[royale-compiler] 02/09: linter: add formatting/whitespace tokens to TokenQuery to support formatting rules

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 58fb870f87d2d451a709e41f50cd43d009752d08
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 13:41:39 2022 -0700

    linter: add formatting/whitespace tokens to TokenQuery to support formatting rules
---
 .../java/org/apache/royale/linter/ASLinter.java    |  52 ++++++-
 .../java/org/apache/royale/linter/MXMLLinter.java  |  37 ++++-
 .../org/apache/royale/linter/MXMLTokenQuery.java   | 117 ++++++++++++--
 .../java/org/apache/royale/linter/TokenQuery.java  | 173 ++++++++++++++++++---
 .../royale/linter/rules/EmptyStatementRule.java    |   2 +-
 .../linter/rules/LineCommentPositionRule.java      |   4 +-
 .../royale/linter/rules/MissingASDocRule.java      |   2 +-
 7 files changed, 341 insertions(+), 46 deletions(-)

diff --git a/linter/src/main/java/org/apache/royale/linter/ASLinter.java b/linter/src/main/java/org/apache/royale/linter/ASLinter.java
index 2f1761658..f4e293029 100644
--- a/linter/src/main/java/org/apache/royale/linter/ASLinter.java
+++ b/linter/src/main/java/org/apache/royale/linter/ASLinter.java
@@ -142,6 +142,8 @@ public class ASLinter extends BaseLinter {
 			// of the repaired tokens, so add them all at the end
 			repairedTokensList.addAll(comments);
 
+			repairedTokensList = insertWhitespaceTokens(repairedTokensList, text);
+
 			IASToken[] allTokens = repairedTokensList.toArray(new IASToken[0]);
 			TokenQuery tokenQuery = new TokenQuery(allTokens);
 			visitNode(node, tokenQuery, fileProblems);
@@ -179,7 +181,7 @@ public class ASLinter extends BaseLinter {
 
 	private void visitNode(IASNode node, TokenQuery tokenQuery, Collection<ICompilerProblem> problems) {
 		ASTNodeID nodeID = node.getNodeID();
-		IASToken prevComment = tokenQuery.getPreviousComment(node);
+		IASToken prevComment = tokenQuery.getCommentBefore(node);
 		boolean linterOn = true;
 		while (prevComment != null) {
 			String commentText = null;
@@ -190,7 +192,7 @@ public class ASLinter extends BaseLinter {
 				commentText = commentText.substring(2, commentText.length() - 2).trim();
 			} else {
 				// not the type of comment that we care about
-				prevComment = tokenQuery.getPreviousComment(prevComment);
+				prevComment = tokenQuery.getCommentBefore(prevComment);
 				continue;
 			}
 			if (LINTER_TAG_ON.equals(commentText)) {
@@ -201,7 +203,7 @@ public class ASLinter extends BaseLinter {
 				linterOn = false;
 				break;
 			}
-			prevComment = tokenQuery.getPreviousComment(prevComment);
+			prevComment = tokenQuery.getCommentBefore(prevComment);
 		}
 		if (linterOn) {
 			for (LinterRule rule : settings.rules) {
@@ -216,4 +218,48 @@ public class ASLinter extends BaseLinter {
 			visitNode(child, tokenQuery, problems);
 		}
 	}
+
+	private List<IASToken> insertWhitespaceTokens(List<IASToken> originalTokens, String text) {
+		ArrayList<IASToken> tokens = new ArrayList<IASToken>();
+		IASToken prevToken = null;
+		for (IASToken token : originalTokens) {
+			if (prevToken != null) {
+
+				boolean skipSemicolon = token.getType() == ASTokenTypes.TOKEN_SEMICOLON && token.isImplicit()
+						&& prevToken != null && (prevToken.getType() == ASTokenTypes.HIDDEN_TOKEN_SINGLE_LINE_COMMENT
+								|| prevToken.getType() == ASTokenTypes.TOKEN_BLOCK_OPEN);
+				if (skipSemicolon) {
+					continue;
+				}
+
+				int start = prevToken.getAbsoluteEnd();
+				int end = token.getAbsoluteStart();
+				if (end > start) {
+					String tokenText = text.substring(start, end);
+					ASToken whitespaceToken = new ASToken(TokenQuery.TOKEN_TYPE_WHITESPACE, start, end,
+							prevToken.getEndLine(),
+							prevToken.getEndColumn(), tokenText);
+					whitespaceToken.setEndLine(token.getLine());
+					whitespaceToken.setEndLine(token.getColumn());
+					tokens.add(whitespaceToken);
+				}
+			}
+			tokens.add(token);
+			prevToken = token;
+		}
+		if (prevToken != null) {
+			int start = prevToken.getAbsoluteEnd();
+			int end = text.length();
+			if (end > start) {
+				String tokenText = text.substring(start, end);
+				ASToken whitespaceToken = new ASToken(TokenQuery.TOKEN_TYPE_WHITESPACE, start, end,
+						prevToken.getEndLine(),
+						prevToken.getEndColumn(), tokenText);
+				whitespaceToken.setEndLine(prevToken.getLine());
+				whitespaceToken.setEndLine(prevToken.getColumn());
+				tokens.add(whitespaceToken);
+			}
+		}
+		return tokens;
+	}
 }
diff --git a/linter/src/main/java/org/apache/royale/linter/MXMLLinter.java b/linter/src/main/java/org/apache/royale/linter/MXMLLinter.java
index 5f4784a6b..bd5662755 100644
--- a/linter/src/main/java/org/apache/royale/linter/MXMLLinter.java
+++ b/linter/src/main/java/org/apache/royale/linter/MXMLLinter.java
@@ -71,8 +71,9 @@ public class MXMLLinter extends BaseLinter {
 			if (!settings.ignoreProblems && hasErrors(fileProblems)) {
 				return;
 			}
+
 			boolean skipLinting = false;
-			IMXMLToken[] allTokens = originalTokens.toArray(new IMXMLToken[0]);
+			IMXMLToken[] allTokens = insertFormattingTokens(originalTokens, text);
 			MXMLTokenQuery tokenQuery = new MXMLTokenQuery(allTokens);
 			for (LinterRule rule : settings.rules) {
 				Map<MXMLTokenKind, MXMLTokenVisitor> tokenHandlers = rule.getMXMLTokenVisitors();
@@ -179,4 +180,38 @@ public class MXMLLinter extends BaseLinter {
 			current = current.getNextSibling(true);
 		}
 	}
+
+	private IMXMLToken[] insertFormattingTokens(List<MXMLToken> originalTokens, String text) {
+		ArrayList<IMXMLToken> tokens = new ArrayList<IMXMLToken>();
+		IMXMLToken prevToken = null;
+		for (IMXMLToken token : originalTokens) {
+			if (prevToken != null) {
+				int start = prevToken.getEnd();
+				int end = token.getStart();
+				if (end > start) {
+					String tokenText = text.substring(start, end);
+					MXMLToken formattingToken = new MXMLToken(MXMLTokenQuery.TOKEN_TYPE_FORMATTING, start, end,
+							prevToken.getLine(), prevToken.getColumn() + end - start, tokenText);
+							formattingToken.setEndLine(token.getLine());
+							formattingToken.setEndLine(token.getColumn());
+					tokens.add(formattingToken);
+				}
+			}
+			tokens.add(token);
+			prevToken = token;
+		}
+		if (prevToken != null) {
+			int start = prevToken.getEnd();
+			int end = text.length();
+			if (end > start) {
+				String tokenText = text.substring(start, end);
+				MXMLToken formattingToken = new MXMLToken(MXMLTokenQuery.TOKEN_TYPE_FORMATTING, start, end,
+						prevToken.getLine(), prevToken.getColumn() + end - start, tokenText);
+					formattingToken.setEndLine(prevToken.getLine());
+					formattingToken.setEndLine(prevToken.getColumn());
+				tokens.add(formattingToken);
+			}
+		}
+		return tokens.toArray(new IMXMLToken[0]);
+	}
 }
diff --git a/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java b/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java
index 82fb83043..66eec2b97 100644
--- a/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java
+++ b/linter/src/main/java/org/apache/royale/linter/MXMLTokenQuery.java
@@ -19,12 +19,12 @@
 
 package org.apache.royale.linter;
 
-import java.util.List;
-
 import org.apache.royale.compiler.common.ISourceLocation;
 import org.apache.royale.compiler.parsing.IMXMLToken;
 
 public class MXMLTokenQuery {
+	public static final int TOKEN_TYPE_FORMATTING = 999999;
+
 	public MXMLTokenQuery(IMXMLToken[] tokens) {
 		allTokens = tokens;
 	}
@@ -42,23 +42,26 @@ public class MXMLTokenQuery {
 	 * Returns the token immediately before a source location.
 	 */
 	public IMXMLToken getTokenBefore(ISourceLocation sourceLocation) {
-		return getTokenBefore(sourceLocation, false);
+		return getTokenBefore(sourceLocation, false, false);
 	}
 
 	/**
 	 * Returns the token immediately before a source location, with the option
-	 * to skip comment tokens.
+	 * to skip comment and formatting tokens.
 	 */
-	public IMXMLToken getTokenBefore(ISourceLocation sourceLocation, boolean skipComments) {
+	public IMXMLToken getTokenBefore(ISourceLocation sourceLocation, boolean skipComments, boolean skipFormatting) {
 		IMXMLToken result = null;
-		for (IMXMLToken otherToken : allTokens) {
-			if (skipComments && isComment(otherToken)) {
+		for (IMXMLToken token : allTokens) {
+			if (skipComments && isComment(token)) {
 				continue;
 			}
-			if (otherToken.getStart() >= sourceLocation.getAbsoluteStart()) {
+			if (skipFormatting && isFormatting(token)) {
+				continue;
+			}
+			if (token.getStart() >= sourceLocation.getAbsoluteStart()) {
 				return result;
 			}
-			result = otherToken;
+			result = token;
 		}
 		return null;
 	}
@@ -67,19 +70,22 @@ public class MXMLTokenQuery {
 	 * Returns the token immediately after a source location.
 	 */
 	public IMXMLToken getTokenAfter(ISourceLocation sourceLocation) {
-		return getTokenAfter(sourceLocation, false);
+		return getTokenAfter(sourceLocation, false, false);
 	}
 
 	/**
 	 * Returns the token immediately after a source location, with the option to
 	 * skip comment tokens.
 	 */
-	public IMXMLToken getTokenAfter(ISourceLocation sourceLocation, boolean skipComments) {
+	public IMXMLToken getTokenAfter(ISourceLocation sourceLocation, boolean skipComments, boolean skipFormatting) {
 		for (IMXMLToken token : allTokens) {
-			if (skipComments && isComment(token)) {
-				continue;
-			}
 			if (token.getStart() >= sourceLocation.getAbsoluteEnd()) {
+				if (skipComments && isComment(token)) {
+					continue;
+				}
+				if (skipFormatting && isFormatting(token)) {
+					continue;
+				}
 				return token;
 			}
 		}
@@ -92,5 +98,88 @@ public class MXMLTokenQuery {
 	public boolean isComment(IMXMLToken token) {
 		return token.getMXMLTokenKind() == IMXMLToken.MXMLTokenKind.COMMENT;
 	}
+
+	/**
+	 * Returns the first comment that appears before the start of a particular
+	 * source location.
+	 */
+	public IMXMLToken getCommentBefore(ISourceLocation before) {
+		IMXMLToken result = null;
+		for (IMXMLToken token : allTokens) {
+			if (token.getStart() >= before.getAbsoluteStart()) {
+				return result;
+			}
+			if (isComment(token)) {
+				result = token;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the first comment that appears after the end of a particular
+	 * source location.
+	 */
+	public IMXMLToken getCommentAfter(ISourceLocation after) {
+		for (IMXMLToken token : allTokens) {
+			if (token.getStart() >= after.getAbsoluteEnd() && isComment(token)) {
+				return token;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Checks if a token is formatting.
+	 */
+	public boolean isFormatting(IMXMLToken token) {
+		return token.getType() == TOKEN_TYPE_FORMATTING;
+	}
+
+	/**
+	 * Returns the first formatting token that appears before the start of a
+	 * particular source location.
+	 */
+	public IMXMLToken getFormattingBefore(ISourceLocation before) {
+		IMXMLToken result = null;
+		for (IMXMLToken token : allTokens) {
+			if (token.getStart() >= before.getAbsoluteStart()) {
+				return result;
+			}
+			if (isFormatting(token)) {
+				result = token;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the first formatting token that appears after the end of a
+	 * particular source location.
+	 */
+	public IMXMLToken getFormattingAfter(ISourceLocation after) {
+		for (IMXMLToken token : allTokens) {
+			if (token.getStart() >= after.getAbsoluteEnd() && isFormatting(token)) {
+				return token;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the first non-comment, non-formatting token that appears before
+	 * the start of a particular source location.
+	 */
+	public IMXMLToken getSignificantTokenBefore(ISourceLocation before) {
+		return getTokenBefore(before, true, true);
+	}
+
+	/**
+	 * Returns the first non-comment, non-formatting token that appears after
+	 * the end of a particular source location.
+	 */
+	public IMXMLToken getSignificantTokenAfter(ISourceLocation after) {
+		return getTokenAfter(after, true, true);
+	}
 	
 }
diff --git a/linter/src/main/java/org/apache/royale/linter/TokenQuery.java b/linter/src/main/java/org/apache/royale/linter/TokenQuery.java
index 99b69c621..b6c1089f4 100644
--- a/linter/src/main/java/org/apache/royale/linter/TokenQuery.java
+++ b/linter/src/main/java/org/apache/royale/linter/TokenQuery.java
@@ -28,6 +28,8 @@ import org.apache.royale.compiler.parsing.IASToken;
 import org.apache.royale.compiler.tree.as.IASNode;
 
 public class TokenQuery {
+	public static final int TOKEN_TYPE_WHITESPACE = 999999;
+
 	public TokenQuery(IASToken[] tokens) {
 		allTokens = tokens;
 	}
@@ -45,6 +47,14 @@ public class TokenQuery {
 	 * Returns all tokens inside of a particular node.
 	 */
 	public IASToken[] getTokens(IASNode node) {
+		return getTokens(node, false, false);
+	}
+
+	/**
+	 * Returns all tokens inside of a particular node, with the option to skip
+	 * comment and whitespace tokens.
+	 */
+	public IASToken[] getTokens(IASNode node, boolean skipComments, boolean skipWhitespace) {
 		List<IASToken> result = new ArrayList<>();
 		for (IASToken token : allTokens) {
 			if (token.getAbsoluteStart() < node.getAbsoluteStart()) {
@@ -53,53 +63,67 @@ public class TokenQuery {
 			if (token.getAbsoluteStart() >= node.getAbsoluteEnd()) {
 				break;
 			}
+			if (skipComments && isComment(token)) {
+				continue;
+			}
+			if (skipWhitespace && isWhitespace(token)) {
+				continue;
+			}
 			result.add(token);
 		}
 		return result.toArray(new IASToken[0]);
 	}
 
 	/**
-	 * Returns the token immediately before a source location.
+	 * Returns the token immediately before a source location. Includes comment
+	 * and whitespace tokens.
 	 */
 	public IASToken getTokenBefore(ISourceLocation sourceLocation) {
-		return getTokenBefore(sourceLocation, false);
+		return getTokenBefore(sourceLocation, false, false);
 	}
 
 	/**
 	 * Returns the token immediately before a source location, with the option
-	 * to skip comment tokens.
+	 * to skip comment and whitespace tokens.
 	 */
-	public IASToken getTokenBefore(ISourceLocation sourceLocation, boolean skipComments) {
+	public IASToken getTokenBefore(ISourceLocation sourceLocation, boolean skipComments, boolean skipWhitespace) {
 		IASToken result = null;
-		for (IASToken otherToken : allTokens) {
-			if (skipComments && isComment(otherToken)) {
+		for (IASToken token : allTokens) {
+			if (skipComments && isComment(token)) {
 				continue;
 			}
-			if (otherToken.getAbsoluteStart() >= sourceLocation.getAbsoluteStart()) {
+			if (skipWhitespace && isWhitespace(token)) {
+				continue;
+			}
+			if (token.getAbsoluteStart() >= sourceLocation.getAbsoluteStart()) {
 				return result;
 			}
-			result = otherToken;
+			result = token;
 		}
 		return null;
 	}
 
 	/**
-	 * Returns the token immediately after a source location.
+	 * Returns the token immediately after a source location. Includes comment
+	 * and whitespace tokens.
 	 */
 	public IASToken getTokenAfter(ISourceLocation sourceLocation) {
-		return getTokenAfter(sourceLocation, false);
+		return getTokenAfter(sourceLocation, false, false);
 	}
 
 	/**
 	 * Returns the token immediately after a source location, with the option to
-	 * skip comment tokens.
+	 * skip comment and whitespace tokens.
 	 */
-	public IASToken getTokenAfter(ISourceLocation sourceLocation, boolean skipComments) {
+	public IASToken getTokenAfter(ISourceLocation sourceLocation, boolean skipComments, boolean skipWhitespace) {
 		for (IASToken token : allTokens) {
-			if (skipComments && isComment(token)) {
-				continue;
-			}
 			if (token.getAbsoluteStart() >= sourceLocation.getAbsoluteEnd()) {
+				if (skipComments && isComment(token)) {
+					continue;
+				}
+				if (skipWhitespace && isWhitespace(token)) {
+					continue;
+				}
 				return token;
 			}
 		}
@@ -107,11 +131,26 @@ public class TokenQuery {
 	}
 
 	/**
-	 * Returns the first token inside a node.
+	 * Returns the first token inside a node. Includes comment
+	 * and whitespace tokens.
 	 */
 	public IASToken getFirstToken(IASNode node) {
+		return getFirstToken(node, false, false);
+	}
+
+	/**
+	 * Returns the first token inside a node, with the option to
+	 * skip comment and whitespace tokens.
+	 */
+	public IASToken getFirstToken(IASNode node, boolean skipComments, boolean skipWhitespace) {
 		for (IASToken token : allTokens) {
 			if (token.getAbsoluteStart() >= node.getAbsoluteStart()) {
+				if (skipComments && isComment(token)) {
+					continue;
+				}
+				if (skipWhitespace && isWhitespace(token)) {
+					continue;
+				}
 				return token;
 			}
 		}
@@ -119,12 +158,27 @@ public class TokenQuery {
 	}
 
 	/**
-	 * Returns the last token inside a node.
+	 * Returns the last token inside a node. Includes comment
+	 * and whitespace tokens.
 	 */
 	public IASToken getLastToken(IASNode node) {
+		return getLastToken(node, false, false);
+	}
+
+	/**
+	 * Returns the last token inside a node, with the option to
+	 * skip comment and whitespace tokens.
+	 */
+	public IASToken getLastToken(IASNode node, boolean skipComments, boolean skipWhitespace) {
 		IASToken result = null;
 		for (IASToken token : allTokens) {
 			if (token.getAbsoluteStart() >= node.getAbsoluteStart()) {
+				if (skipComments && isComment(token)) {
+					continue;
+				}
+				if (skipWhitespace && isWhitespace(token)) {
+					continue;
+				}
 				result = token;
 			} else if (result != null) {
 				break;
@@ -133,6 +187,36 @@ public class TokenQuery {
 		return result;
 	}
 
+	/**
+	 * Returns the first token of the specified type that appears before the
+	 * start of a particular source location.
+	 */
+	public IASToken getPreviousTokenOfType(ISourceLocation before, int type) {
+		IASToken result = null;
+		for (IASToken token : allTokens) {
+			if (token.getAbsoluteStart() >= before.getAbsoluteStart()) {
+				return result;
+			}
+			if (token.getType() == type) {
+				result = token;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the first token of the specified type that appears after the end
+	 * of a particular source location.
+	 */
+	public IASToken getNextTokenOfType(ISourceLocation after, int type) {
+		for (IASToken token : allTokens) {
+			if (token.getType() == type && token.getAbsoluteStart() >= after.getAbsoluteEnd()) {
+				return token;
+			}
+		}
+		return null;
+	}
+
 	/**
 	 * Returns all comment tokens inside a node.
 	 */
@@ -157,47 +241,86 @@ public class TokenQuery {
 				|| token.getType() == ASTokenTypes.TOKEN_ASDOC_COMMENT;
 	}
 
-	public IASToken getPreviousTokenOfType(ISourceLocation before, int type) {
+	/**
+	 * Returns the first comment that appears before the start of a particular
+	 * source location.
+	 */
+	public IASToken getCommentBefore(ISourceLocation before) {
 		IASToken result = null;
 		for (IASToken token : allTokens) {
 			if (token.getAbsoluteStart() >= before.getAbsoluteStart()) {
 				return result;
 			}
-			if (token.getType() == type) {
+			if (isComment(token)) {
 				result = token;
 			}
 		}
 		return null;
 	}
 
-	public IASToken getNextTokenOfType(ISourceLocation after, int type) {
+	/**
+	 * Returns the first comment that appears after the end of a particular
+	 * source location.
+	 */
+	public IASToken getCommentAfter(ISourceLocation after) {
 		for (IASToken token : allTokens) {
-			if (token.getType() == type && token.getAbsoluteStart() >= after.getAbsoluteEnd()) {
+			if (token.getAbsoluteStart() >= after.getAbsoluteEnd() && isComment(token)) {
 				return token;
 			}
 		}
 		return null;
 	}
 
-	public IASToken getPreviousComment(ISourceLocation before) {
+	/**
+	 * Checks if a token is whitespace.
+	 */
+	public boolean isWhitespace(IASToken token) {
+		return token.getType() == TOKEN_TYPE_WHITESPACE;
+	}
+
+	/**
+	 * Returns the first whitespace that appears before the start of a
+	 * particular source location.
+	 */
+	public IASToken getWhitespaceBefore(ISourceLocation before) {
 		IASToken result = null;
 		for (IASToken token : allTokens) {
 			if (token.getAbsoluteStart() >= before.getAbsoluteStart()) {
 				return result;
 			}
-			if (isComment(token)) {
+			if (isWhitespace(token)) {
 				result = token;
 			}
 		}
 		return null;
 	}
 
-	public IASToken getNextComment(ISourceLocation after) {
+	/**
+	 * Returns the first whitespace that appears after the end of a
+	 * particular source location.
+	 */
+	public IASToken getWhitespaceAfter(ISourceLocation after) {
 		for (IASToken token : allTokens) {
-			if (token.getAbsoluteStart() >= after.getAbsoluteEnd() && isComment(token)) {
+			if (token.getAbsoluteStart() >= after.getAbsoluteEnd() && isWhitespace(token)) {
 				return token;
 			}
 		}
 		return null;
 	}
+
+	/**
+	 * Returns the first non-comment, non-whitespace token that appears before
+	 * the start of a particular source location.
+	 */
+	public IASToken getSignificantTokenBefore(ISourceLocation before) {
+		return getTokenBefore(before, true, true);
+	}
+
+	/**
+	 * Returns the first non-comment, non-whitespace token that appears after
+	 * the end of a particular source location.
+	 */
+	public IASToken getSignificantTokenAfter(ISourceLocation after) {
+		return getTokenAfter(after, true, true);
+	}
 }
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java b/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java
index 62159539c..a6c63b0cc 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/EmptyStatementRule.java
@@ -47,7 +47,7 @@ public class EmptyStatementRule extends LinterRule {
 	}
 
 	private void checkSemicolon(IASToken semicolon, TokenQuery tokenQuery, Collection<ICompilerProblem> problems) {
-		IASToken prevToken = tokenQuery.getTokenBefore(semicolon);
+		IASToken prevToken = tokenQuery.getSignificantTokenBefore(semicolon);
 		if (prevToken == null) {
 			return;
 		}
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java b/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java
index 6a58c927c..28d5e193b 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/LineCommentPositionRule.java
@@ -50,17 +50,19 @@ public class LineCommentPositionRule extends LinterRule {
 	public LineCommentPosition position = LineCommentPosition.ABOVE;
 
 	private void checkSingleLineComment(IASToken comment, TokenQuery tokenQuery, Collection<ICompilerProblem> problems) {
-		IASToken prevToken = tokenQuery.getTokenBefore(comment);
+		IASToken prevToken = tokenQuery.getSignificantTokenBefore(comment);
 		if (prevToken == null) {
 			return;
 		}
 		if (LineCommentPosition.ABOVE.equals(position)) {
 			if (prevToken.getLine() == comment.getLine()) {
+				// is beside the comment
 				problems.add(new LineCommentPositionLinterProblem(comment, position));
 			}
 		}
 		else if (LineCommentPosition.BESIDE.equals(position)) {
 			if (prevToken.getLine() != comment.getLine()) {
+				// is not beside the comment
 				problems.add(new LineCommentPositionLinterProblem(comment, position));
 			}
 		}
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MissingASDocRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MissingASDocRule.java
index 5c8e3ba86..e2fc08879 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MissingASDocRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MissingASDocRule.java
@@ -74,7 +74,7 @@ public class MissingASDocRule extends LinterRule {
 		if (!definitionNode.hasNamespace("public")) {
 			return;
 		}
-		IASToken token = tokenQuery.getTokenBefore(definitionNode);
+		IASToken token = tokenQuery.getTokenBefore(definitionNode, false, true);
 		if (token.getType() == ASTokenTypes.TOKEN_ASDOC_COMMENT) {
 			String docComment = token.getText();
 			if (!isDocCommentEmpty(docComment)) {


[royale-compiler] 01/09: linter: start adding some tests

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit b4672772792f68ba2eb72404909c68f64e24a5e2
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Oct 27 13:41:09 2022 -0700

    linter: start adding some tests
---
 linter/build.xml                                   |   2 +-
 linter/src/test/build.xml                          |  93 +++++++++
 .../royale/linter/rules/TestClassNameRule.java     | 111 +++++++++++
 .../royale/linter/rules/TestConstantNameRule.java  |  85 ++++++++
 .../royale/linter/rules/TestFieldNameRule.java     | 123 ++++++++++++
 .../royale/linter/rules/TestFunctionNameRule.java  | 221 +++++++++++++++++++++
 .../royale/linter/rules/TestInterfaceNameRule.java | 111 +++++++++++
 .../rules/TestLocalVarAndParameterNameRule.java    | 201 +++++++++++++++++++
 .../apache/royale/linter/rules/TestMXMLIDRule.java | 124 ++++++++++++
 .../royale/linter/rules/TestPackageNameRule.java   | 148 ++++++++++++++
 10 files changed, 1218 insertions(+), 1 deletion(-)

diff --git a/linter/build.xml b/linter/build.xml
index 3ccd6b9a1..5ed64452f 100644
--- a/linter/build.xml
+++ b/linter/build.xml
@@ -108,7 +108,7 @@
     </target>
     
     <target name="main" depends="jar">
-        <!-- <antcall target="test"/> -->
+        <antcall target="test"/>
         <antcall target="jar-test"/>
     </target>
 
diff --git a/linter/src/test/build.xml b/linter/src/test/build.xml
new file mode 100644
index 000000000..43acdec94
--- /dev/null
+++ b/linter/src/test/build.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" ?>
+
+<!--
+
+  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.
+
+-->
+
+<project name="linter.tests" default="main" basedir=".">
+
+    <pathconvert property="linter.tests" dirsep="/">
+        <path location="${basedir}"/>
+    </pathconvert>
+    
+    <property environment="env"/>
+	<property file="unittest.properties" />
+	<property name="test.timeout" value="3000000" />
+	<property name="maxmem" value="512" />
+	
+	<condition property="sdk" value="${ROYALE_HOME}" else="${env.ROYALE_HOME}">
+	    <isset property="ROYALE_HOME" />
+	</condition>
+	
+    <property name="linter" value="${linter.tests}/../.."/>
+    <property name="royale" value="${linter}/../compiler"/>
+    
+    <target name="jar.tests">
+        <java jar="${royale}/lib/linter.jar" fork="true"/>
+    </target>
+    
+    <target name="compile.tests">
+        <echo>linter is ${linter} royale is ${royale}</echo>
+        <delete dir="${linter}/target/test-classes"/>
+        <mkdir dir="${linter}/target/test-classes"/>
+        <javac debug="${javac.debug}" deprecation="${javac.deprecation}" destdir="${linter}/target/test-classes" includeAntRuntime="true">
+            <src path="${linter.tests}/java"/>
+            <compilerarg value="-Xlint:all,-path"/>
+            <classpath>
+                <pathelement location="${linter}/../compiler-test-utils/target/classes"/>
+                <fileset dir="${royale}/lib" includes="**/*.jar"/>
+            </classpath>
+        </javac>
+    </target>
+    
+    <target name="tests" depends="compile.tests">
+        <mkdir dir="${linter}/target/junit-reports"/>
+        <mkdir dir="${linter}/target/junit-temp"/>
+        <junit dir="${linter}"
+            fork="yes" forkMode="perBatch" maxmemory="${maxmem}m" timeout="${test.timeout}"
+            printsummary="true" showoutput="true"
+            haltonerror="true" haltonfailure="true"
+            failureproperty="tests.unit.failed">
+            <jvmarg value="-Duser.language=en"/>
+            <jvmarg value="-Duser.country=US"/>
+            <classpath>
+                <pathelement location="${linter}/target/classes"/>
+                <pathelement location="${linter}/target/test-classes"/>
+                <pathelement location="${linter}/../compiler-test-utils/target/classes"/>
+                <fileset dir="${royale}/lib" includes="**/*.jar"/>
+            </classpath>
+            <batchtest todir="${linter}/target/junit-reports">
+                <fileset dir="${linter}/target/test-classes">
+                    <include name="**/Test*.class"/>
+                </fileset>
+            </batchtest>
+            <formatter type="xml"/>
+        </junit>
+    </target>
+    
+    <target name="main" depends="jar.tests, tests"/>
+
+    <target name="clean">
+        <delete dir="${linter}/target/junit-reports"/>
+        <delete dir="${linter}/target/junit-temp"/>
+    </target>
+
+    <target name="wipe" depends="clean">
+    </target>
+
+</project>
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestClassNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestClassNameRule.java
new file mode 100644
index 000000000..0674b97c5
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestClassNameRule.java
@@ -0,0 +1,111 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestClassNameRule {
+	@Test
+	public void testClassNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ClassNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testClassNameStartsWithLowerCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ClassNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class myClass{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ClassNameRule.ClassNameLinterProblem);
+	}
+
+	@Test
+	public void testClassNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ClassNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class $MyClass{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ClassNameRule.ClassNameLinterProblem);
+	}
+
+	@Test
+	public void testClassNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ClassNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class _MyClass{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ClassNameRule.ClassNameLinterProblem);
+	}
+
+	@Test
+	public void testClassNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ClassNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class My$Class{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ClassNameRule.ClassNameLinterProblem);
+	}
+
+	@Test
+	public void testClassNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ClassNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class My_Class{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ClassNameRule.ClassNameLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestConstantNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestConstantNameRule.java
new file mode 100644
index 000000000..3f9adc1da
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestConstantNameRule.java
@@ -0,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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestConstantNameRule {
+	@Test
+	public void testConstantNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ConstantNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{const MY_CONSTANT:String;}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testConstantNameContainsLowerCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ConstantNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{const mY_CONSTANT:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ConstantNameRule.ConstantNameLinterProblem);
+	}
+
+	@Test
+	public void testConstantNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ConstantNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{const $MY_CONSTANT:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ConstantNameRule.ConstantNameLinterProblem);
+	}
+
+	@Test
+	public void testConstantNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new ConstantNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{const _MY_CONSTANT:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof ConstantNameRule.ConstantNameLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestFieldNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestFieldNameRule.java
new file mode 100644
index 000000000..261d86aa8
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestFieldNameRule.java
@@ -0,0 +1,123 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestFieldNameRule {
+	@Test
+	public void testFieldNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FieldNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{var myField:String;}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testFieldNameStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FieldNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{var MyField:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FieldNameRule.FieldNameLinterProblem);
+	}
+
+	@Test
+	public void testFieldNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FieldNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{var $myField:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FieldNameRule.FieldNameLinterProblem);
+	}
+
+	@Test
+	public void testFieldNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FieldNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{var _myField:String;}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testFieldNameStartsWith_AndUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FieldNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{var _MyField:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FieldNameRule.FieldNameLinterProblem);
+	}
+
+	@Test
+	public void testFieldNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FieldNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{var my$Field:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FieldNameRule.FieldNameLinterProblem);
+	}
+
+	@Test
+	public void testFieldNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FieldNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{var my_Field:String;}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FieldNameRule.FieldNameLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestFunctionNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestFunctionNameRule.java
new file mode 100644
index 000000000..d3f261c5d
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestFunctionNameRule.java
@@ -0,0 +1,221 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestFunctionNameRule {
+	@Test
+	public void testMethodNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{}}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testMethodNameStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function MyMethod():void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testMethodNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function $myMethod():void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testMethodNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function _myMethod():void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testMethodNameStartsWith_AndUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function _MyMethod():void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testMethodNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function my$Method():void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testMethodNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function my_Method():void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalFunctionNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{function myFunction():void{}}}}",
+				problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testLocalFunctionNameStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{function MyFunction():void{}}}}",
+				problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalFunctionNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{function $myFunction():void{}}}}",
+				problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalFunctionNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{function _myFunction():void{}}}}",
+				problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalFunctionNameStartsWith_AndUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{function _MyFunction():void{}}}}",
+				problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalFunctionNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{function my$Function():void{}}}}",
+				problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalFunctionNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new FunctionNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myMethod():void{function my_Function():void{}}}}",
+				problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof FunctionNameRule.FunctionNameLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestInterfaceNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestInterfaceNameRule.java
new file mode 100644
index 000000000..3b4a66ecb
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestInterfaceNameRule.java
@@ -0,0 +1,111 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestInterfaceNameRule {
+	@Test
+	public void testInterfaceNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new InterfaceNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {interface IMyInterface{}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testInterfaceNameStartsWithLowerCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new InterfaceNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {interface iMyInterface{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof InterfaceNameRule.InterfaceNameLinterProblem);
+	}
+
+	@Test
+	public void testInterfaceNameStartsWithLowerCaseAfterI() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new InterfaceNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {interface ImyInterface{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof InterfaceNameRule.InterfaceNameLinterProblem);
+	}
+
+	@Test
+	public void testInterfaceNameStartsWithoutI() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new InterfaceNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {interface MyInterface{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof InterfaceNameRule.InterfaceNameLinterProblem);
+	}
+
+	@Test
+	public void testInterfaceNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new InterfaceNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {interface IMy$Interface{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof InterfaceNameRule.InterfaceNameLinterProblem);
+	}
+
+	@Test
+	public void testInterfaceNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new InterfaceNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {interface IMy_Interface{}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof InterfaceNameRule.InterfaceNameLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarAndParameterNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarAndParameterNameRule.java
new file mode 100644
index 000000000..5eee108be
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestLocalVarAndParameterNameRule.java
@@ -0,0 +1,201 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestLocalVarAndParameterNameRule {
+	@Test
+	public void testLocalVarNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction():void{var myVar:String;}}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testLocalVarNameStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction():void{var MyVar:String;}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.LocalVarNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalVarNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction():void{var $myVar:String;}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.LocalVarNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalVarNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction():void{var _myVar:String;}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.LocalVarNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalVarNameStartsWith_AndUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction():void{var _MyVar:String;}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.LocalVarNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalVarNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction():void{var my$Var:String;}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.LocalVarNameLinterProblem);
+	}
+
+	@Test
+	public void testLocalVarNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction():void{var my_Var:String;}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.LocalVarNameLinterProblem);
+	}
+
+	@Test
+	public void testParameterNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction(myParam:String):void{}}}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testParameterNameStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction(MyParam:String):void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.ParameterNameLinterProblem);
+	}
+
+	@Test
+	public void testParameterNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction($myParam:String):void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.ParameterNameLinterProblem);
+	}
+
+	@Test
+	public void testParameterNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction(_myParam:String):void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.ParameterNameLinterProblem);
+	}
+
+	@Test
+	public void testParameterNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction(my$Param:String):void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.ParameterNameLinterProblem);
+	}
+
+	@Test
+	public void testParameterNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new LocalVarAndParameterNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {class MyClass{function myFunction(my_Param:String):void{}}}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof LocalVarAndParameterNameRule.ParameterNameLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestMXMLIDRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestMXMLIDRule.java
new file mode 100644
index 000000000..796efe6e4
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestMXMLIDRule.java
@@ -0,0 +1,124 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.apache.royale.linter.MXMLLinter;
+import org.junit.Test;
+
+public class TestMXMLIDRule {
+	@Test
+	public void testMXMLIDValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new MXMLIDRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		MXMLLinter linter = new MXMLLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.mxml", "<fx:Object><fx:Number id=\"myMxmlId\">123.4</fx:Number></fx:Object>", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testMXMLIDEmpty() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new MXMLIDRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		MXMLLinter linter = new MXMLLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.mxml", "<fx:Object><fx:Number id=\"\">123.4</fx:Number></fx:Object>", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof MXMLIDRule.MXMLIDLinterProblem);
+	}
+
+	@Test
+	public void testMXMLIDStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new MXMLIDRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		MXMLLinter linter = new MXMLLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.mxml", "<fx:Object><fx:Number id=\"MyMxmlId\">123.4</fx:Number></fx:Object>", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof MXMLIDRule.MXMLIDLinterProblem);
+	}
+
+	@Test
+	public void testMXMLIDStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new MXMLIDRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		MXMLLinter linter = new MXMLLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.mxml", "<fx:Object><fx:Number id=\"$myMxmlId\">123.4</fx:Number></fx:Object>", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof MXMLIDRule.MXMLIDLinterProblem);
+	}
+
+	@Test
+	public void testMXMLIDStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new MXMLIDRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		MXMLLinter linter = new MXMLLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.mxml", "<fx:Object><fx:Number id=\"_myMxmlId\">123.4</fx:Number></fx:Object>", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof MXMLIDRule.MXMLIDLinterProblem);
+	}
+
+	@Test
+	public void testMXMLIDContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new MXMLIDRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		MXMLLinter linter = new MXMLLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.mxml", "<fx:Object><fx:Number id=\"my$MxmlId\">123.4</fx:Number></fx:Object>", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof MXMLIDRule.MXMLIDLinterProblem);
+	}
+
+	@Test
+	public void testMXMLIDContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new MXMLIDRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		MXMLLinter linter = new MXMLLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.mxml", "<fx:Object><fx:Number id=\"my_MxmlId\">123.4</fx:Number></fx:Object>", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof MXMLIDRule.MXMLIDLinterProblem);
+	}
+}
\ No newline at end of file
diff --git a/linter/src/test/java/org/apache/royale/linter/rules/TestPackageNameRule.java b/linter/src/test/java/org/apache/royale/linter/rules/TestPackageNameRule.java
new file mode 100644
index 000000000..8011505e3
--- /dev/null
+++ b/linter/src/test/java/org/apache/royale/linter/rules/TestPackageNameRule.java
@@ -0,0 +1,148 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.royale.linter.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.linter.ASLinter;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.LinterSettings;
+import org.junit.Test;
+
+public class TestPackageNameRule {
+	@Test
+	public void testPackageNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package myPackage {}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testEmptyPackageNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package {}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testMultiPackageNameValid() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package com.myPackage {}", problems);
+		assertEquals(0, problems.size());
+	}
+
+	@Test
+	public void testPackageNameStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package MyPackage {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof PackageNameRule.PackageNameLinterProblem);
+	}
+
+	@Test
+	public void testPackageNameMultiStartsWithUpperCase() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package com.MyPackage {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof PackageNameRule.PackageNameLinterProblem);
+	}
+
+	@Test
+	public void testPackageNameStartsWith$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package $myPackage {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof PackageNameRule.PackageNameLinterProblem);
+	}
+
+	@Test
+	public void testPackageNameStartsWith_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package _myPackage {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof PackageNameRule.PackageNameLinterProblem);
+	}
+
+	@Test
+	public void testPackageNameContains$() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package my$Package {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof PackageNameRule.PackageNameLinterProblem);
+	}
+
+	@Test
+	public void testPackageNameContains_() {
+		List<LinterRule> rules = new ArrayList<LinterRule>();
+		rules.add(new PackageNameRule());
+		LinterSettings settings = new LinterSettings();
+		settings.rules = rules;
+		ASLinter linter = new ASLinter(settings);
+		List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+		linter.lint("file.as", "package my_Package {}", problems);
+		assertEquals(1, problems.size());
+		assertTrue(problems.get(0) instanceof PackageNameRule.PackageNameLinterProblem);
+	}
+}
\ No newline at end of file