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/05 17:32:38 UTC

[royale-compiler] 02/02: linter: add ILinterProblem interface to allow for easier detection of linter problems

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 dc79c93d41ce08257d4d04b5eae865040473299a
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Wed Oct 5 10:32:15 2022 -0700

    linter: add ILinterProblem interface to allow for easier detection of linter problems
---
 .../ILinterProblem.java}                           | 32 ++--------------------
 .../apache/royale/linter/rules/ClassNameRule.java  |  3 +-
 .../royale/linter/rules/ConstantNameRule.java      |  3 +-
 .../royale/linter/rules/EmptyCommentRule.java      |  3 +-
 .../royale/linter/rules/EmptyFunctionBodyRule.java |  3 +-
 .../royale/linter/rules/EmptyNestedBlockRule.java  |  3 +-
 .../royale/linter/rules/EmptyStatementRule.java    |  3 +-
 .../apache/royale/linter/rules/FieldNameRule.java  |  3 +-
 .../royale/linter/rules/FunctionNameRule.java      |  3 +-
 .../royale/linter/rules/InterfaceNameRule.java     |  3 +-
 .../linter/rules/LineCommentPositionRule.java      |  3 +-
 .../linter/rules/LocalVarAndParameterNameRule.java |  5 ++--
 .../linter/rules/LocalVarShadowsFieldRule.java     |  3 +-
 .../linter/rules/MXMLEmptyAttributeRule.java       |  3 +-
 .../org/apache/royale/linter/rules/MXMLIDRule.java |  3 +-
 .../royale/linter/rules/MaxBlockDepthRule.java     |  3 +-
 .../royale/linter/rules/MaxParametersRule.java     |  3 +-
 .../royale/linter/rules/MissingASDocRule.java      |  5 ++--
 .../linter/rules/MissingConstructorSuperRule.java  |  3 +-
 .../royale/linter/rules/MissingNamespaceRule.java  | 13 +++++----
 .../royale/linter/rules/MissingSemicolonRule.java  |  3 +-
 .../royale/linter/rules/MissingTypeRule.java       |  7 +++--
 .../apache/royale/linter/rules/NoAnyTypeRule.java  |  7 +++--
 .../royale/linter/rules/NoBooleanEqualityRule.java |  3 +-
 .../rules/NoConstructorDispatchEventRule.java      |  5 ++--
 .../linter/rules/NoConstructorReturnTypeRule.java  |  3 +-
 .../linter/rules/NoDuplicateObjectKeysRule.java    |  3 +-
 .../royale/linter/rules/NoDynamicClassRule.java    |  3 +-
 .../linter/rules/NoIfBooleanLiteralRule.java       |  3 +-
 .../royale/linter/rules/NoLeadingZeroesRule.java   |  3 +-
 .../royale/linter/rules/NoSparseArrayRule.java     |  3 +-
 .../royale/linter/rules/NoStringEventNameRule.java |  7 +++--
 .../royale/linter/rules/NoThisInClosureRule.java   |  3 +-
 .../apache/royale/linter/rules/NoTraceRule.java    |  3 +-
 .../royale/linter/rules/NoVoidOperatorRule.java    |  3 +-
 .../royale/linter/rules/NoWildcardImportRule.java  |  3 +-
 .../org/apache/royale/linter/rules/NoWithRule.java |  4 ++-
 .../rules/OverrideContainsOnlySuperCallRule.java   |  3 +-
 .../royale/linter/rules/PackageNameRule.java       |  3 +-
 .../royale/linter/rules/StaticConstantsRule.java   |  3 +-
 .../royale/linter/rules/StrictEqualityRule.java    |  4 ++-
 .../linter/rules/SwitchWithoutDefaultRule.java     |  3 +-
 .../royale/linter/rules/UnsafeNegationRule.java    |  3 +-
 .../royale/linter/rules/ValidTypeofRule.java       |  3 +-
 .../royale/linter/rules/VariablesOnTopRule.java    |  3 +-
 45 files changed, 107 insertions(+), 87 deletions(-)

diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java b/linter/src/main/java/org/apache/royale/linter/problems/ILinterProblem.java
similarity index 51%
copy from linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
copy to linter/src/main/java/org/apache/royale/linter/problems/ILinterProblem.java
index 388bd7a94..31eed863a 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoWithRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/problems/ILinterProblem.java
@@ -17,36 +17,10 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-package org.apache.royale.linter.rules;
+package org.apache.royale.linter.problems;
 
-import java.util.HashMap;
-import java.util.Map;
+import org.apache.royale.compiler.problems.ICompilerProblem;
 
