diff options
author | Daniel Grunwald <daniel@danielgrunwald.de> | 2012-05-16 19:05:04 +0400 |
---|---|---|
committer | Daniel Grunwald <daniel@danielgrunwald.de> | 2012-05-16 19:05:04 +0400 |
commit | 4d07b33b4427ff8d74cb760ba6104184cd586a15 (patch) | |
tree | eb40232ad618204da0d7234993bd8303a8bb541e /ICSharpCode.NRefactory.ConsistencyCheck | |
parent | 3745ade65fa4651d7315d98041be217f0686411a (diff) |
CSharpAstResolver now can resolve type members even when no parsedFile is specified.
This is useful for analyzing generated code that does not have accurate StartLocation/EndLocation assigned.
Diffstat (limited to 'ICSharpCode.NRefactory.ConsistencyCheck')
3 files changed, 50 insertions, 15 deletions
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs b/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs index 869b98a4..b93c60f9 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs @@ -57,10 +57,10 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck solution.AllFiles.Count(), solution.Projects.Count); - using (new Timer("ID String test... ")) - IDStringConsistencyCheck.Run(solution); + //using (new Timer("ID String test... ")) IDStringConsistencyCheck.Run(solution); //RunTestOnAllFiles("Roundtripping test", RoundtripTest.RunTest); RunTestOnAllFiles("Resolver test", ResolverTest.RunTest); + RunTestOnAllFiles("Resolver test (no parsed file)", ResolverTest.RunTestWithoutParsedFile); RunTestOnAllFiles("Resolver test (randomized order)", RandomizedOrderResolverTest.RunTest); new FindReferencesConsistencyCheck(solution).Run(); diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/RandomizedOrderResolverTest.cs b/ICSharpCode.NRefactory.ConsistencyCheck/RandomizedOrderResolverTest.cs index 4c1ad1f7..d6f9390b 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/RandomizedOrderResolverTest.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/RandomizedOrderResolverTest.cs @@ -147,7 +147,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck return false; } - bool IsEqualResolveResult(ResolveResult rr1, ResolveResult rr2) + internal static bool IsEqualResolveResult(ResolveResult rr1, ResolveResult rr2) { if (rr1 == rr2) return true; @@ -169,7 +169,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck return eq; } - bool Compare(object val1, object val2, Type type) + static bool Compare(object val1, object val2, Type type) { if (val1 == val2) return true; @@ -205,7 +205,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck } } - bool IsEqualResolverState(CSharpResolver r1, CSharpResolver r2) + internal static bool IsEqualResolverState(CSharpResolver r1, CSharpResolver r2) { if (r1.CheckForOverflow != r2.CheckForOverflow) return false; @@ -226,7 +226,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck return r1.LocalVariables.Zip(r2.LocalVariables, IsEqualVariable).All(_ => _); } - bool IsEqualVariable(IVariable v1, IVariable v2) + internal static bool IsEqualVariable(IVariable v1, IVariable v2) { return object.Equals(v1.ConstantValue, v2.ConstantValue) && v1.IsConst == v2.IsConst diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs b/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs index a20e2613..59f156eb 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs @@ -29,7 +29,7 @@ using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.ConsistencyCheck { /// <summary> - /// Description of ResolverTest. + /// Validates that no compile errors are found in valid code. /// </summary> public class ResolverTest { @@ -38,10 +38,10 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck CSharpAstResolver resolver = new CSharpAstResolver(file.Project.Compilation, file.CompilationUnit, file.ParsedFile); var navigator = new ValidatingResolveAllNavigator(file.FileName); resolver.ApplyNavigator(navigator, CancellationToken.None); - navigator.Validate(file.CompilationUnit); + navigator.Validate(resolver, file.CompilationUnit); } - sealed class ValidatingResolveAllNavigator : IResolveVisitorNavigator + class ValidatingResolveAllNavigator : IResolveVisitorNavigator { string fileName; bool allowErrors; @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck this.allowErrors = (fileName.Contains(".xaml") || File.Exists(Path.ChangeExtension(fileName, ".xaml")) || fileName.EndsWith("AvalonDockLayout.cs") || fileName.EndsWith("ResourcesFileTreeNode.cs") || fileName.EndsWith("ChangeMarkerMargin.cs")); } - HashSet<AstNode> resolvedNodes = new HashSet<AstNode>(); + Dictionary<AstNode, ResolveResult> resolvedNodes = new Dictionary<AstNode, ResolveResult>(); HashSet<AstNode> nodesWithConversions = new HashSet<AstNode>(); public ResolveVisitorNavigationMode Scan(AstNode node) @@ -62,10 +62,11 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck return ResolveVisitorNavigationMode.Resolve; } - public void Resolved(AstNode node, ResolveResult result) + public virtual void Resolved(AstNode node, ResolveResult result) { - if (!resolvedNodes.Add(node)) + if (resolvedNodes.ContainsKey(node)) throw new InvalidOperationException("Duplicate Resolved() call"); + resolvedNodes.Add(node, result); if (CSharpAstResolver.IsUnresolvableNode(node)) throw new InvalidOperationException("Resolved unresolvable node"); @@ -74,7 +75,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck } } - public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + public virtual void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) { if (!nodesWithConversions.Add(expression)) throw new InvalidOperationException("Duplicate ProcessConversion() call"); @@ -83,13 +84,47 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck } } - public void Validate(CompilationUnit cu) + public virtual void Validate(CSharpAstResolver resolver, CompilationUnit cu) { - foreach (AstNode node in cu.DescendantsAndSelf.Except(resolvedNodes)) { + foreach (AstNode node in cu.DescendantsAndSelf.Except(resolvedNodes.Keys)) { if (!CSharpAstResolver.IsUnresolvableNode(node)) { Console.WriteLine("Forgot to resolve " + node); } } + foreach (var pair in resolvedNodes) { + if (resolver.Resolve(pair.Key) != pair.Value) + throw new InvalidOperationException("Inconsistent result"); + } + } + } + + public static void RunTestWithoutParsedFile(CSharpFile file) + { + CSharpAstResolver originalResolver = new CSharpAstResolver(file.Project.Compilation, file.CompilationUnit, file.ParsedFile); + originalResolver.ApplyNavigator(new ValidatingResolveAllNavigator(file.FileName), CancellationToken.None); + CSharpAstResolver resolver = new CSharpAstResolver(file.Project.Compilation, file.CompilationUnit); + var navigator = new ComparingResolveAllNavigator(originalResolver); + resolver.ApplyNavigator(navigator, CancellationToken.None); + navigator.Validate(resolver, file.CompilationUnit); + } + + sealed class ComparingResolveAllNavigator : ValidatingResolveAllNavigator + { + readonly CSharpAstResolver originalResolver; + + public ComparingResolveAllNavigator(CSharpAstResolver originalResolver) + : base(originalResolver.ParsedFile.FileName) + { + this.originalResolver = originalResolver; + } + + public override void Resolved(AstNode node, ResolveResult result) + { + base.Resolved(node, result); + ResolveResult originalResult = originalResolver.Resolve(node); + if (!RandomizedOrderResolverTest.IsEqualResolveResult(originalResult, result)) { + Console.WriteLine("Compiler error at " + node.GetRegion().FileName + ":" + node.StartLocation + ": Should be " + originalResult + " but was " + result); + } } } } |