diff --git a/.gitignore b/.gitignore
index 1027b084e5..0031dcbe29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+bin
+obj
/lib/*.dll
/ICSharpCode.NRefactory.Tests/PartCover/*
_ReSharper*/*
diff --git a/ICSharpCode.NRefactory.CSharp.AstVerifier/.gitignore b/ICSharpCode.NRefactory.CSharp.AstVerifier/.gitignore
deleted file mode 100644
index 9ce745d95d..0000000000
--- a/ICSharpCode.NRefactory.CSharp.AstVerifier/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-
-bin/
-obj/
\ No newline at end of file
diff --git a/ICSharpCode.NRefactory.CSharp/.gitignore b/ICSharpCode.NRefactory.CSharp/.gitignore
deleted file mode 100644
index 9ce745d95d..0000000000
--- a/ICSharpCode.NRefactory.CSharp/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-
-bin/
-obj/
\ No newline at end of file
diff --git a/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs
index ec01a9e406..0bfc1c1d76 100644
--- a/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs
+++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs
@@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp
public class ArrayInitializerExpression : Expression
{
///
- /// For ease of use purposes in the resolver the ast representation
+ /// For ease of use purposes in the resolver the ast representation
/// of { a, b, c } is { {a}, {b}, {c} }.
/// If IsSingleElement is true then this array initializer expression is a generated one.
/// That has no meaning in the source code (and contains no brace tokens).
@@ -73,7 +73,7 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
}
-
+
public override T AcceptVisitor (IAstVisitor visitor)
{
return default (T);
@@ -107,7 +107,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitArrayInitializerExpression (this);
}
-
+
public override T AcceptVisitor (IAstVisitor visitor)
{
return visitor.VisitArrayInitializerExpression (this);
@@ -138,8 +138,54 @@ namespace ICSharpCode.NRefactory.CSharp
return true;
}
}
-
+
+ }
+
+ #region PatternPlaceholder
+ public static implicit operator ArrayInitializerExpression(PatternMatching.Pattern pattern)
+ {
+ return pattern != null ? new PatternPlaceholder(pattern) : null;
+ }
+
+ sealed class PatternPlaceholder : ArrayInitializerExpression, PatternMatching.INode
+ {
+ readonly PatternMatching.Pattern child;
+
+ public PatternPlaceholder(PatternMatching.Pattern child)
+ {
+ this.child = child;
+ }
+
+ public override NodeType NodeType {
+ get { return NodeType.Pattern; }
+ }
+
+ public override void AcceptVisitor (IAstVisitor visitor)
+ {
+ visitor.VisitPatternPlaceholder(this, child);
+ }
+
+ public override T AcceptVisitor (IAstVisitor visitor)
+ {
+ return visitor.VisitPatternPlaceholder(this, child);
+ }
+
+ public override S AcceptVisitor(IAstVisitor visitor, T data)
+ {
+ return visitor.VisitPatternPlaceholder(this, child, data);
+ }
+
+ protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
+ {
+ return child.DoMatch(other, match);
+ }
+
+ bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo)
+ {
+ return child.DoMatchCollection(role, pos, match, backtrackingInfo);
+ }
}
+ #endregion
}
}
diff --git a/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs b/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs
index 2fc1405dee..2906696b36 100644
--- a/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs
+++ b/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs
@@ -146,13 +146,13 @@ namespace ICSharpCode.NRefactory.CSharp
///
/// Converts this syntax tree into a parsed file that can be stored in the type system.
///
- public CSharpParsedFile ToTypeSystem ()
+ public CSharpUnresolvedFile ToTypeSystem ()
{
if (string.IsNullOrEmpty (this.FileName))
throw new InvalidOperationException ("Cannot use ToTypeSystem() on a syntax tree without file name.");
var v = new TypeSystemConvertVisitor (this.FileName);
v.VisitSyntaxTree (this);
- return v.ParsedFile;
+ return v.UnresolvedFile;
}
public static SyntaxTree Parse (string program, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken))
diff --git a/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs b/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
index a890c1ea41..fccba4622f 100644
--- a/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
+++ b/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
@@ -31,15 +31,15 @@ namespace ICSharpCode.NRefactory.CSharp
public class CSharpProjectContent : IProjectContent
{
string assemblyName;
+ string projectFileName;
string location;
- Dictionary parsedFiles;
+ Dictionary unresolvedFiles;
List assemblyReferences;
CompilerSettings compilerSettings;
public CSharpProjectContent()
{
- this.assemblyName = string.Empty;
- this.parsedFiles = new Dictionary(Platform.FileNameComparer);
+ this.unresolvedFiles = new Dictionary(Platform.FileNameComparer);
this.assemblyReferences = new List();
this.compilerSettings = new CompilerSettings();
compilerSettings.Freeze();
@@ -48,20 +48,25 @@ namespace ICSharpCode.NRefactory.CSharp
protected CSharpProjectContent(CSharpProjectContent pc)
{
this.assemblyName = pc.assemblyName;
+ this.projectFileName = pc.projectFileName;
this.location = pc.location;
- this.parsedFiles = new Dictionary(pc.parsedFiles, Platform.FileNameComparer);
+ this.unresolvedFiles = new Dictionary(pc.unresolvedFiles, Platform.FileNameComparer);
this.assemblyReferences = new List(pc.assemblyReferences);
this.compilerSettings = pc.compilerSettings;
}
- public IEnumerable Files {
- get { return parsedFiles.Values; }
+ public IEnumerable Files {
+ get { return unresolvedFiles.Values; }
}
public IEnumerable AssemblyReferences {
get { return assemblyReferences; }
}
+ public string ProjectFileName {
+ get { return projectFileName; }
+ }
+
public string AssemblyName {
get { return assemblyName; }
}
@@ -96,10 +101,10 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
- public IParsedFile GetFile(string fileName)
+ public IUnresolvedFile GetFile(string fileName)
{
- IParsedFile file;
- if (parsedFiles.TryGetValue(fileName, out file))
+ IUnresolvedFile file;
+ if (unresolvedFiles.TryGetValue(fileName, out file))
return file;
else
return null;
@@ -129,11 +134,18 @@ namespace ICSharpCode.NRefactory.CSharp
pc.assemblyName = newAssemblyName;
return pc;
}
+
+ public IProjectContent SetProjectFileName(string newProjectFileName)
+ {
+ CSharpProjectContent pc = Clone();
+ pc.projectFileName = newProjectFileName;
+ return pc;
+ }
- public IProjectContent SetLocation(string location)
+ public IProjectContent SetLocation(string newLocation)
{
CSharpProjectContent pc = Clone();
- pc.location = location;
+ pc.location = newLocation;
return pc;
}
@@ -148,6 +160,11 @@ namespace ICSharpCode.NRefactory.CSharp
}
public IProjectContent AddAssemblyReferences(IEnumerable references)
+ {
+ return AddAssemblyReferences(references.ToArray());
+ }
+
+ public IProjectContent AddAssemblyReferences(params IAssemblyReference[] references)
{
CSharpProjectContent pc = Clone();
pc.assemblyReferences.AddRange(references);
@@ -155,13 +172,62 @@ namespace ICSharpCode.NRefactory.CSharp
}
public IProjectContent RemoveAssemblyReferences(IEnumerable references)
+ {
+ return RemoveAssemblyReferences(references.ToArray());
+ }
+
+ public IProjectContent RemoveAssemblyReferences(params IAssemblyReference[] references)
{
CSharpProjectContent pc = Clone();
- pc.assemblyReferences.RemoveAll(r => references.Contains(r));
+ foreach (var r in references)
+ pc.assemblyReferences.Remove(r);
return pc;
}
- public IProjectContent UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile)
+ ///
+ /// Adds the specified files to the project content.
+ /// If a file with the same name already exists, updated the existing file.
+ ///
+ public IProjectContent AddOrUpdateFiles(IEnumerable newFiles)
+ {
+ CSharpProjectContent pc = Clone();
+ foreach (var file in newFiles) {
+ pc.unresolvedFiles[file.FileName] = file;
+ }
+ return pc;
+ }
+
+ ///
+ /// Adds the specified files to the project content.
+ /// If a file with the same name already exists, this method updates the existing file.
+ ///
+ public IProjectContent AddOrUpdateFiles(params IUnresolvedFile[] newFiles)
+ {
+ return AddOrUpdateFiles((IEnumerable)newFiles);
+ }
+
+ ///
+ /// Removes the files with the specified names.
+ ///
+ public IProjectContent RemoveFiles(IEnumerable fileNames)
+ {
+ CSharpProjectContent pc = Clone();
+ foreach (var fileName in fileNames) {
+ pc.unresolvedFiles.Remove(fileName);
+ }
+ return pc;
+ }
+
+ ///
+ /// Removes the files with the specified names.
+ ///
+ public IProjectContent RemoveFiles(params string[] fileNames)
+ {
+ return RemoveFiles((IEnumerable)fileNames);
+ }
+
+ [Obsolete("Use RemoveFiles/AddOrUpdateFiles instead")]
+ public IProjectContent UpdateProjectContent(IUnresolvedFile oldFile, IUnresolvedFile newFile)
{
if (oldFile == null && newFile == null)
return this;
@@ -171,23 +237,24 @@ namespace ICSharpCode.NRefactory.CSharp
}
CSharpProjectContent pc = Clone();
if (newFile == null)
- pc.parsedFiles.Remove(oldFile.FileName);
+ pc.unresolvedFiles.Remove(oldFile.FileName);
else
- pc.parsedFiles[newFile.FileName] = newFile;
+ pc.unresolvedFiles[newFile.FileName] = newFile;
return pc;
}
- public IProjectContent UpdateProjectContent(IEnumerable oldFiles, IEnumerable newFiles)
+ [Obsolete("Use RemoveFiles/AddOrUpdateFiles instead")]
+ public IProjectContent UpdateProjectContent(IEnumerable oldFiles, IEnumerable newFiles)
{
CSharpProjectContent pc = Clone();
if (oldFiles != null) {
foreach (var oldFile in oldFiles) {
- pc.parsedFiles.Remove(oldFile.FileName);
+ pc.unresolvedFiles.Remove(oldFile.FileName);
}
}
if (newFiles != null) {
foreach (var newFile in newFiles) {
- pc.parsedFiles.Add(newFile.FileName, newFile);
+ pc.unresolvedFiles.Add(newFile.FileName, newFile);
}
}
return pc;
diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
index 6f518094fe..553974c7a4 100644
--- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
+++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
@@ -723,7 +723,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// var astResolver = new CSharpAstResolver(
// GetState(),
// identifierStart.Unit,
- // CSharpParsedFile
+ // CSharpUnresolvedFile
// );
//
// foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)n)) {
@@ -1172,7 +1172,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (csResolver == null) {
if (node != null) {
csResolver = GetState();
- //var astResolver = new CSharpAstResolver (csResolver, node, xp != null ? xp.Item1 : CSharpParsedFile);
+ //var astResolver = new CSharpAstResolver (csResolver, node, xp != null ? xp.Item1 : CSharpUnresolvedFile);
try {
//csResolver = astResolver.GetResolverStateBefore (node);
diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
index 8e36405a45..fa71c629e6 100644
--- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
+++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
@@ -494,13 +494,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
state.CurrentMember = currentMember;
state.CurrentTypeDefinition = currentType;
- state.CurrentUsingScope = CSharpParsedFile.GetUsingScope (location);
+ state.CurrentUsingScope = CSharpUnresolvedFile.GetUsingScope (location);
if (state.CurrentMember != null) {
var node = Unit.GetNodeAt (location);
if (node == null)
return state;
var navigator = new NodeListResolveVisitorNavigator (new[] { node });
- var visitor = new ResolveVisitor (state, CSharpParsedFile, navigator);
+ var visitor = new ResolveVisitor (state, CSharpUnresolvedFile, navigator);
Unit.AcceptVisitor (visitor, null);
try {
var newState = visitor.GetResolverStateBefore (node);
diff --git a/ICSharpCode.NRefactory.CSharp/Completion/ICompletionContextProvider.cs b/ICSharpCode.NRefactory.CSharp/Completion/ICompletionContextProvider.cs
index b477dc1bbf..91ee3f2bba 100644
--- a/ICSharpCode.NRefactory.CSharp/Completion/ICompletionContextProvider.cs
+++ b/ICSharpCode.NRefactory.CSharp/Completion/ICompletionContextProvider.cs
@@ -1,4 +1,4 @@
-//
+//
// IMemberProvider.cs
//
// Author:
@@ -45,16 +45,16 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
public class DefaultCompletionContextProvider : ICompletionContextProvider
{
readonly IDocument document;
- readonly CSharpParsedFile parsedFile;
+ readonly CSharpUnresolvedFile unresolvedFile;
- public DefaultCompletionContextProvider (IDocument document, CSharpParsedFile parsedFile)
+ public DefaultCompletionContextProvider (IDocument document, CSharpUnresolvedFile unresolvedFile)
{
if (document == null)
throw new ArgumentNullException("document");
- if (parsedFile == null)
- throw new ArgumentNullException("parsedFile");
+ if (unresolvedFile == null)
+ throw new ArgumentNullException("unresolvedFile");
this.document = document;
- this.parsedFile = parsedFile;
+ this.unresolvedFile = unresolvedFile;
}
public void GetCurrentMembers(int offset, out IUnresolvedTypeDefinition currentType, out IUnresolvedMember currentMember)
@@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
currentType = null;
- foreach (var type in parsedFile.TopLevelTypeDefinitions) {
+ foreach (var type in unresolvedFile.TopLevelTypeDefinitions) {
if (type.Region.Begin < location)
currentType = type;
}
@@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
public CSharpAstResolver GetResolver (CSharpResolver resolver, AstNode rootNode)
{
- return new CSharpAstResolver (resolver, rootNode, parsedFile);
+ return new CSharpAstResolver (resolver, rootNode, unresolvedFile);
}
diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
index 05220de763..93dbc6fe18 100644
--- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
+++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
@@ -18,8 +18,9 @@
..\ICSharpCode.NRefactory.snk
False
File
- ..\ICSharpCode.NRefactory\bin\$(Configuration)\ICSharpCode.NRefactory.CSharp.xml
+ ..\bin\$(Configuration)\ICSharpCode.NRefactory.CSharp.xml
1591,1587,1570
+ ..\bin\$(Configuration)\
AnyCPU
@@ -29,13 +30,11 @@
4096
- ..\ICSharpCode.NRefactory\bin\Debug\
False
False
DEBUG;TRACE;FULL_AST
- ..\ICSharpCode.NRefactory\bin\Release\
True
False
TRACE;FULL_AST
@@ -48,7 +47,6 @@
True
- ..\ICSharpCode.NRefactory\bin\Debug\
False
False
DEBUG;TRACE;FULL_AST;NET45
@@ -59,7 +57,6 @@
True
- ..\ICSharpCode.NRefactory\bin\Release\
True
False
TRACE;FULL_AST;NET45
@@ -303,7 +300,7 @@
-
+
diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
index ca3e70ab5b..b7db647027 100644
--- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
+++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
@@ -64,19 +64,19 @@ namespace ICSharpCode.NRefactory.CSharp
///
/// The input syntax tree.
/// The current compilation.
- /// CSharpParsedFile, used for resolving.
+ /// CSharpUnresolvedFile, used for resolving.
/// Converted CodeCompileUnit
///
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
///
- public CodeCompileUnit Convert(ICompilation compilation, SyntaxTree syntaxTree, CSharpParsedFile parsedFile)
+ public CodeCompileUnit Convert(ICompilation compilation, SyntaxTree syntaxTree, CSharpUnresolvedFile unresolvedFile)
{
if (syntaxTree == null)
throw new ArgumentNullException("syntaxTree");
if (compilation == null)
throw new ArgumentNullException("compilation");
- CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, parsedFile);
+ CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFile);
return (CodeCompileUnit)Convert(syntaxTree, resolver);
}
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs
index 2f5a61be34..0b7ac5c27f 100644
--- a/ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs
@@ -73,9 +73,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
}
- public virtual CSharpParsedFile ParsedFile {
+ public virtual CSharpUnresolvedFile UnresolvedFile {
get {
- return resolver.ParsedFile;
+ return resolver.UnresolvedFile;
}
}
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs
index 090624c0ec..fe3c1a6c8b 100644
--- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs
@@ -328,7 +328,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
bool HasDependencyCheck(FindReferences referenceFinder, LocalResolveResult localResolveResult)
{
bool result = false;
- referenceFinder.FindLocalReferences(localResolveResult.Variable, context.ParsedFile,
+ referenceFinder.FindLocalReferences(localResolveResult.Variable, context.UnresolvedFile,
(SyntaxTree)context.RootNode, context.Compilation,
(node, resolveResult) => {
result |= VariableHasBeenConverted(localResolveResult.Variable);
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/InlineLocalVariableAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/InlineLocalVariableAction.cs
index 263e5570f8..a8bec696c8 100644
--- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/InlineLocalVariableAction.cs
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/InlineLocalVariableAction.cs
@@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
yield break;
}
yield return new CodeAction(context.TranslateString("Inline local variable"), script => {
- refFinder.FindLocalReferences(resolveResult.Variable, context.ParsedFile, unit, context.Compilation, (n, r) => script.Replace(n, initializer.Initializer.Clone()), default(CancellationToken));
+ refFinder.FindLocalReferences(resolveResult.Variable, context.UnresolvedFile, unit, context.Compilation, (n, r) => script.Replace(n, initializer.Initializer.Clone()), default(CancellationToken));
script.Remove(node);
});
}
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/MoveToOuterScopeAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/MoveToOuterScopeAction.cs
index ad2bc6826c..f04be04710 100644
--- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/MoveToOuterScopeAction.cs
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/MoveToOuterScopeAction.cs
@@ -105,7 +105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
bool referenceFound = false;
var variable = localResolveResult.Variable;
var syntaxTree = context.RootNode as SyntaxTree;
- referenceFinder.FindLocalReferences(localResolveResult.Variable, context.ParsedFile, syntaxTree,
+ referenceFinder.FindLocalReferences(localResolveResult.Variable, context.UnresolvedFile, syntaxTree,
context.Compilation, (node, nodeResolveResult) => {
if (node.StartLocation > firstSearchNode.StartLocation && node.EndLocation < targetNode.StartLocation)
referenceFound = true;
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveRedundantCatchTypeAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveRedundantCatchTypeAction.cs
index 68ab7b3e7f..fd6817c955 100644
--- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveRedundantCatchTypeAction.cs
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/RemoveRedundantCatchTypeAction.cs
@@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
int referencesFound = 0;
var findRef = new FindReferences();
- findRef.FindLocalReferences(variable, context.ParsedFile, syntaxTree, context.Compilation, (n, entity) => {
+ findRef.FindLocalReferences(variable, context.UnresolvedFile, syntaxTree, context.Compilation, (n, entity) => {
referencesFound++;
}, CancellationToken.None);
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ValueParameterUnusedIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ValueParameterUnusedIssue.cs
index 6d2cc3d1b7..bef62511b1 100644
--- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ValueParameterUnusedIssue.cs
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ValueParameterUnusedIssue.cs
@@ -83,7 +83,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
bool referenceFound = false;
var findRef = new FindReferences();
var syntaxTree = (SyntaxTree)context.RootNode;
- findRef.FindLocalReferences(variable, context.ParsedFile, syntaxTree, context.Compilation, (n, entity) => {
+ findRef.FindLocalReferences(variable, context.UnresolvedFile, syntaxTree, context.Compilation, (n, entity) => {
if (n.StartLocation >= node.StartLocation && n.EndLocation <= node.EndLocation) {
referenceFound = true;
}
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs
index ae5d3478a1..6b33502c70 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs
@@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
readonly CSharpResolver initialResolverState;
readonly AstNode rootNode;
- readonly CSharpParsedFile parsedFile;
+ readonly CSharpUnresolvedFile unresolvedFile;
readonly ResolveVisitor resolveVisitor;
bool resolverInitialized;
@@ -42,20 +42,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Use this overload if you are resolving within a complete C# file.
///
/// The current compilation.
- /// The syntax tree corresponding to the specified parsed file.
- ///
- /// Optional: Result of the for the file being resolved.
+ /// The syntax tree to be resolved.
+ ///
+ /// Optional: Result of for the file being resolved.
///
- /// This is used for setting up the context on the resolver. The parsed file must be registered in the compilation.
+ /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation.
///
///
- /// When a parsedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify
+ /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify
/// member declarations in the AST with members in the type system.
- /// When no parsedFile is specified (null value for this parameter), the resolver will instead compare the
+ /// When no unresolvedFile is specified (null value for this parameter), the resolver will instead compare the
/// member's signature in the AST with the signature in the type system.
///
///
- public CSharpAstResolver(ICompilation compilation, SyntaxTree syntaxTree, CSharpParsedFile parsedFile = null)
+ public CSharpAstResolver(ICompilation compilation, SyntaxTree syntaxTree, CSharpUnresolvedFile unresolvedFile = null)
{
if (compilation == null)
throw new ArgumentNullException("compilation");
@@ -63,8 +63,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new ArgumentNullException("syntaxTree");
this.initialResolverState = new CSharpResolver(compilation);
this.rootNode = syntaxTree;
- this.parsedFile = parsedFile;
- this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile);
+ this.unresolvedFile = unresolvedFile;
+ this.resolveVisitor = new ResolveVisitor(initialResolverState, unresolvedFile);
}
///
@@ -72,20 +72,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Use this overload if you are resolving code snippets (not necessarily complete files).
///
/// The resolver state at the root node (to be more precise: just outside the root node).
- /// The root node of the resolved tree.
- ///
- /// Optional: Result of the for the file being resolved.
+ /// The root node of the tree to be resolved.
+ ///
+ /// Optional: Result of for the file being resolved.
///
- /// This is used for setting up the context on the resolver. The parsed file must be registered in the compilation.
+ /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation.
///
///
- /// When a parsedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify
+ /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify
/// member declarations in the AST with members in the type system.
- /// When no parsedFile is specified (null value for this parameter), the resolver will instead compare the
+ /// When no unresolvedFile is specified (null value for this parameter), the resolver will instead compare the
/// member's signature in the AST with the signature in the type system.
///
///
- public CSharpAstResolver(CSharpResolver resolver, AstNode rootNode, CSharpParsedFile parsedFile = null)
+ public CSharpAstResolver(CSharpResolver resolver, AstNode rootNode, CSharpUnresolvedFile unresolvedFile = null)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
@@ -93,8 +93,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new ArgumentNullException("rootNode");
this.initialResolverState = resolver;
this.rootNode = rootNode;
- this.parsedFile = parsedFile;
- this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile);
+ this.unresolvedFile = unresolvedFile;
+ this.resolveVisitor = new ResolveVisitor(initialResolverState, unresolvedFile);
}
///
@@ -119,11 +119,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
///
- /// Gets the parsed file used by this CSharpAstResolver.
+ /// Gets the unresolved file used by this CSharpAstResolver.
/// Can return null.
///
- public CSharpParsedFile ParsedFile {
- get { return parsedFile; }
+ public CSharpUnresolvedFile UnresolvedFile {
+ get { return unresolvedFile; }
}
///
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
index d754e1b30a..c269f581d1 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
@@ -290,7 +290,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
///
/// Gets the file names that possibly contain references to the element being searched for.
///
- public IEnumerable GetInterestingFiles(IFindReferenceSearchScope searchScope, ICompilation compilation)
+ public IEnumerable GetInterestingFiles(IFindReferenceSearchScope searchScope, ICompilation compilation)
{
if (searchScope == null)
throw new ArgumentNullException("searchScope");
@@ -303,47 +303,47 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeDefinition topLevelTypeDef = compilation.Import(searchScope.TopLevelTypeDefinition);
if (topLevelTypeDef == null) {
// This compilation cannot have references to the target entity.
- return EmptyList.Instance;
+ return EmptyList.Instance;
}
switch (searchScope.Accessibility) {
case Accessibility.None:
case Accessibility.Private:
if (topLevelTypeDef.ParentAssembly == compilation.MainAssembly)
- return topLevelTypeDef.Parts.Select(p => p.ParsedFile).OfType().Distinct();
+ return topLevelTypeDef.Parts.Select(p => p.UnresolvedFile).OfType().Distinct();
else
- return EmptyList.Instance;
+ return EmptyList.Instance;
case Accessibility.Protected:
return GetInterestingFilesProtected(topLevelTypeDef);
case Accessibility.Internal:
if (topLevelTypeDef.ParentAssembly.InternalsVisibleTo(compilation.MainAssembly))
- return pc.Files.OfType();
+ return pc.Files.OfType();
else
- return EmptyList.Instance;
+ return EmptyList.Instance;
case Accessibility.ProtectedAndInternal:
if (topLevelTypeDef.ParentAssembly.InternalsVisibleTo(compilation.MainAssembly))
return GetInterestingFilesProtected(topLevelTypeDef);
else
- return EmptyList.Instance;
+ return EmptyList.Instance;
case Accessibility.ProtectedOrInternal:
if (topLevelTypeDef.ParentAssembly.InternalsVisibleTo(compilation.MainAssembly))
- return pc.Files.OfType();
+ return pc.Files.OfType();
else
return GetInterestingFilesProtected(topLevelTypeDef);
default:
- return pc.Files.OfType();
+ return pc.Files.OfType();
}
} else {
- return pc.Files.OfType();
+ return pc.Files.OfType();
}
}
- IEnumerable GetInterestingFilesProtected(ITypeDefinition referencedTypeDefinition)
+ IEnumerable GetInterestingFilesProtected(ITypeDefinition referencedTypeDefinition)
{
return (from typeDef in referencedTypeDefinition.Compilation.MainAssembly.GetAllTypeDefinitions()
where typeDef.IsDerivedFrom(referencedTypeDefinition)
from part in typeDef.Parts
- select part.ParsedFile
- ).OfType().Distinct();
+ select part.UnresolvedFile
+ ).OfType().Distinct();
}
#endregion
@@ -352,35 +352,35 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Finds all references in the given file.
///
/// The search scope for which to look.
- /// The type system representation of the file being searched.
+ /// The type system representation of the file being searched.
/// The syntax tree of the file being searched.
/// The compilation for the project that contains the file.
/// Callback used to report the references that were found.
/// CancellationToken that may be used to cancel the operation.
- public void FindReferencesInFile(IFindReferenceSearchScope searchScope, CSharpParsedFile parsedFile, SyntaxTree syntaxTree,
+ public void FindReferencesInFile(IFindReferenceSearchScope searchScope, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree,
ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (searchScope == null)
throw new ArgumentNullException("searchScope");
- FindReferencesInFile(new[] { searchScope }, parsedFile, syntaxTree, compilation, callback, cancellationToken);
+ FindReferencesInFile(new[] { searchScope }, unresolvedFile, syntaxTree, compilation, callback, cancellationToken);
}
///
/// Finds all references in the given file.
///
/// The search scopes for which to look.
- /// The type system representation of the file being searched.
+ /// The type system representation of the file being searched.
/// The syntax tree of the file being searched.
/// The compilation for the project that contains the file.
/// Callback used to report the references that were found.
/// CancellationToken that may be used to cancel the operation.
- public void FindReferencesInFile(IList searchScopes, CSharpParsedFile parsedFile, SyntaxTree syntaxTree,
+ public void FindReferencesInFile(IList searchScopes, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree,
ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (searchScopes == null)
throw new ArgumentNullException("searchScopes");
- if (parsedFile == null)
- throw new ArgumentNullException("parsedFile");
+ if (unresolvedFile == null)
+ throw new ArgumentNullException("unresolvedFile");
if (syntaxTree == null)
throw new ArgumentNullException("syntaxTree");
if (compilation == null)
@@ -404,7 +404,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
cancellationToken.ThrowIfCancellationRequested();
combinedNavigator = new DetectSkippableNodesNavigator(combinedNavigator, syntaxTree);
cancellationToken.ThrowIfCancellationRequested();
- CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, parsedFile);
+ CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFile);
resolver.ApplyNavigator(combinedNavigator, cancellationToken);
foreach (var n in navigators) {
var frn = n as FindReferenceNavigator;
@@ -1171,19 +1171,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Finds all references of a given variable.
///
/// The variable for which to look.
- /// The type system representation of the file being searched.
+ /// The type system representation of the file being searched.
/// The syntax tree of the file being searched.
/// The compilation.
/// Callback used to report the references that were found.
/// Cancellation token that may be used to cancel the operation.
- public void FindLocalReferences(IVariable variable, CSharpParsedFile parsedFile, SyntaxTree syntaxTree,
+ public void FindLocalReferences(IVariable variable, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree,
ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (variable == null)
throw new ArgumentNullException("variable");
var searchScope = new SearchScope(c => new FindLocalReferencesNavigator(variable));
searchScope.declarationCompilation = compilation;
- FindReferencesInFile(searchScope, parsedFile, syntaxTree, compilation, callback, cancellationToken);
+ FindReferencesInFile(searchScope, unresolvedFile, syntaxTree, compilation, callback, cancellationToken);
}
class FindLocalReferencesNavigator : FindReferenceNavigator
@@ -1225,12 +1225,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Finds all references of a given type parameter.
///
/// The type parameter for which to look.
- /// The type system representation of the file being searched.
+ /// The type system representation of the file being searched.
/// The syntax tree of the file being searched.
/// The compilation.
/// Callback used to report the references that were found.
/// Cancellation token that may be used to cancel the operation.
- public void FindTypeParameterReferences(IType typeParameter, CSharpParsedFile parsedFile, SyntaxTree syntaxTree,
+ public void FindTypeParameterReferences(IType typeParameter, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree,
ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (typeParameter == null)
@@ -1240,7 +1240,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var searchScope = new SearchScope(c => new FindTypeParameterReferencesNavigator((ITypeParameter)typeParameter));
searchScope.declarationCompilation = compilation;
searchScope.accessibility = Accessibility.Private;
- FindReferencesInFile(searchScope, parsedFile, syntaxTree, compilation, callback, cancellationToken);
+ FindReferencesInFile(searchScope, unresolvedFile, syntaxTree, compilation, callback, cancellationToken);
}
class FindTypeParameterReferencesNavigator : FindReferenceNavigator
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
index ba407c76fa..e94ffa42a2 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
@@ -118,7 +118,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public void AddError(OverloadResolutionErrors newError)
{
this.Errors |= newError;
- this.ErrorCount++;
+ if (!IsApplicable(newError))
+ this.ErrorCount++;
}
}
@@ -130,6 +131,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Candidate bestCandidate;
Candidate bestCandidateAmbiguousWith;
IType[] explicitlyGivenTypeArguments;
+ bool bestCandidateWasValidated;
+ OverloadResolutionErrors bestCandidateValidationResult;
#region Constructor
public OverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null, CSharpConversions conversions = null)
@@ -155,6 +158,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
+ #region Input Properties
///
/// Gets/Sets whether the methods are extension methods that are being called using extension method syntax.
///
@@ -183,21 +187,36 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public IList Arguments {
get { return arguments; }
}
+ #endregion
#region AddCandidate
+ ///
+ /// Adds a candidate to overload resolution.
+ ///
+ /// The candidate member to add.
+ /// The errors that prevent the member from being applicable, if any.
+ /// Note: this method does not return errors that do not affect applicability.
public OverloadResolutionErrors AddCandidate(IParameterizedMember member)
{
return AddCandidate(member, OverloadResolutionErrors.None);
}
+ ///
+ /// Adds a candidate to overload resolution.
+ ///
+ /// The candidate member to add.
+ /// Additional errors that apply to the candidate.
+ /// This is used to represent errors during member lookup (e.g. OverloadResolutionErrors.Inaccessible)
+ /// in overload resolution.
+ /// The errors that prevent the member from being applicable, if any.
+ /// Note: this method does not return errors that do not affect applicability.
public OverloadResolutionErrors AddCandidate(IParameterizedMember member, OverloadResolutionErrors additionalErrors)
{
if (member == null)
throw new ArgumentNullException("member");
Candidate c = new Candidate(member, false);
- if (additionalErrors != OverloadResolutionErrors.None)
- c.AddError(additionalErrors);
+ c.AddError(additionalErrors);
if (CalculateCandidate(c)) {
//candidates.Add(c);
}
@@ -206,8 +225,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
&& member.Parameters[member.Parameters.Count - 1].IsParams)
{
Candidate expandedCandidate = new Candidate(member, true);
- if (additionalErrors != OverloadResolutionErrors.None)
- expandedCandidate.AddError(additionalErrors);
+ expandedCandidate.AddError(additionalErrors);
// consider expanded form only if it isn't obviously wrong
if (CalculateCandidate(expandedCandidate)) {
//candidates.Add(expandedCandidate);
@@ -219,11 +237,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return c.Errors;
}
- public static bool IsApplicable(OverloadResolutionErrors errors)
- {
- return (errors & ~OverloadResolutionErrors.AmbiguousMatch) == OverloadResolutionErrors.None;
- }
-
///
/// Calculates applicability etc. for the candidate.
///
@@ -236,6 +249,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
RunTypeInference(candidate);
CheckApplicability(candidate);
ConsiderIfNewCandidateIsBest(candidate);
+ ValidateMethodConstraints(candidate);
return true;
}
@@ -432,20 +446,36 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region Validate Constraints
+ OverloadResolutionErrors ValidateMethodConstraints(Candidate candidate)
+ {
+ // If type inference already failed, we won't check the constraints:
+ if ((candidate.Errors & OverloadResolutionErrors.TypeInferenceFailed) != 0)
+ return OverloadResolutionErrors.None;
+
+ IMethod method = candidate.Member as IMethod;
+ if (method == null || method.TypeParameters.Count == 0)
+ return OverloadResolutionErrors.None; // the method isn't generic
+ var substitution = GetSubstitution(candidate);
+ for (int i = 0; i < method.TypeParameters.Count; i++) {
+ if (!ValidateConstraints(method.TypeParameters[i], substitution.MethodTypeArguments[i], substitution))
+ return OverloadResolutionErrors.MethodConstraintsNotSatisfied;
+ }
+ return OverloadResolutionErrors.None;
+ }
+
///
/// Validates whether the given type argument satisfies the constraints for the given type parameter.
///
/// The type parameter.
/// The type argument.
/// The substitution that defines how type parameters are replaced with type arguments.
- /// The substitution is used to check constraints that depend on other type parameters (or recursively on the same type parameter).
+ /// The substitution is used to check constraints that depend on other type parameters (or recursively on the same type parameter).
+ /// May be null if no substitution should be used.
/// True if the constraints are satisfied; false otherwise.
- public static bool ValidateConstraints(ITypeParameter typeParameter, IType typeArgument, TypeVisitor substitution)
+ public static bool ValidateConstraints(ITypeParameter typeParameter, IType typeArgument, TypeVisitor substitution = null)
{
if (typeParameter == null)
throw new ArgumentNullException("typeParameter");
- if (typeParameter.Owner == null)
- throw new ArgumentNullException("typeParameter.Owner");
if (typeArgument == null)
throw new ArgumentNullException("typeArgument");
return ValidateConstraints(typeParameter, typeArgument, substitution, CSharpConversions.Get(typeParameter.Owner.Compilation));
@@ -490,6 +520,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region CheckApplicability
+ ///
+ /// Returns whether a candidate with the given errors is still considered to be applicable.
+ ///
+ public static bool IsApplicable(OverloadResolutionErrors errors)
+ {
+ const OverloadResolutionErrors errorsThatDoNotMatterForApplicability =
+ OverloadResolutionErrors.AmbiguousMatch | OverloadResolutionErrors.MethodConstraintsNotSatisfied;
+ return (errors & ~errorsThatDoNotMatterForApplicability) == OverloadResolutionErrors.None;
+ }
+
void CheckApplicability(Candidate candidate)
{
// C# 4.0 spec: §7.5.3.1 Applicable function member
@@ -697,6 +737,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
if (bestCandidate == null) {
bestCandidate = candidate;
+ bestCandidateWasValidated = false;
} else {
switch (BetterFunctionMember(candidate, bestCandidate)) {
case 0:
@@ -707,6 +748,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
break;
case 1:
bestCandidate = candidate;
+ bestCandidateWasValidated = false;
bestCandidateAmbiguousWith = null;
break;
// case 2: best candidate stays best
@@ -715,15 +757,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
+ #region Output Properties
public IParameterizedMember BestCandidate {
get { return bestCandidate != null ? bestCandidate.Member : null; }
}
+ ///
+ /// Returns the errors that apply to the best candidate.
+ /// This includes additional errors that do not affect applicability (e.g. AmbiguousMatch, MethodConstraintsNotSatisfied)
+ ///
public OverloadResolutionErrors BestCandidateErrors {
get {
if (bestCandidate == null)
return OverloadResolutionErrors.None;
- OverloadResolutionErrors err = bestCandidate.Errors;
+ if (!bestCandidateWasValidated) {
+ bestCandidateValidationResult = ValidateMethodConstraints(bestCandidate);
+ bestCandidateWasValidated = true;
+ }
+ OverloadResolutionErrors err = bestCandidate.Errors | bestCandidateValidationResult;
if (bestCandidateAmbiguousWith != null)
err |= OverloadResolutionErrors.AmbiguousMatch;
return err;
@@ -731,7 +782,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
public bool FoundApplicableCandidate {
- get { return bestCandidate != null && bestCandidate.Errors == OverloadResolutionErrors.None; }
+ get { return bestCandidate != null && IsApplicable(bestCandidate.Errors); }
}
public IParameterizedMember BestCandidateAmbiguousWith {
@@ -848,21 +899,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return null;
IMethod method = bestCandidate.Member as IMethod;
if (method != null && method.TypeParameters.Count > 0) {
- SpecializedMethod sm = method as SpecializedMethod;
- if (sm != null) {
- // Do not compose the substitutions, but merge them.
- // This is required for InvocationTests.SubstituteClassAndMethodTypeParametersAtOnce
- return new SpecializedMethod(
- (IMethod)method.MemberDefinition,
- new TypeParameterSubstitution(sm.Substitution.ClassTypeArguments, bestCandidate.InferredTypes));
- } else {
- return new SpecializedMethod(method, new TypeParameterSubstitution(null, bestCandidate.InferredTypes));
- }
+ return new SpecializedMethod((IMethod)method.MemberDefinition, GetSubstitution(bestCandidate));
} else {
return bestCandidate.Member;
}
}
+ TypeParameterSubstitution GetSubstitution(Candidate candidate)
+ {
+ SpecializedMethod sm = candidate.Member as SpecializedMethod;
+ if (sm != null) {
+ // Do not compose the substitutions, but merge them.
+ // This is required for InvocationTests.SubstituteClassAndMethodTypeParametersAtOnce
+ return new TypeParameterSubstitution(sm.Substitution.ClassTypeArguments, candidate.InferredTypes);
+ } else {
+ return new TypeParameterSubstitution(null, candidate.InferredTypes);
+ }
+ }
+
///
/// Creates a ResolveResult representing the result of overload resolution.
///
@@ -890,5 +944,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
argumentToParameterMap: this.GetArgumentToParameterMap(),
initializerStatements: initializerStatements);
}
+ #endregion
}
}
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolutionErrors.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolutionErrors.cs
index 1b1ea2c91c..399f2ff091 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolutionErrors.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolutionErrors.cs
@@ -65,10 +65,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// There is no unique best overload.
/// This error does not apply to any single candidate, but only to the overall result of overload resolution.
///
+ ///
+ /// This error does not prevent a candidate from being applicable.
+ ///
AmbiguousMatch = 0x0200,
///
/// The member is not accessible.
///
- Inaccessible = 0x0400
+ ///
+ /// This error is generated by member lookup; not by overload resolution.
+ ///
+ Inaccessible = 0x0400,
+ ///
+ /// A generic method
+ ///
+ ///
+ /// This error does not prevent a candidate from being applicable.
+ ///
+ MethodConstraintsNotSatisfied = 0x0800
}
}
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs
index d3dc835b22..43cc5ff3d7 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs
@@ -30,24 +30,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
///
public static class ResolveAtLocation
{
- public static ResolveResult Resolve (ICompilation compilation, CSharpParsedFile parsedFile, SyntaxTree syntaxTree, TextLocation location,
+ public static ResolveResult Resolve (ICompilation compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location,
CancellationToken cancellationToken = default(CancellationToken))
{
- return Resolve (new Lazy(() => compilation), parsedFile, syntaxTree, location, cancellationToken);
+ return Resolve (new Lazy(() => compilation), unresolvedFile, syntaxTree, location, cancellationToken);
}
- public static ResolveResult Resolve(Lazy compilation, CSharpParsedFile parsedFile, SyntaxTree syntaxTree, TextLocation location,
+ public static ResolveResult Resolve(Lazy compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location,
CancellationToken cancellationToken = default(CancellationToken))
{
AstNode node;
- return Resolve(compilation, parsedFile, syntaxTree, location, out node, cancellationToken);
+ return Resolve(compilation, unresolvedFile, syntaxTree, location, out node, cancellationToken);
}
- public static ResolveResult Resolve (ICompilation compilation, CSharpParsedFile parsedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
+ public static ResolveResult Resolve (ICompilation compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
CancellationToken cancellationToken = default(CancellationToken))
{
- return Resolve (new Lazy(() => compilation), parsedFile, syntaxTree, location, out node, cancellationToken);
+ return Resolve (new Lazy(() => compilation), unresolvedFile, syntaxTree, location, out node, cancellationToken);
}
- public static ResolveResult Resolve(Lazy compilation, CSharpParsedFile parsedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
+ public static ResolveResult Resolve(Lazy compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
CancellationToken cancellationToken = default(CancellationToken))
{
node = syntaxTree.GetNodeAt(location);
@@ -96,7 +96,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
// TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused
- CSharpAstResolver resolver = new CSharpAstResolver(compilation.Value, syntaxTree, parsedFile);
+ CSharpAstResolver resolver = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
ResolveResult rr = resolver.Resolve(node, cancellationToken);
if (rr is MethodGroupResolveResult && parentInvocation != null)
return resolver.Resolve(parentInvocation);
diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
index 9e7e789d05..c7f82cc8ef 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
@@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// We do not have to put this into the stored state (resolver) because
/// query expressions are always resolved in a single operation.
ResolveResult currentQueryResult;
- readonly CSharpParsedFile parsedFile;
+ readonly CSharpUnresolvedFile unresolvedFile;
readonly Dictionary resolveResultCache = new Dictionary();
readonly Dictionary resolverBeforeDict = new Dictionary();
readonly Dictionary resolverAfterDict = new Dictionary();
@@ -93,12 +93,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
///
/// Creates a new ResolveVisitor instance.
///
- public ResolveVisitor(CSharpResolver resolver, CSharpParsedFile parsedFile)
+ public ResolveVisitor(CSharpResolver resolver, CSharpUnresolvedFile unresolvedFile)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
this.resolver = resolver;
- this.parsedFile = parsedFile;
+ this.unresolvedFile = unresolvedFile;
this.navigator = skipAllNavigator;
}
@@ -534,12 +534,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
CSharpResolver previousResolver = resolver;
try {
- if (parsedFile != null) {
- resolver = resolver.WithCurrentUsingScope(parsedFile.RootUsingScope.Resolve(resolver.Compilation));
+ if (unresolvedFile != null) {
+ resolver = resolver.WithCurrentUsingScope(unresolvedFile.RootUsingScope.Resolve(resolver.Compilation));
} else {
var cv = new TypeSystemConvertVisitor(unit.FileName ?? string.Empty);
ApplyVisitorToUsings(cv, unit.Children);
- PushUsingScope(cv.ParsedFile.RootUsingScope);
+ PushUsingScope(cv.UnresolvedFile.RootUsingScope);
}
ScanChildren(unit);
return voidResult;
@@ -567,8 +567,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
CSharpResolver previousResolver = resolver;
try {
- if (parsedFile != null) {
- resolver = resolver.WithCurrentUsingScope(parsedFile.GetUsingScope(namespaceDeclaration.StartLocation).Resolve(resolver.Compilation));
+ if (unresolvedFile != null) {
+ resolver = resolver.WithCurrentUsingScope(unresolvedFile.GetUsingScope(namespaceDeclaration.StartLocation).Resolve(resolver.Compilation));
} else {
string fileName = namespaceDeclaration.GetRegion().FileName ?? string.Empty;
// Fetch parent using scope
@@ -589,7 +589,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Last using scope:
usingScope = new UsingScope(resolver.CurrentUsingScope.UnresolvedUsingScope, identifiers.Last().Name);
usingScope.Region = region;
- var cv = new TypeSystemConvertVisitor(new CSharpParsedFile(region.FileName ?? string.Empty), usingScope);
+ var cv = new TypeSystemConvertVisitor(new CSharpUnresolvedFile(region.FileName ?? string.Empty), usingScope);
ApplyVisitorToUsings(cv, namespaceDeclaration.Children);
PushUsingScope(usingScope);
}
@@ -673,7 +673,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) {
if (node.Role == Roles.Variable) {
IMember member;
- if (parsedFile != null) {
+ if (unresolvedFile != null) {
member = GetMemberFromLocation(node);
} else {
string name = ((VariableInitializer)node).Name;
@@ -699,7 +699,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
TextLocation location = TypeSystemConvertVisitor.GetStartLocationAfterAttributes(node);
return typeDef.GetMembers(
delegate (IUnresolvedMember m) {
- if (m.ParsedFile != parsedFile)
+ if (m.UnresolvedFile != unresolvedFile)
return false;
DomRegion region = m.Region;
return !region.IsEmpty && region.Begin <= location && region.End > location;
@@ -792,7 +792,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpResolver oldResolver = resolver;
try {
IMember member;
- if (parsedFile != null) {
+ if (unresolvedFile != null) {
member = GetMemberFromLocation(memberDeclaration);
} else {
// Re-discover the method:
@@ -855,7 +855,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpResolver oldResolver = resolver;
try {
IMember member;
- if (parsedFile != null) {
+ if (unresolvedFile != null) {
member = GetMemberFromLocation(propertyOrIndexerDeclaration);
} else {
// Re-discover the property:
@@ -911,7 +911,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpResolver oldResolver = resolver;
try {
IMember member;
- if (parsedFile != null) {
+ if (unresolvedFile != null) {
member = GetMemberFromLocation(eventDeclaration);
} else {
string name = eventDeclaration.Name;
@@ -1034,7 +1034,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Scan(attributeSection);
IMember member = null;
- if (parsedFile != null) {
+ if (unresolvedFile != null) {
member = GetMemberFromLocation(enumMemberDeclaration);
} else if (resolver.CurrentTypeDefinition != null) {
string name = enumMemberDeclaration.Name;
@@ -1958,8 +1958,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
DomRegion MakeRegion(AstNode node)
{
- if (parsedFile != null)
- return new DomRegion(parsedFile.FileName, node.StartLocation, node.EndLocation);
+ if (unresolvedFile != null)
+ return new DomRegion(unresolvedFile.FileName, node.StartLocation, node.EndLocation);
else
return node.GetRegion();
}
@@ -2148,7 +2148,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly QuerySelectClause selectClause;
readonly CSharpResolver storedContext;
- readonly CSharpParsedFile parsedFile;
+ readonly CSharpUnresolvedFile unresolvedFile;
readonly List hypotheses = new List();
internal IList parameters = new List();
@@ -2186,7 +2186,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
this.parentVisitor = parentVisitor;
this.storedContext = parentVisitor.resolver;
- this.parsedFile = parentVisitor.parsedFile;
+ this.unresolvedFile = parentVisitor.unresolvedFile;
this.bodyResult = parentVisitor.voidResult;
}
@@ -2254,7 +2254,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (ok)
return h;
}
- ResolveVisitor visitor = new ResolveVisitor(storedContext, parsedFile);
+ ResolveVisitor visitor = new ResolveVisitor(storedContext, unresolvedFile);
var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null);
hypotheses.Add(newHypothesis);
return newHypothesis;
diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs
index fe72e9b576..ec9b9cfeb4 100644
--- a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs
+++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs
@@ -73,9 +73,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return result;
} else {
result = new List();
- foreach (var parsedFile in projectContent.Files.OfType()) {
- var attributes = assemblyAttributes ? parsedFile.AssemblyAttributes : parsedFile.ModuleAttributes;
- var context = new CSharpTypeResolveContext(this, parsedFile.RootUsingScope.Resolve(compilation));
+ foreach (var unresolvedFile in projectContent.Files.OfType()) {
+ var attributes = assemblyAttributes ? unresolvedFile.AssemblyAttributes : unresolvedFile.ModuleAttributes;
+ var context = new CSharpTypeResolveContext(this, unresolvedFile.RootUsingScope.Resolve(compilation));
foreach (var unresolvedAttr in attributes) {
result.Add(unresolvedAttr.CreateResolvedAttribute(context));
}
diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpUnresolvedFile.cs
similarity index 95%
rename from ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs
rename to ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpUnresolvedFile.cs
index 186961031f..ac5da75885 100644
--- a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs
+++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpUnresolvedFile.cs
@@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// Represents a file that was parsed and converted for the type system.
///
[Serializable]
- public sealed class CSharpParsedFile : AbstractFreezable, IParsedFile, IUnresolvedDocumentationProvider
+ public sealed class CSharpUnresolvedFile : AbstractFreezable, IUnresolvedFile, IUnresolvedDocumentationProvider
{
readonly string fileName;
readonly UsingScope rootUsingScope;
@@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
usingScopes = FreezableHelper.FreezeListAndElements(usingScopes);
}
- public CSharpParsedFile(string fileName)
+ public CSharpUnresolvedFile(string fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
@@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
this.rootUsingScope = new UsingScope();
}
- public CSharpParsedFile(string fileName, UsingScope rootUsingScope)
+ public CSharpUnresolvedFile(string fileName, UsingScope rootUsingScope)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
@@ -178,7 +178,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return rctx;
}
- ITypeResolveContext IParsedFile.GetTypeResolveContext (ICompilation compilation, TextLocation loc)
+ ITypeResolveContext IUnresolvedFile.GetTypeResolveContext (ICompilation compilation, TextLocation loc)
{
return GetTypeResolveContext (compilation, loc);
}
diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
index 0958a9c616..98228ac423 100644
--- a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
+++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
@@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
///
public class TypeSystemConvertVisitor : DepthFirstAstVisitor
{
- readonly CSharpParsedFile parsedFile;
+ readonly CSharpUnresolvedFile unresolvedFile;
UsingScope usingScope;
CSharpUnresolvedTypeDefinition currentTypeDefinition;
DefaultUnresolvedMethod currentMethod;
@@ -64,32 +64,32 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
{
if (fileName == null)
throw new ArgumentNullException("fileName");
- this.parsedFile = new CSharpParsedFile(fileName);
- this.usingScope = parsedFile.RootUsingScope;
+ this.unresolvedFile = new CSharpUnresolvedFile(fileName);
+ this.usingScope = unresolvedFile.RootUsingScope;
}
///
/// Creates a new TypeSystemConvertVisitor and initializes it with a given context.
///
- /// The parsed file to which members should be added.
+ /// The parsed file to which members should be added.
/// The current using scope.
/// The current type definition.
- public TypeSystemConvertVisitor(CSharpParsedFile parsedFile, UsingScope currentUsingScope = null, CSharpUnresolvedTypeDefinition currentTypeDefinition = null)
+ public TypeSystemConvertVisitor(CSharpUnresolvedFile unresolvedFile, UsingScope currentUsingScope = null, CSharpUnresolvedTypeDefinition currentTypeDefinition = null)
{
- if (parsedFile == null)
- throw new ArgumentNullException("parsedFile");
- this.parsedFile = parsedFile;
- this.usingScope = currentUsingScope ?? parsedFile.RootUsingScope;
+ if (unresolvedFile == null)
+ throw new ArgumentNullException("unresolvedFile");
+ this.unresolvedFile = unresolvedFile;
+ this.usingScope = currentUsingScope ?? unresolvedFile.RootUsingScope;
this.currentTypeDefinition = currentTypeDefinition;
}
- public CSharpParsedFile ParsedFile {
- get { return parsedFile; }
+ public CSharpUnresolvedFile UnresolvedFile {
+ get { return unresolvedFile; }
}
DomRegion MakeRegion(TextLocation start, TextLocation end)
{
- return new DomRegion(parsedFile.FileName, start.Line, start.Column, end.Line, end.Column);
+ return new DomRegion(unresolvedFile.FileName, start.Line, start.Column, end.Line, end.Column);
}
DomRegion MakeRegion(AstNode node)
@@ -122,7 +122,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
#region Compilation Unit
public override IUnresolvedEntity VisitSyntaxTree (SyntaxTree unit)
{
- parsedFile.Errors = unit.Errors;
+ unresolvedFile.Errors = unit.Errors;
return base.VisitSyntaxTree (unit);
}
#endregion
@@ -167,7 +167,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
usingScope.Region = region;
}
base.VisitNamespaceDeclaration(namespaceDeclaration);
- parsedFile.UsingScopes.Add(usingScope); // add after visiting children so that nested scopes come first
+ unresolvedFile.UsingScopes.Add(usingScope); // add after visiting children so that nested scopes come first
usingScope = previousUsingScope;
return null;
}
@@ -184,9 +184,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
currentTypeDefinition.NestedTypes.Add(newType);
} else {
newType = new CSharpUnresolvedTypeDefinition(usingScope, name);
- parsedFile.TopLevelTypeDefinitions.Add(newType);
+ unresolvedFile.TopLevelTypeDefinitions.Add(newType);
}
- newType.ParsedFile = parsedFile;
+ newType.UnresolvedFile = unresolvedFile;
newType.HasExtensionMethods = false; // gets set to true when an extension method is added
return newType;
}
@@ -868,9 +868,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
{
// non-assembly attributes are handled by their parent entity
if (attributeSection.AttributeTarget == "assembly") {
- ConvertAttributes(parsedFile.AssemblyAttributes, attributeSection);
+ ConvertAttributes(unresolvedFile.AssemblyAttributes, attributeSection);
} else if (attributeSection.AttributeTarget == "module") {
- ConvertAttributes(parsedFile.ModuleAttributes, attributeSection);
+ ConvertAttributes(unresolvedFile.ModuleAttributes, attributeSection);
}
return null;
}
@@ -1197,7 +1197,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
}
if (documentation != null) {
documentation.Reverse(); // bring documentation in correct order
- parsedFile.AddDocumentation(entity, string.Join(Environment.NewLine, documentation));
+ unresolvedFile.AddDocumentation(entity, string.Join(Environment.NewLine, documentation));
}
}
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/.gitignore b/ICSharpCode.NRefactory.ConsistencyCheck/.gitignore
deleted file mode 100644
index 9ce745d95d..0000000000
--- a/ICSharpCode.NRefactory.ConsistencyCheck/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-
-bin/
-obj/
\ No newline at end of file
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/CSharpFile.cs b/ICSharpCode.NRefactory.ConsistencyCheck/CSharpFile.cs
new file mode 100644
index 0000000000..addcd9e23a
--- /dev/null
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/CSharpFile.cs
@@ -0,0 +1,68 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.CSharp.Resolver;
+using ICSharpCode.NRefactory.CSharp.TypeSystem;
+using ICSharpCode.NRefactory.Editor;
+using ICSharpCode.NRefactory.TypeSystem;
+
+namespace ICSharpCode.NRefactory.ConsistencyCheck
+{
+ public class CSharpFile
+ {
+ public readonly CSharpProject Project;
+ public readonly string FileName;
+ public readonly string OriginalText;
+
+ public SyntaxTree SyntaxTree;
+ public CSharpUnresolvedFile UnresolvedTypeSystemForFile;
+
+ public CSharpFile(CSharpProject project, string fileName)
+ {
+ this.Project = project;
+ this.FileName = fileName;
+
+ CSharpParser p = new CSharpParser(project.CompilerSettings);
+// using (var stream = File.OpenRead(fileName)) {
+// this.CompilationUnit = p.Parse(stream, fileName);
+// }
+
+ // Keep the original text around; we might use it for a refactoring later
+ this.OriginalText = File.ReadAllText(fileName);
+ this.SyntaxTree = p.Parse(this.OriginalText, fileName);
+
+ if (p.HasErrors) {
+ Console.WriteLine("Error parsing " + fileName + ":");
+ foreach (var error in p.ErrorsAndWarnings) {
+ Console.WriteLine(" " + error.Region + " " + error.Message);
+ }
+ }
+ this.UnresolvedTypeSystemForFile = this.SyntaxTree.ToTypeSystem();
+ }
+
+ public CSharpAstResolver CreateResolver()
+ {
+ return new CSharpAstResolver(Project.Compilation, SyntaxTree, UnresolvedTypeSystemForFile);
+ }
+ }
+}
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs b/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs
index 111e4dd7f9..d6deadb933 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs
@@ -20,163 +20,128 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+
using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.CSharp.TypeSystem;
-using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Logging;
namespace ICSharpCode.NRefactory.ConsistencyCheck
{
+ ///
+ /// Represents a C# project (.csproj file)
+ ///
public class CSharpProject
{
+ ///
+ /// Parent solution.
+ ///
public readonly Solution Solution;
+
+ ///
+ /// Title is the project name as specified in the .sln file.
+ ///
public readonly string Title;
+
+ ///
+ /// Name of the output assembly.
+ ///
public readonly string AssemblyName;
+
+ ///
+ /// Full path to the .csproj file.
+ ///
public readonly string FileName;
public readonly List Files = new List();
public readonly CompilerSettings CompilerSettings = new CompilerSettings();
- public IProjectContent ProjectContent;
+ ///
+ /// The unresolved type system for this project.
+ ///
+ public readonly IProjectContent ProjectContent;
- public ICompilation Compilation {
- get {
- return Solution.SolutionSnapshot.GetCompilation(ProjectContent);
- }
- }
+ ///
+ /// The resolved type system for this project.
+ /// This field is initialized once all projects have been loaded (in Solution constructor).
+ ///
+ public ICompilation Compilation;
public CSharpProject(Solution solution, string title, string fileName)
{
+ // Normalize the file name
+ fileName = Path.GetFullPath(fileName);
+
this.Solution = solution;
this.Title = title;
this.FileName = fileName;
- var p = new Microsoft.Build.Evaluation.Project(fileName);
- this.AssemblyName = p.GetPropertyValue("AssemblyName");
- this.CompilerSettings.AllowUnsafeBlocks = GetBoolProperty(p, "AllowUnsafeBlocks") ?? false;
- this.CompilerSettings.CheckForOverflow = GetBoolProperty(p, "CheckForOverflowUnderflow") ?? false;
- foreach (string symbol in p.GetPropertyValue("DefineConstants").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) {
+ // Use MSBuild to open the .csproj
+ var msbuildProject = new Microsoft.Build.Evaluation.Project(fileName);
+ // Figure out some compiler settings
+ this.AssemblyName = msbuildProject.GetPropertyValue("AssemblyName");
+ this.CompilerSettings.AllowUnsafeBlocks = GetBoolProperty(msbuildProject, "AllowUnsafeBlocks") ?? false;
+ this.CompilerSettings.CheckForOverflow = GetBoolProperty(msbuildProject, "CheckForOverflowUnderflow") ?? false;
+ string defineConstants = msbuildProject.GetPropertyValue("DefineConstants");
+ foreach (string symbol in defineConstants.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
this.CompilerSettings.ConditionalSymbols.Add(symbol.Trim());
+
+ // Initialize the unresolved type system
+ IProjectContent pc = new CSharpProjectContent();
+ pc = pc.SetAssemblyName(this.AssemblyName);
+ pc = pc.SetProjectFileName(fileName);
+ pc = pc.SetCompilerSettings(this.CompilerSettings);
+ // Parse the C# code files
+ foreach (var item in msbuildProject.GetItems("Compile")) {
+ var file = new CSharpFile(this, Path.Combine(msbuildProject.DirectoryPath, item.EvaluatedInclude));
+ Files.Add(file);
}
- foreach (var item in p.GetItems("Compile")) {
- Files.Add(new CSharpFile(this, Path.Combine(p.DirectoryPath, item.EvaluatedInclude)));
- }
- List references = new List();
- string mscorlib = FindAssembly(Program.AssemblySearchPaths, "mscorlib");
- if (mscorlib != null) {
- references.Add(Program.LoadAssembly(mscorlib));
- } else {
- Console.WriteLine("Could not find mscorlib");
- }
- bool hasSystemCore = false;
- foreach (var item in p.GetItems("Reference")) {
- string assemblyFileName = null;
- if (item.HasMetadata("HintPath")) {
- assemblyFileName = Path.Combine(p.DirectoryPath, item.GetMetadataValue("HintPath"));
- if (!File.Exists(assemblyFileName))
- assemblyFileName = null;
- }
- if (assemblyFileName == null) {
- assemblyFileName = FindAssembly(Program.AssemblySearchPaths, item.EvaluatedInclude);
- }
- if (assemblyFileName != null) {
- if (Path.GetFileName(assemblyFileName).Equals("System.Core.dll", StringComparison.OrdinalIgnoreCase))
- hasSystemCore = true;
- references.Add(Program.LoadAssembly(assemblyFileName));
- } else {
- Console.WriteLine("Could not find referenced assembly " + item.EvaluatedInclude);
- }
+ // Add parsed files to the type system
+ pc = pc.AddOrUpdateFiles(Files.Select(f => f.UnresolvedTypeSystemForFile));
+
+ // Add referenced assemblies:
+ foreach (string assemblyFile in ResolveAssemblyReferences(msbuildProject)) {
+ IUnresolvedAssembly assembly = solution.LoadAssembly(assemblyFile);
+ pc = pc.AddAssemblyReferences(new [] { assembly });
}
- if (!hasSystemCore && FindAssembly(Program.AssemblySearchPaths, "System.Core") != null)
- references.Add(Program.LoadAssembly(FindAssembly(Program.AssemblySearchPaths, "System.Core")));
- foreach (var item in p.GetItems("ProjectReference")) {
- references.Add(new ProjectReference(solution, item.GetMetadataValue("Name")));
+
+ // Add project references:
+ foreach (var item in msbuildProject.GetItems("ProjectReference")) {
+ string referencedFileName = Path.Combine(msbuildProject.DirectoryPath, item.EvaluatedInclude);
+ // Normalize the path; this is required to match the name with the referenced project's file name
+ referencedFileName = Path.GetFullPath(referencedFileName);
+ pc = pc.AddAssemblyReferences(new[] { new ProjectReference(referencedFileName) });
}
- this.ProjectContent = new CSharpProjectContent()
- .SetAssemblyName(this.AssemblyName)
- .SetCompilerSettings(this.CompilerSettings)
- .AddAssemblyReferences(references)
- .UpdateProjectContent(null, Files.Select(f => f.ParsedFile));
+ this.ProjectContent = pc;
}
- string FindAssembly(IEnumerable assemblySearchPaths, string evaluatedInclude)
+ IEnumerable ResolveAssemblyReferences(Microsoft.Build.Evaluation.Project project)
{
- if (evaluatedInclude.IndexOf(',') >= 0)
- evaluatedInclude = evaluatedInclude.Substring(0, evaluatedInclude.IndexOf(','));
- foreach (string searchPath in assemblySearchPaths) {
- string assemblyFile = Path.Combine(searchPath, evaluatedInclude + ".dll");
- if (File.Exists(assemblyFile))
- return assemblyFile;
- }
- return null;
+ // Use MSBuild to figure out the full path of the referenced assemblies
+ var projectInstance = project.CreateProjectInstance();
+ projectInstance.SetProperty("BuildingProject", "false");
+ project.SetProperty("DesignTimeBuild", "true");
+
+ projectInstance.Build("ResolveAssemblyReferences", new [] { new ConsoleLogger(LoggerVerbosity.Minimal) });
+ var items = projectInstance.GetItems("_ResolveAssemblyReferenceResolvedFiles");
+ string baseDirectory = Path.GetDirectoryName(this.FileName);
+ return items.Select(i => Path.Combine(baseDirectory, i.GetMetadataValue("Identity")));
}
static bool? GetBoolProperty(Microsoft.Build.Evaluation.Project p, string propertyName)
{
string val = p.GetPropertyValue(propertyName);
- if (val.Equals("true", StringComparison.OrdinalIgnoreCase))
- return true;
- if (val.Equals("false", StringComparison.OrdinalIgnoreCase))
- return false;
- return null;
+ bool result;
+ if (bool.TryParse(val, out result))
+ return result;
+ else
+ return null;
}
public override string ToString()
{
return string.Format("[CSharpProject AssemblyName={0}]", AssemblyName);
}
-
- public CSharpFile GetFile(string fileName)
- {
- return Files.Single(f => f.FileName == fileName);
- }
- }
-
- public class ProjectReference : IAssemblyReference
- {
- readonly Solution solution;
- readonly string projectTitle;
-
- public ProjectReference(Solution solution, string projectTitle)
- {
- this.solution = solution;
- this.projectTitle = projectTitle;
- }
-
- public IAssembly Resolve(ITypeResolveContext context)
- {
- var project = solution.Projects.Single(p => string.Equals(p.Title, projectTitle, StringComparison.OrdinalIgnoreCase));
- return project.ProjectContent.Resolve(context);
- }
- }
-
- public class CSharpFile
- {
- public readonly CSharpProject Project;
- public readonly string FileName;
-
- public readonly ITextSource Content;
- public readonly int LinesOfCode;
- public SyntaxTree SyntaxTree;
- public CSharpParsedFile ParsedFile;
-
- public CSharpFile(CSharpProject project, string fileName)
- {
- this.Project = project;
- this.FileName = fileName;
- this.Content = new StringTextSource(File.ReadAllText(FileName));
- this.LinesOfCode = 1 + this.Content.Text.Count(c => c == '\n');
-
- CSharpParser p = new CSharpParser(project.CompilerSettings);
- this.SyntaxTree = p.Parse(Content, fileName);
- if (p.HasErrors) {
- Console.WriteLine("Error parsing " + fileName + ":");
- foreach (var error in p.ErrorsAndWarnings) {
- Console.WriteLine(" " + error.Region + " " + error.Message);
- }
- }
- this.ParsedFile = this.SyntaxTree.ToTypeSystem();
- }
}
}
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/FindReferencesConsistencyCheck.cs b/ICSharpCode.NRefactory.ConsistencyCheck/FindReferencesConsistencyCheck.cs
index 896a0e21c8..839a6c54ff 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/FindReferencesConsistencyCheck.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/FindReferencesConsistencyCheck.cs
@@ -59,8 +59,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
}
}
);
- var resolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.ParsedFile);
- resolver.ApplyNavigator(navigator);
+ file.CreateResolver().ApplyNavigator(navigator);
}
}
Console.WriteLine("For each entity, find all references...");
@@ -102,19 +101,19 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
HashSet foundReferences = new HashSet();
var interestingFiles = new HashSet();
foreach (var searchScope in searchScopes) {
- foreach (var parsedFile in fr.GetInterestingFiles(searchScope, project.Compilation)) {
- var file = project.GetFile(parsedFile.FileName);
- Debug.Assert(file.ParsedFile == parsedFile);
+ foreach (var unresolvedFile in fr.GetInterestingFiles(searchScope, project.Compilation)) {
+ var file = project.Files.Single(f => f.FileName == unresolvedFile.FileName);
+ Debug.Assert(file.UnresolvedTypeSystemForFile == unresolvedFile);
// Skip file if it doesn't contain the search term
- if (searchScope.SearchTerm != null && file.Content.IndexOf(searchScope.SearchTerm, 0, file.Content.TextLength, StringComparison.Ordinal) < 0)
+ if (searchScope.SearchTerm != null && file.OriginalText.IndexOf(searchScope.SearchTerm, StringComparison.Ordinal) < 0)
continue;
interestingFiles.Add(file);
}
}
foreach (var file in interestingFiles) {
- fr.FindReferencesInFile(searchScopes, file.ParsedFile, file.SyntaxTree, project.Compilation,
+ fr.FindReferencesInFile(searchScopes, file.UnresolvedTypeSystemForFile, file.SyntaxTree, project.Compilation,
delegate(AstNode node, ResolveResult result) {
foundReferences.Add(node);
}, CancellationToken.None);
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj b/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj
index e125b6b5ab..d1351a7ff5 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj
@@ -15,12 +15,12 @@
False
4
false
+ bin\$(Configuration)\
x86
- bin\Debug\
true
Full
False
@@ -28,9 +28,7 @@
DEBUG;TRACE
- bin\Release\
- False
- None
+ PdbOnly
True
False
TRACE
@@ -39,7 +37,6 @@
AnyCPU
- bin\Debug\
true
Full
False
@@ -48,9 +45,7 @@
v4.5
- bin\Release\
- False
- None
+ PdbOnly
True
False
TRACE
@@ -58,6 +53,7 @@
+
3.5
@@ -75,6 +71,7 @@
Properties\GlobalAssemblyInfo.cs
+
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs b/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs
index 88ee1489c2..936edfab6e 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs
@@ -52,8 +52,8 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
}
Console.WriteLine("Loaded {0} lines of code ({1:f1} MB) in {2} files in {3} projects.",
- solution.AllFiles.Sum(f => f.LinesOfCode),
- solution.AllFiles.Sum(f => f.Content.TextLength) / 1024.0 / 1024.0,
+ solution.AllFiles.Sum(f => 1 + f.OriginalText.Count(c => c == '\n')),
+ solution.AllFiles.Sum(f => f.OriginalText.Length) / 1024.0 / 1024.0,
solution.AllFiles.Count(),
solution.Projects.Count);
@@ -63,7 +63,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
using (new Timer("Resolve unresolved members... ")) TypeSystemTests.ResolvedUnresolvedMembers(solution);
//RunTestOnAllFiles("Roundtripping test", RoundtripTest.RunTest);
RunTestOnAllFiles("Resolver test", ResolverTest.RunTest);
- RunTestOnAllFiles("Resolver test (no parsed file)", ResolverTest.RunTestWithoutParsedFile);
+ RunTestOnAllFiles("Resolver test (no parsed file)", ResolverTest.RunTestWithoutUnresolvedFile);
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 06906f310b..a0610c4b1f 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/RandomizedOrderResolverTest.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/RandomizedOrderResolverTest.cs
@@ -45,9 +45,9 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
Random rnd = new Random(seed);
var test = new RandomizedOrderResolverTest();
// Resolve all nodes, but in a random order without using a navigator.
- test.resolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.ParsedFile);
+ test.resolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.UnresolvedTypeSystemForFile);
// For comparing whether the results are equivalent, we also use a normal 'resolve all' resolver:
- test.resolveAllResolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.ParsedFile);
+ test.resolveAllResolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.UnresolvedTypeSystemForFile);
test.resolveAllResolver.ApplyNavigator(new ResolveAllNavigator(), CancellationToken.None);
// Prepare list of actions that we need to verify:
var actions = new List>();
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs b/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs
index 23ee726b96..be51723e5c 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs
@@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
{
public static void RunTest(CSharpFile file)
{
- CSharpAstResolver resolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.ParsedFile);
+ CSharpAstResolver resolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.UnresolvedTypeSystemForFile);
var navigator = new ValidatingResolveAllNavigator(file.FileName);
resolver.ApplyNavigator(navigator, CancellationToken.None);
navigator.Validate(resolver, file.SyntaxTree);
@@ -102,19 +102,19 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
}
}
- public static void RunTestWithoutParsedFile(CSharpFile file)
+ public static void RunTestWithoutUnresolvedFile(CSharpFile file)
{
CSharpAstResolver resolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree);
var navigator = new ValidatingResolveAllNavigator(file.FileName);
resolver.ApplyNavigator(navigator, CancellationToken.None);
navigator.Validate(resolver, file.SyntaxTree);
- CSharpAstResolver originalResolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.ParsedFile);
+ CSharpAstResolver originalResolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.UnresolvedTypeSystemForFile);
foreach (var node in file.SyntaxTree.DescendantsAndSelf) {
var originalResult = originalResolver.Resolve(node);
var result = resolver.Resolve(node);
if (!RandomizedOrderResolverTest.IsEqualResolveResult(result, originalResult)) {
- Console.WriteLine("Got different without IParsedFile at " + file.FileName + ":" + node.StartLocation);
+ Console.WriteLine("Got different without IUnresolvedFile at " + file.FileName + ":" + node.StartLocation);
}
}
}
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs b/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs
index 48d29ce843..35f503d5bd 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs
@@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
{
public static void RunTest(CSharpFile file)
{
- string code = file.Content.Text.Replace("\r\n", "\n");
+ string code = file.OriginalText.Replace("\r\n", "\n");
Debug.Assert(code.IndexOf('\r') < 0);
if (code.Contains("#pragma"))
return; // skip code with preprocessor directives
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/Solution.cs b/ICSharpCode.NRefactory.ConsistencyCheck/Solution.cs
index 279dd81c8f..0cdde17897 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/Solution.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/Solution.cs
@@ -17,12 +17,14 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
+
using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
+using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.ConsistencyCheck
{
@@ -62,6 +64,25 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
}
}
}
+ // Create compilations (resolved type systems) after all projects have been loaded.
+ // (we can't do this earlier because project A might have a reference to project B, where A is loaded before B)
+ // To allow NRefactory to resolve project references, we need to use a 'DefaultSolutionSnapshot'
+ // instead of calling CreateCompilation() on each project individually.
+ var solutionSnapshot = new DefaultSolutionSnapshot(this.Projects.Select(p => p.ProjectContent));
+ foreach (CSharpProject project in this.Projects) {
+ project.Compilation = solutionSnapshot.GetCompilation(project.ProjectContent);
+ }
+ }
+
+ ConcurrentDictionary assemblyDict = new ConcurrentDictionary(Platform.FileNameComparer);
+
+ ///
+ /// Loads a referenced assembly from a .dll.
+ /// Returns the existing instance if the assembly was already loaded.
+ ///
+ public IUnresolvedAssembly LoadAssembly(string assemblyFileName)
+ {
+ return assemblyDict.GetOrAdd(assemblyFileName, file => new CecilLoader().LoadAssemblyFile(file));
}
}
}
diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/VisitorBenchmark.cs b/ICSharpCode.NRefactory.ConsistencyCheck/VisitorBenchmark.cs
index 9c58ef543e..855f09fea0 100644
--- a/ICSharpCode.NRefactory.ConsistencyCheck/VisitorBenchmark.cs
+++ b/ICSharpCode.NRefactory.ConsistencyCheck/VisitorBenchmark.cs
@@ -50,11 +50,6 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
visitor.EnterIdentifierExpression += list.Add;
syntaxTree.AcceptVisitor(visitor);
});
- RunTest("ObservableAstVisitor