-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;
+public interface ILinterProblem extends ICompilerProblem {
 
-/**
- * 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;
-	}
-
-	public static class NoWithLinterProblem extends CompilerProblem {
-		public static final String DESCRIPTION = "Must not use 'with' statement";
-
-		public NoWithLinterProblem(IASToken token)
-		{
-			super(token);
-		}
-	}
 }
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/ClassNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/ClassNameRule.java
index 462f28a6c..b0b208df7 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/ClassNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/ClassNameRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.tree.as.IClassNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that class names match a specific pattern.
@@ -63,7 +64,7 @@ public class ClassNameRule extends LinterRule {
 		problems.add(new ClassNameLinterProblem(classNode, thePattern));
 	}
 
-	public static class ClassNameLinterProblem extends CompilerProblem {
+	public static class ClassNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Class name does not match the pattern '${pattern}'";
 
 		public ClassNameLinterProblem(IClassNode node, Pattern pattern)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/ConstantNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/ConstantNameRule.java
index 16f8b1cec..24798269e 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/ConstantNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/ConstantNameRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that constant names match a specific pattern.
@@ -66,7 +67,7 @@ public class ConstantNameRule extends LinterRule {
 		problems.add(new ConstantNameLinterProblem(variableNode, thePattern));
 	}
 
-	public static class ConstantNameLinterProblem extends CompilerProblem {
+	public static class ConstantNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Constant name does not match the pattern '${pattern}'";
 
 		public ConstantNameLinterProblem(IVariableNode node, Pattern pattern)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/EmptyCommentRule.java b/linter/src/main/java/org/apache/royale/linter/rules/EmptyCommentRule.java
index 177c45b6c..31679040b 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/EmptyCommentRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/EmptyCommentRule.java
@@ -35,6 +35,7 @@ import org.apache.royale.linter.MXMLTokenQuery;
 import org.apache.royale.linter.MXMLTokenVisitor;
 import org.apache.royale.linter.TokenQuery;
 import org.apache.royale.linter.TokenVisitor;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for line or block comments that are empty.
@@ -95,7 +96,7 @@ public class EmptyCommentRule extends LinterRule {
 		problems.add(new EmptyCommentLinterProblem(comment));
 	}
 
-	public static class EmptyCommentLinterProblem extends CompilerProblem {
+	public static class EmptyCommentLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Comment must not be empty";
 
 		public EmptyCommentLinterProblem(IASToken token) {
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/EmptyFunctionBodyRule.java b/linter/src/main/java/org/apache/royale/linter/rules/EmptyFunctionBodyRule.java
index bfa04a6f0..bf357d633 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/EmptyFunctionBodyRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/EmptyFunctionBodyRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.tree.as.IFunctionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for function bodies that are empty.
@@ -81,7 +82,7 @@ public class EmptyFunctionBodyRule extends LinterRule {
 		return true;
 	}
 
-	public static class EmptyFunctionBodyLinterProblem extends CompilerProblem {
+	public static class EmptyFunctionBodyLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Function body must not be empty";
 
 		public EmptyFunctionBodyLinterProblem(IBlockNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/EmptyNestedBlockRule.java b/linter/src/main/java/org/apache/royale/linter/rules/EmptyNestedBlockRule.java
index 87319ce99..d168c2a6e 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/EmptyNestedBlockRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/EmptyNestedBlockRule.java
@@ -34,6 +34,7 @@ import org.apache.royale.compiler.tree.as.ITypeNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for empty blocks, as long as they aren't the bodies of classes,
@@ -77,7 +78,7 @@ public class EmptyNestedBlockRule extends LinterRule {
 		return true;
 	}
 
-	public static class EmptyNestedBlockLinterProblem extends CompilerProblem {
+	public static class EmptyNestedBlockLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Block must not be empty";
 
 		public EmptyNestedBlockLinterProblem(IBlockNode node)
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 ccfb3f841..62159539c 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
@@ -30,6 +30,7 @@ import org.apache.royale.compiler.problems.ICompilerProblem;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.TokenQuery;
 import org.apache.royale.linter.TokenVisitor;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for empty statements. An empty statement consists of only a semicolon
@@ -59,7 +60,7 @@ public class EmptyStatementRule extends LinterRule {
 		problems.add(new EmptyStatementLinterProblem(semicolon));
 	}
 
-	public static class EmptyStatementLinterProblem extends CompilerProblem {
+	public static class EmptyStatementLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Statement must not be empty";
 
 		public EmptyStatementLinterProblem(IASToken token)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/FieldNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/FieldNameRule.java
index 974613e1c..68c26a093 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/FieldNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/FieldNameRule.java
@@ -35,6 +35,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that field names match a specific pattern.
@@ -77,7 +78,7 @@ public class FieldNameRule extends LinterRule {
 		problems.add(new FieldNameLinterProblem(variableNode, thePattern));
 	}
 
-	public static class FieldNameLinterProblem extends CompilerProblem {
+	public static class FieldNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Field name '${varName}' does not match the pattern '${pattern}'";
 
 		public FieldNameLinterProblem(IVariableNode node, Pattern pattern)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/FunctionNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/FunctionNameRule.java
index 9cb10db3e..66618bb11 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/FunctionNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/FunctionNameRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.tree.as.IFunctionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that function names match a specific pattern.
@@ -70,7 +71,7 @@ public class FunctionNameRule extends LinterRule {
 		problems.add(new FunctionNameLinterProblem(functionNode, thePattern));
 	}
 
-	public static class FunctionNameLinterProblem extends CompilerProblem {
+	public static class FunctionNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Function name '${functionName}' does not match the pattern '${pattern}'";
 
 		public FunctionNameLinterProblem(IFunctionNode node, Pattern pattern)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/InterfaceNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/InterfaceNameRule.java
index 23a4d2770..8629d8fae 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/InterfaceNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/InterfaceNameRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.tree.as.IInterfaceNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that interface names match a specific pattern.
@@ -63,7 +64,7 @@ public class InterfaceNameRule extends LinterRule {
 		problems.add(new InterfaceNameLinterProblem(interfaceNode, thePattern));
 	}
 
-	public static class InterfaceNameLinterProblem extends CompilerProblem {
+	public static class InterfaceNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Interface name does not match the pattern '${pattern}'";
 
 		public InterfaceNameLinterProblem(IInterfaceNode node, Pattern pattern)
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 ae3fc4b0f..6a58c927c 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
@@ -31,6 +31,7 @@ import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.TokenQuery;
 import org.apache.royale.linter.TokenVisitor;
 import org.apache.royale.linter.config.LineCommentPosition;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks if line comments appear beside code on the same line, or on a
@@ -65,7 +66,7 @@ public class LineCommentPositionRule extends LinterRule {
 		}
 	}
 
-	public static class LineCommentPositionLinterProblem extends CompilerProblem {
+	public static class LineCommentPositionLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Comment must be ${position} code";
 
 		public LineCommentPositionLinterProblem(IASToken token, LineCommentPosition position)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/LocalVarAndParameterNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/LocalVarAndParameterNameRule.java
index 6a1be14de..589d385cd 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/LocalVarAndParameterNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/LocalVarAndParameterNameRule.java
@@ -37,6 +37,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that local variable and parameter names match a specific pattern.
@@ -95,7 +96,7 @@ public class LocalVarAndParameterNameRule extends LinterRule {
 		problems.add(new ParameterNameLinterProblem(paramNode, thePattern));
 	}
 
-	public static class LocalVarNameLinterProblem extends CompilerProblem {
+	public static class LocalVarNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Variable name '${varName}' does not match the pattern '${pattern}'";
 
 		public LocalVarNameLinterProblem(IVariableNode node, Pattern pattern)
@@ -109,7 +110,7 @@ public class LocalVarAndParameterNameRule extends LinterRule {
 		public String varName;
 	}
 
-	public static class ParameterNameLinterProblem extends CompilerProblem {
+	public static class ParameterNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Parameter name '${paramName}' does not match the pattern '${pattern}'";
 
 		public ParameterNameLinterProblem(IVariableNode node, Pattern pattern)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/LocalVarShadowsFieldRule.java b/linter/src/main/java/org/apache/royale/linter/rules/LocalVarShadowsFieldRule.java
index 4fce9ce8c..125034139 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/LocalVarShadowsFieldRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/LocalVarShadowsFieldRule.java
@@ -35,6 +35,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 public class LocalVarShadowsFieldRule extends LinterRule {
 	@Override
@@ -72,7 +73,7 @@ public class LocalVarShadowsFieldRule extends LinterRule {
 		}
 	}
 
-	public static class LocalVarShadowsFieldLinterProblem extends CompilerProblem {
+	public static class LocalVarShadowsFieldLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Local variable '${varName}' has the same name as field in class '${className}'";
 
 		public LocalVarShadowsFieldLinterProblem(IVariableNode variableNode, IClassNode classNode)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MXMLEmptyAttributeRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MXMLEmptyAttributeRule.java
index 147ea2b56..3594e58d9 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MXMLEmptyAttributeRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MXMLEmptyAttributeRule.java
@@ -30,6 +30,7 @@ import org.apache.royale.compiler.problems.ICompilerProblem;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.MXMLTagVisitor;
 import org.apache.royale.linter.MXMLTokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that MXML attribute values are not empty.
@@ -52,7 +53,7 @@ public class MXMLEmptyAttributeRule extends LinterRule {
 		}
 	}
 
-	public static class MXMLEmptyAttributeLinterProblem extends CompilerProblem {
+	public static class MXMLEmptyAttributeLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "MXML attribute '${attributeName}' value is empty";
 
 		public MXMLEmptyAttributeLinterProblem(IMXMLTagAttributeData attribute) {
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MXMLIDRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MXMLIDRule.java
index 428704443..d5dbe68f1 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MXMLIDRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MXMLIDRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.problems.ICompilerProblem;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.MXMLTagVisitor;
 import org.apache.royale.linter.MXMLTokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that MXML id attribute values match a specific pattern.
@@ -66,7 +67,7 @@ public class MXMLIDRule extends LinterRule {
 		problems.add(new MXMLIDLinterProblem(idAttribute, thePattern));
 	}
 
-	public static class MXMLIDLinterProblem extends CompilerProblem {
+	public static class MXMLIDLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "MXML id '${idValue}' does not match the pattern '${pattern}'";
 
 		public MXMLIDLinterProblem(IMXMLTagAttributeData attribute, Pattern pattern)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MaxBlockDepthRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MaxBlockDepthRule.java
index 49aa594eb..b8e195391 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MaxBlockDepthRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MaxBlockDepthRule.java
@@ -34,6 +34,7 @@ import org.apache.royale.compiler.tree.as.IStatementNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks the number of nested blocks in a function.
@@ -95,7 +96,7 @@ public class MaxBlockDepthRule extends LinterRule {
 		return maxDepth;
 	}
 
-	public static class MaxBlockDepthLinterProblem extends CompilerProblem {
+	public static class MaxBlockDepthLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Function '${functionName}' has blocks nested ${depth} levels deep, but expected no deeper than ${maxDepth} levels";
 
 		public MaxBlockDepthLinterProblem(IFunctionNode node, int depth, int maxDepth)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MaxParametersRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MaxParametersRule.java
index b2005b30a..13acef074 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MaxParametersRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MaxParametersRule.java
@@ -30,6 +30,7 @@ import org.apache.royale.compiler.tree.as.IFunctionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks the number of function parameters.
@@ -53,7 +54,7 @@ public class MaxParametersRule extends LinterRule {
 		problems.add(new MaxParametersLinterProblem(functionNode, maximum));
 	}
 
-	public static class MaxParametersLinterProblem extends CompilerProblem {
+	public static class MaxParametersLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Function '${functionName}' has ${params} parameters, but expected no more than ${maxParams} parameters";
 
 		public MaxParametersLinterProblem(IFunctionNode node, int maxParams)
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 5459afd60..5c8e3ba86 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
@@ -37,6 +37,7 @@ import org.apache.royale.linter.MXMLTokenQuery;
 import org.apache.royale.linter.MXMLTokenVisitor;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for missing or empty ASDoc comments.
@@ -115,7 +116,7 @@ public class MissingASDocRule extends LinterRule {
 		problems.add(new EmptyASDocLinterProblem(comment));
 	}
 
-	public static class MissingASDocLinterProblem extends CompilerProblem {
+	public static class MissingASDocLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Public APIs must have ASDoc comments";
 
 		public MissingASDocLinterProblem(IDocumentableDefinitionNode node)
@@ -124,7 +125,7 @@ public class MissingASDocRule extends LinterRule {
 		}
 	}
 
-	public static class EmptyASDocLinterProblem extends CompilerProblem {
+	public static class EmptyASDocLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "ASDoc comments must not be empty";
 
 		public EmptyASDocLinterProblem(IASToken token)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MissingConstructorSuperRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MissingConstructorSuperRule.java
index f2863b768..1d186c788 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MissingConstructorSuperRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MissingConstructorSuperRule.java
@@ -35,6 +35,7 @@ import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode.LanguageIdenti
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that all constructors include a call to super().
@@ -79,7 +80,7 @@ public class MissingConstructorSuperRule extends LinterRule {
 		return false;
 	}
 
-	public static class MissingConstructorSuperLinterProblem extends CompilerProblem {
+	public static class MissingConstructorSuperLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Constructor '${functionName}' does not include 'super()' call";
 
 		public MissingConstructorSuperLinterProblem(IFunctionNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MissingNamespaceRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MissingNamespaceRule.java
index 1d0262680..13d032757 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MissingNamespaceRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MissingNamespaceRule.java
@@ -41,6 +41,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that symbols in package or class scopes have a namespace.
@@ -145,7 +146,7 @@ public class MissingNamespaceRule extends LinterRule {
 		return ns != null;
 	}
 
-	public static class MissingNamespaceOnClassLinterProblem extends CompilerProblem {
+	public static class MissingNamespaceOnClassLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing namespace on class '${className}'";
 
 		public MissingNamespaceOnClassLinterProblem(IClassNode node)
@@ -157,7 +158,7 @@ public class MissingNamespaceRule extends LinterRule {
 		public String className;
 	}
 
-	public static class MissingNamespaceOnInterfaceLinterProblem extends CompilerProblem {
+	public static class MissingNamespaceOnInterfaceLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing namespace on interface '${interfaceName}'";
 
 		public MissingNamespaceOnInterfaceLinterProblem(IInterfaceNode node)
@@ -169,7 +170,7 @@ public class MissingNamespaceRule extends LinterRule {
 		public String interfaceName;
 	}
 
-	public static class MissingNamespaceOnPackageFunctionLinterProblem extends CompilerProblem {
+	public static class MissingNamespaceOnPackageFunctionLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing namespace on package function '${functionName}'";
 
 		public MissingNamespaceOnPackageFunctionLinterProblem(IFunctionNode node)
@@ -181,7 +182,7 @@ public class MissingNamespaceRule extends LinterRule {
 		public String functionName;
 	}
 
-	public static class MissingNamespaceOnMethodLinterProblem extends CompilerProblem {
+	public static class MissingNamespaceOnMethodLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing namespace on method '${functionName}'";
 
 		public MissingNamespaceOnMethodLinterProblem(IFunctionNode node)
@@ -193,7 +194,7 @@ public class MissingNamespaceRule extends LinterRule {
 		public String functionName;
 	}
 
-	public static class MissingNamespaceOnPackageVariableLinterProblem extends CompilerProblem {
+	public static class MissingNamespaceOnPackageVariableLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing namespace on package variable '${variableName}'";
 
 		public MissingNamespaceOnPackageVariableLinterProblem(IVariableNode node)
@@ -205,7 +206,7 @@ public class MissingNamespaceRule extends LinterRule {
 		public String variableName;
 	}
 
-	public static class MissingNamespaceOnFieldLinterProblem extends CompilerProblem {
+	public static class MissingNamespaceOnFieldLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing namespace on field '${variableName}'";
 
 		public MissingNamespaceOnFieldLinterProblem(IVariableNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MissingSemicolonRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MissingSemicolonRule.java
index 50a5371f9..9aa1368c1 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MissingSemicolonRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MissingSemicolonRule.java
@@ -30,6 +30,7 @@ import org.apache.royale.compiler.problems.ICompilerProblem;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.TokenQuery;
 import org.apache.royale.linter.TokenVisitor;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for statements with missing semicolons.
@@ -51,7 +52,7 @@ public class MissingSemicolonRule extends LinterRule {
 		problems.add(new MissingSemicolonLinterProblem(semicolon));
 	}
 
-	public static class MissingSemicolonLinterProblem extends CompilerProblem {
+	public static class MissingSemicolonLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Semicolon is required";
 
 		public MissingSemicolonLinterProblem(IASToken token)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MissingTypeRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MissingTypeRule.java
index 1b1903475..70227b73b 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/MissingTypeRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MissingTypeRule.java
@@ -34,6 +34,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks that a type has been declared for all variables, function parameters,
@@ -94,7 +95,7 @@ public class MissingTypeRule extends LinterRule {
 		return true;
 	}
 
-	public static class MissingVariableTypeLinterProblem extends CompilerProblem {
+	public static class MissingVariableTypeLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing type for variable '${varName}'";
 
 		public MissingVariableTypeLinterProblem(IVariableNode node)
@@ -106,7 +107,7 @@ public class MissingTypeRule extends LinterRule {
 		public String varName;
 	}
 
-	public static class MissingFunctionParameterTypeLinterProblem extends CompilerProblem {
+	public static class MissingFunctionParameterTypeLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing type for function parameter '${paramName}'";
 
 		public MissingFunctionParameterTypeLinterProblem(IParameterNode node)
@@ -118,7 +119,7 @@ public class MissingTypeRule extends LinterRule {
 		public String paramName;
 	}
 
-	public static class MissingFunctionReturnTypeLinterProblem extends CompilerProblem {
+	public static class MissingFunctionReturnTypeLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing function return type";
 
 		public MissingFunctionReturnTypeLinterProblem(IFunctionNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoAnyTypeRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoAnyTypeRule.java
index f1879710a..ac5b58bc7 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoAnyTypeRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoAnyTypeRule.java
@@ -36,6 +36,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for uses of the * type.
@@ -92,7 +93,7 @@ public class NoAnyTypeRule extends LinterRule {
 		return true;
 	}
 
-	public static class NoAnyTypeOnVariableLinterProblem extends CompilerProblem {
+	public static class NoAnyTypeOnVariableLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not use the * type for variable '${varName}'";
 
 		public NoAnyTypeOnVariableLinterProblem(IVariableNode node)
@@ -104,7 +105,7 @@ public class NoAnyTypeRule extends LinterRule {
 		public String varName;
 	}
 
-	public static class NoAnyTypeOnParameterLinterProblem extends CompilerProblem {
+	public static class NoAnyTypeOnParameterLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not use the * type for function parameter '${paramName}'";
 
 		public NoAnyTypeOnParameterLinterProblem(IParameterNode node)
@@ -116,7 +117,7 @@ public class NoAnyTypeRule extends LinterRule {
 		public String paramName;
 	}
 
-	public static class NoAnyTypeReturnLinterProblem extends CompilerProblem {
+	public static class NoAnyTypeReturnLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not use the * type for function return type";
 
 		public NoAnyTypeReturnLinterProblem(IFunctionNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoBooleanEqualityRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoBooleanEqualityRule.java
index 8209e554c..5768718f5 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoBooleanEqualityRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoBooleanEqualityRule.java
@@ -31,6 +31,7 @@ import org.apache.royale.compiler.tree.as.IExpressionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for redundant equality comparisons with 'true' and 'false' boolean
@@ -64,7 +65,7 @@ public class NoBooleanEqualityRule extends LinterRule {
 		}
 	}
 
-	public static class NoBooleanEqualityLinterProblem extends CompilerProblem {
+	public static class NoBooleanEqualityLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must simplify statement to remove redundant comparison with true or false";
 
 		public NoBooleanEqualityLinterProblem(IExpressionNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorDispatchEventRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorDispatchEventRule.java
index 6ab9109f4..50bb49668 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorDispatchEventRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorDispatchEventRule.java
@@ -31,11 +31,12 @@ import org.apache.royale.compiler.tree.as.IFunctionCallNode;
 import org.apache.royale.compiler.tree.as.IFunctionNode;
 import org.apache.royale.compiler.tree.as.IIdentifierNode;
 import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
 import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
+import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that a constructor does not call `dispatchEvent` because it's likely
@@ -84,7 +85,7 @@ public class NoConstructorDispatchEventRule extends LinterRule {
 		}
 	}
 
-	public static class NoConstructorDispatchEventLinterProblem extends CompilerProblem {
+	public static class NoConstructorDispatchEventLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Constructor '${functionName}' must not call 'dispatchEvent'";
 
 		public NoConstructorDispatchEventLinterProblem(IFunctionNode functionNode, IExpressionNode dispatchEventNode) {
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorReturnTypeRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorReturnTypeRule.java
index e3d547544..12c72a6d1 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorReturnTypeRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoConstructorReturnTypeRule.java
@@ -31,6 +31,7 @@ import org.apache.royale.compiler.tree.as.IFunctionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that a constructor does not specify a return type (not even `void`).
@@ -56,7 +57,7 @@ public class NoConstructorReturnTypeRule extends LinterRule {
 		problems.add(new NoConstructorReturnTypeLinterProblem(functionNode));
 	}
 
-	public static class NoConstructorReturnTypeLinterProblem extends CompilerProblem {
+	public static class NoConstructorReturnTypeLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Constructor '${functionName}' must not specify '${returnType}' return type";
 
 		public NoConstructorReturnTypeLinterProblem(IFunctionNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoDuplicateObjectKeysRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoDuplicateObjectKeysRule.java
index 601af9f01..48befed34 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoDuplicateObjectKeysRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoDuplicateObjectKeysRule.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.tree.as.IObjectLiteralValuePairNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that each key in an object literal is unique.
@@ -90,7 +91,7 @@ public class NoDuplicateObjectKeysRule extends LinterRule {
 		}
 	}
 
-	public static class NoDuplicateObjectKeysLinterProblem extends CompilerProblem {
+	public static class NoDuplicateObjectKeysLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Object literal contains duplicate key '${keyName}'";
 
 		public NoDuplicateObjectKeysLinterProblem(IExpressionNode node, String keyName)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoDynamicClassRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoDynamicClassRule.java
index f56b11e11..cb2af9d34 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoDynamicClassRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoDynamicClassRule.java
@@ -31,6 +31,7 @@ import org.apache.royale.compiler.tree.as.IClassNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that symbols in package or class scopes have a namespace.
@@ -52,7 +53,7 @@ public class NoDynamicClassRule extends LinterRule {
 		problems.add(new NoDynamicClassLinterProblem(classNode));
 	}
 
-	public static class NoDynamicClassLinterProblem extends CompilerProblem {
+	public static class NoDynamicClassLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Class '${className}' must not be dynamic";
 
 		public NoDynamicClassLinterProblem(IClassNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoIfBooleanLiteralRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoIfBooleanLiteralRule.java
index 457520f7d..dd171c174 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoIfBooleanLiteralRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoIfBooleanLiteralRule.java
@@ -33,6 +33,7 @@ import org.apache.royale.compiler.tree.as.ILiteralNode.LiteralType;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that a boolean literal value is not used as an 'if' condition.
@@ -59,7 +60,7 @@ public class NoIfBooleanLiteralRule extends LinterRule {
 		problems.add(new NoIfBooleanLiteralLinterProblem(literalNode));
 	}
 
-	public static class NoIfBooleanLiteralLinterProblem extends CompilerProblem {
+	public static class NoIfBooleanLiteralLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Condition is always '${value}'";
 
 		public NoIfBooleanLiteralLinterProblem(ILiteralNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoLeadingZeroesRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoLeadingZeroesRule.java
index d5470755d..c860e990b 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoLeadingZeroesRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoLeadingZeroesRule.java
@@ -31,6 +31,7 @@ import org.apache.royale.compiler.tree.as.INumericLiteralNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for use of numeric literals with leading zeroes, except when it starts
@@ -65,7 +66,7 @@ public class NoLeadingZeroesRule extends LinterRule {
 		problems.add(new NoLeadingZeroesLinterProblem(numberNode));
 	}
 
-	public static class NoLeadingZeroesLinterProblem extends CompilerProblem {
+	public static class NoLeadingZeroesLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must remove leading zeros from numeric literal '${value}'";
 
 		public NoLeadingZeroesLinterProblem(INumericLiteralNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoSparseArrayRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoSparseArrayRule.java
index 3420b55c3..91238b65d 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoSparseArrayRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoSparseArrayRule.java
@@ -33,6 +33,7 @@ import org.apache.royale.compiler.tree.as.ILiteralNode.LiteralType;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that an array literal contains no empty slots (multiple repeating commas with no values).
@@ -64,7 +65,7 @@ public class NoSparseArrayRule extends LinterRule {
 		}
 	}
 
-	public static class NoSparseArrayLinterProblem extends CompilerProblem {
+	public static class NoSparseArrayLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Array literals must not be sparse";
 
 		public NoSparseArrayLinterProblem(ILiteralContainerNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoStringEventNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoStringEventNameRule.java
index c4541bbf1..f3e5ec7e2 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoStringEventNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoStringEventNameRule.java
@@ -36,6 +36,7 @@ import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that calls to event dispatcher methods don't use string values for
@@ -90,13 +91,13 @@ public class NoStringEventNameRule extends LinterRule {
 		if (!LiteralType.STRING.equals(literalNode.getLiteralType())) {
 			return;
 		}
-		problems.add(new NoStringEventNameProblem(functionCallNode, functionName));
+		problems.add(new NoStringEventNameLinterProblem(functionCallNode, functionName));
 	}
 
-	public static class NoStringEventNameProblem extends CompilerProblem {
+	public static class NoStringEventNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Calls to '${functionName}' must use constant value instead of string literal for event name";
 
-		public NoStringEventNameProblem(IFunctionCallNode node, String functionName)
+		public NoStringEventNameLinterProblem(IFunctionCallNode node, String functionName)
 		{
 			super(node.getArgumentNodes()[0]);
 			this.functionName = functionName;
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoThisInClosureRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoThisInClosureRule.java
index 38db15c16..fa9dfbd0c 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoThisInClosureRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoThisInClosureRule.java
@@ -34,6 +34,7 @@ import org.apache.royale.compiler.tree.as.IFunctionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for use of the 'this' keyword in closures.
@@ -75,7 +76,7 @@ public class NoThisInClosureRule extends LinterRule {
 		return null;
 	}
 
-	public static class NoThisInClosureLinterProblem extends CompilerProblem {
+	public static class NoThisInClosureLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Closure must not contain 'this' keyword";
 
 		public NoThisInClosureLinterProblem(IASToken token)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoTraceRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoTraceRule.java
index 39ee54e5d..daf7f5543 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoTraceRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoTraceRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check for calls to the 'trace()' function.
@@ -57,7 +58,7 @@ public class NoTraceRule extends LinterRule {
 		problems.add(new NoTraceLinterProblem(functionCallNode));
 	}
 
-	public static class NoTraceLinterProblem extends CompilerProblem {
+	public static class NoTraceLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not call trace() function";
 
 		public NoTraceLinterProblem(IFunctionCallNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoVoidOperatorRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoVoidOperatorRule.java
index 76e7e7d13..5f4c71bdf 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoVoidOperatorRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoVoidOperatorRule.java
@@ -31,6 +31,7 @@ import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for uses of 'void' operator. Using 'void' as return type is allowed.
@@ -53,7 +54,7 @@ public class NoVoidOperatorRule extends LinterRule {
 		problems.add(new NoVoidOperatorLinterProblem(unaryOperatorNode));
 	}
 
-	public static class NoVoidOperatorLinterProblem extends CompilerProblem {
+	public static class NoVoidOperatorLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not use 'void' operator";
 
 		public NoVoidOperatorLinterProblem(IUnaryOperatorNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/NoWildcardImportRule.java b/linter/src/main/java/org/apache/royale/linter/rules/NoWildcardImportRule.java
index 62b479112..6ed33246b 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/NoWildcardImportRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/NoWildcardImportRule.java
@@ -30,6 +30,7 @@ import org.apache.royale.compiler.tree.as.IImportNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check for import statements that import the entire package.
@@ -51,7 +52,7 @@ public class NoWildcardImportRule extends LinterRule {
 		problems.add(new NoWildcardImportLinterProblem(importNode));
 	}
 
-	public static class NoWildcardImportLinterProblem extends CompilerProblem {
+	public static class NoWildcardImportLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not use wildcard import";
 
 		public NoWildcardImportLinterProblem(IImportNode node)
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 388bd7a94..5301d3c1e 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
@@ -27,6 +27,8 @@ 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)'.
@@ -41,7 +43,7 @@ public class NoWithRule extends LinterRule {
 		return result;
 	}
 
-	public static class NoWithLinterProblem extends CompilerProblem {
+	public static class NoWithLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not use 'with' statement";
 
 		public NoWithLinterProblem(IASToken token)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/OverrideContainsOnlySuperCallRule.java b/linter/src/main/java/org/apache/royale/linter/rules/OverrideContainsOnlySuperCallRule.java
index 2138aed72..1b0d9a13a 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/OverrideContainsOnlySuperCallRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/OverrideContainsOnlySuperCallRule.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.tree.as.IScopedNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that an overridden function contains more than a call to super.
@@ -89,7 +90,7 @@ public class OverrideContainsOnlySuperCallRule extends LinterRule {
 		problems.add(new OverrideContainsOnlySuperCallLinterProblem(functionNode));
 	}
 
-	public static class OverrideContainsOnlySuperCallLinterProblem extends CompilerProblem {
+	public static class OverrideContainsOnlySuperCallLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Method override '${functionName}' must contain more than call to 'super.${functionName}'";
 
 		public OverrideContainsOnlySuperCallLinterProblem(IFunctionNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/PackageNameRule.java b/linter/src/main/java/org/apache/royale/linter/rules/PackageNameRule.java
index de50e9a4d..9aaf7a8dd 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/PackageNameRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/PackageNameRule.java
@@ -32,6 +32,7 @@ import org.apache.royale.compiler.tree.as.IPackageNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that package names match a specific pattern.
@@ -66,7 +67,7 @@ public class PackageNameRule extends LinterRule {
 		problems.add(new PackageNameLinterProblem(packageNode, thePattern));
 	}
 
-	public static class PackageNameLinterProblem extends CompilerProblem {
+	public static class PackageNameLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Package name '${packageName}' does not match the pattern '${pattern}'";
 
 		public PackageNameLinterProblem(IPackageNode node, Pattern pattern)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/StaticConstantsRule.java b/linter/src/main/java/org/apache/royale/linter/rules/StaticConstantsRule.java
index 59ddba9a9..bab41c9c6 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/StaticConstantsRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/StaticConstantsRule.java
@@ -34,6 +34,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Checks for constants that are declared on a class, but are not static.
@@ -63,7 +64,7 @@ public class StaticConstantsRule extends LinterRule {
 		problems.add(new StaticConstantsLinterProblem(variableNode));
 	}
 
-	public static class StaticConstantsLinterProblem extends CompilerProblem {
+	public static class StaticConstantsLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Constant must be static";
 
 		public StaticConstantsLinterProblem(IVariableNode node)
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 457617cbf..4ba214e8a 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
@@ -28,6 +28,8 @@ import org.apache.royale.compiler.problems.CompilerProblem;
 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 '==='
@@ -46,7 +48,7 @@ public class StrictEqualityRule extends LinterRule {
 		return result;
 	}
 
-	public static class StrictEqualityLinterProblem extends CompilerProblem {
+	public static class StrictEqualityLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must use ${requiredTokenText} instead of ${tokenText}";
 
 		public StrictEqualityLinterProblem(IASToken token)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/SwitchWithoutDefaultRule.java b/linter/src/main/java/org/apache/royale/linter/rules/SwitchWithoutDefaultRule.java
index 3a9a7b667..fa30f1546 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/SwitchWithoutDefaultRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/SwitchWithoutDefaultRule.java
@@ -31,6 +31,7 @@ import org.apache.royale.compiler.tree.as.ITerminalNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check for 'switch' statements that are missing a 'default' clause.
@@ -53,7 +54,7 @@ public class SwitchWithoutDefaultRule extends LinterRule {
 		problems.add(new SwitchWithoutDefaultLinterProblem(switchNode));
 	}
 
-	public static class SwitchWithoutDefaultLinterProblem extends CompilerProblem {
+	public static class SwitchWithoutDefaultLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Missing 'default' clause in 'switch' statement";
 
 		public SwitchWithoutDefaultLinterProblem(ISwitchNode node)
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/UnsafeNegationRule.java b/linter/src/main/java/org/apache/royale/linter/rules/UnsafeNegationRule.java
index ab766f584..9f74ad101 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/UnsafeNegationRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/UnsafeNegationRule.java
@@ -34,6 +34,7 @@ import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that the left side of in, is, and instanceof is not negated unsafely.
@@ -67,7 +68,7 @@ public class UnsafeNegationRule extends LinterRule {
 		problems.add(new UnsafeNegationLinterProblem(binaryOperatorNode));
 	}
 
-	public static class UnsafeNegationLinterProblem extends CompilerProblem {
+	public static class UnsafeNegationLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Must not use negation on left side of in, is, and instanceof operators. Did you mean to use parentheses?";
 
 		public UnsafeNegationLinterProblem(IASNode node) {
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/ValidTypeofRule.java b/linter/src/main/java/org/apache/royale/linter/rules/ValidTypeofRule.java
index 0e3821597..1eb9eeb89 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/ValidTypeofRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/ValidTypeofRule.java
@@ -38,6 +38,7 @@ import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that an array literal contains no empty slots (multiple repeating
@@ -97,7 +98,7 @@ public class ValidTypeofRule extends LinterRule {
 		problems.add(new ValidTypeofLinterProblem(stringLiteral));
 	}
 
-	public static class ValidTypeofLinterProblem extends CompilerProblem {
+	public static class ValidTypeofLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "String '${value}' is not a valid result for typeof operator";
 
 		public ValidTypeofLinterProblem(ILiteralNode node) {
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/VariablesOnTopRule.java b/linter/src/main/java/org/apache/royale/linter/rules/VariablesOnTopRule.java
index a6ae31f94..7ef51d642 100644
--- a/linter/src/main/java/org/apache/royale/linter/rules/VariablesOnTopRule.java
+++ b/linter/src/main/java/org/apache/royale/linter/rules/VariablesOnTopRule.java
@@ -33,6 +33,7 @@ import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.linter.LinterRule;
 import org.apache.royale.linter.NodeVisitor;
 import org.apache.royale.linter.TokenQuery;
+import org.apache.royale.linter.problems.ILinterProblem;
 
 /**
  * Check that variables are always declared at the top of a function.
@@ -75,7 +76,7 @@ public class VariablesOnTopRule extends LinterRule {
 		return afterNonVariable;
 	}
 
-	public static class VariablesOnTopLinterProblem extends CompilerProblem {
+	public static class VariablesOnTopLinterProblem extends CompilerProblem implements ILinterProblem {
 		public static final String DESCRIPTION = "Variable name '${varName}' must be declared at the top of this function";
 
 		public VariablesOnTopLinterProblem(IVariableNode node)