diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs index 6b5e237958..9db7d897a2 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -2246,31 +2246,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return parentheses != 1 || bracket > 0 ? -1 : index; } - CSharpResolver GetState () - { - return new CSharpResolver (ctx); - /*var state = new CSharpResolver (ctx); - - state.CurrentMember = currentMember; - state.CurrentTypeDefinition = currentType; - state.CurrentUsingScope = CSharpParsedFile.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); - Unit.AcceptVisitor (visitor, null); - try { - var newState = visitor.GetResolverStateBefore (node); - if (newState != null) - state = newState; - } catch (Exception) { - } - } - - return state;*/ - } #endregion #region Preprocessor diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs index 2d038cf089..c145d6258b 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs @@ -192,7 +192,33 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var expr = Unit.GetNodeAt (loc.Line, loc.Column); return expr != null && expr.Value is string; } - #endregion + + protected CSharpResolver GetState () + { + return new CSharpResolver (ctx); + /*var state = new CSharpResolver (ctx); + + state.CurrentMember = currentMember; + state.CurrentTypeDefinition = currentType; + state.CurrentUsingScope = CSharpParsedFile.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); + Unit.AcceptVisitor (visitor, null); + try { + var newState = visitor.GetResolverStateBefore (node); + if (newState != null) + state = newState; + } catch (Exception) { + } + } + + return state;*/ + } + #endregion #region Basic parsing/resolving functions Stack> GetBracketStack (string memberText) @@ -343,7 +369,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } else { memberLocation = new TextLocation (1, 1); } - using (var stream = new System.IO.StringReader (wrapper.ToString ())) { try { var parser = new CSharpParser (); diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs index 6ad0c84469..dd8979fea8 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs @@ -57,7 +57,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; var mref = baseUnit.GetNodeAt (location, n => n is IndexerExpression); - Print (baseUnit); AstNode expr; if (mref is IndexerExpression) { expr = ((IndexerExpression)mref).Target; @@ -74,6 +73,25 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return Tuple.Create (tsvisitor.ParsedFile, (AstNode)expr, Unit); } + public Tuple GetTypeBeforeCursor () + { + CompilationUnit baseUnit; + if (currentMember == null && currentType == null) + return null; + baseUnit = ParseStub ("x> a"); + + var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; + var expr = baseUnit.GetNodeAt (location.Line, location.Column + 1); // '>' position + + var member = Unit.GetNodeAt (memberLocation); + var member2 = baseUnit.GetNodeAt (memberLocation); + member2.Remove (); + member.ReplaceWith (member2); + var tsvisitor = new TypeSystemConvertVisitor (CSharpParsedFile.FileName); + Unit.AcceptVisitor (tsvisitor, null); + return Tuple.Create (tsvisitor.ParsedFile, (AstNode)expr, Unit); + } + public IParameterDataProvider GetParameterDataProvider (int offset, char completionChar) { if (offset <= 0) @@ -85,13 +103,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (IsInsideCommentOrString ()) return null; - var invoke = GetInvocationBeforeCursor (true) ?? GetIndexerBeforeCursor (); - if (invoke == null) - return null; ResolveResult resolveResult; switch (completionChar) { case '(': + var invoke = GetInvocationBeforeCursor (true) ?? GetIndexerBeforeCursor (); + if (invoke == null) + return null; if (invoke.Item2 is ObjectCreateExpression) { var createType = ResolveExpression (invoke.Item1, ((ObjectCreateExpression)invoke.Item2).Type, invoke.Item3); return factory.CreateConstructorProvider (createType.Item1.Type); @@ -131,6 +149,18 @@ namespace ICSharpCode.NRefactory.CSharp.Completion // } break; case ',': + invoke = GetInvocationBeforeCursor (true) ?? GetIndexerBeforeCursor (); + if (invoke == null) { + invoke = GetTypeBeforeCursor (); + if (invoke !=null) { + var typeExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); + if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) + return null; + + return factory.CreateTypeParameterDataProvider (CollectAllTypes (typeExpression.Item1.Type)); + } + return null; + } if (invoke.Item2 is ObjectCreateExpression) { var createType = ResolveExpression (invoke.Item1, ((ObjectCreateExpression)invoke.Item2).Type, invoke.Item3); return factory.CreateConstructorProvider (createType.Item1.Type); @@ -161,12 +191,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (resolveResult != null) return factory.CreateIndexerParameterDataProvider (resolveResult.Type, invoke.Item2); break; -// case '<': -// if (string.IsNullOrEmpty (result.Expression)) -// return null; -// return new NRefactoryTemplateParameterDataProvider (textEditorData, resolver, GetUsedNamespaces (), result, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); + case '<': + invoke = GetTypeBeforeCursor (); + if (invoke == null) + return null; + var typeExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); + if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) + return null; + return factory.CreateTypeParameterDataProvider (CollectAllTypes (typeExpression.Item1.Type)); case '[': + invoke = GetIndexerBeforeCursor (); + if (invoke == null) + return null; var indexerExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); if (indexerExpression == null || indexerExpression.Item1 == null || indexerExpression.Item1.IsError) return null; @@ -175,6 +212,24 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return null; } + IEnumerable CollectAllTypes (IType baseType) + { + var state = GetState (); + for (var n = state.CurrentUsingScope; n != null; n = n.Parent) { + foreach (var u in n.Usings) { + foreach (var type in u.Types) { + if (type.TypeParameterCount > 0 && type.Name == baseType.Name) + yield return type; + } + } + + foreach (var type in n.Namespace.Types) { + if (type.TypeParameterCount > 0 && type.Name == baseType.Name) + yield return type; + } + } + } + List GetUsedNamespaces () { var scope = CSharpParsedFile.GetUsingScope (location); diff --git a/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs b/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs index 56321bdb18..bea5860496 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs @@ -27,6 +27,7 @@ using System; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.CSharp.Resolver; +using System.Collections.Generic; namespace ICSharpCode.NRefactory.CSharp.Completion { @@ -41,6 +42,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion IParameterDataProvider CreateDelegateDataProvider (IType type); IParameterDataProvider CreateIndexerParameterDataProvider (IType type, AstNode resolvedNode); + + IParameterDataProvider CreateTypeParameterDataProvider (IEnumerable types); } } diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs index 1aebea0f54..23360e6e2f 100644 --- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -118,6 +118,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteSpecialsUpToNode (node); containerStack.Push (node); positionStack.Push (node.FirstChild); + formatter.WriteToken (""); // force indentation, if required OnOutputStarted (new AstNodeEventArgs (node)); formatter.StartNode (node); } diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs index fd0e81a4fc..911ec67ccd 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs @@ -62,24 +62,29 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { public int Offset { get; - set; + internal set; } public int Length { - get { - return EndOffset - Offset; - } + get; + internal set; } public int EndOffset { - get; - set; + get { + return Offset + Length; + } } public Segment (int offset) { this.Offset = offset; } + + public override string ToString () + { + return string.Format ("[NodeOutput.Segment: Offset={0}, Length={1}, EndOffset={2}]", Offset, Length, EndOffset); + } } } diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs index 9d4d9e42ed..c63bc36f0a 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs @@ -48,22 +48,36 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring get; } + public ICompilation Compilation { + get; + protected set; + } + public abstract CSharpFormattingOptions FormattingOptions { get; } public abstract AstType CreateShortType (IType fullType); - public AstType CreateShortType (string ns, string typeName) + public AstType CreateShortType (string ns, string name, int typeParameterCount = 0) { - throw new NotImplementedException(); - //return CreateShortType (TypeResolveContext.GetTypeDefinition (ns, typeName, 0, StringComparer.Ordinal)); + var def = Compilation.MainAssembly.GetTypeDefinition (ns, name, typeParameterCount); + if (def == null) { + foreach (var asm in Compilation.ReferencedAssemblies) { + def = asm.GetTypeDefinition (ns, name, typeParameterCount); + if (def != null) + break; + } + + } + if (def == null) + return new MemberType (new SimpleType (ns), name); + return CreateShortType (def); } public virtual AstType CreateShortType (AstType fullType) { - throw new NotImplementedException(); - //return CreateShortType (Resolve (fullType).Type.Resolve (TypeResolveContext)); + return CreateShortType (Resolve (fullType).Type); } // public abstract IType GetDefinition (AstType resolvedType); diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs index 39d45f9afb..ff7feb58fd 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs @@ -162,7 +162,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring result.NodeSegments [e.AstNode] = new NodeOutput.Segment (stringWriter.GetStringBuilder ().Length); }; visitor.OutputFinished += (sender, e) => { - result.NodeSegments [e.AstNode].EndOffset = stringWriter.GetStringBuilder ().Length; + var nodeSegment = result.NodeSegments [e.AstNode]; + nodeSegment.Length = stringWriter.GetStringBuilder ().Length - nodeSegment.Offset; }; node.AcceptVisitor (visitor, null); result.Text = stringWriter.ToString ().TrimEnd (); diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs index 960b5f7ea3..42fe828b26 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs @@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver SearchScope additionalScope = null; switch (entity.EntityType) { case EntityType.TypeDefinition: - scope = FindTypeDefinitionReferences((ITypeDefinition)entity, this.FindTypeReferencesEvenIfAliased); + scope = FindTypeDefinitionReferences((ITypeDefinition)entity, this.FindTypeReferencesEvenIfAliased, out additionalScope); break; case EntityType.Field: if (entity.DeclaringTypeDefinition != null && entity.DeclaringTypeDefinition.Kind == TypeKind.Enum) @@ -353,14 +353,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region Find TypeDefinition References - SearchScope FindTypeDefinitionReferences(ITypeDefinition typeDefinition, bool findTypeReferencesEvenIfAliased) + SearchScope FindTypeDefinitionReferences(ITypeDefinition typeDefinition, bool findTypeReferencesEvenIfAliased, out SearchScope additionalScope) { string searchTerm = null; - if (!findTypeReferencesEvenIfAliased && ReflectionHelper.GetTypeCode(typeDefinition) == TypeCode.Empty) { - // not a built-in type + additionalScope = null; + if (!findTypeReferencesEvenIfAliased && KnownTypeReference.GetCSharpNameByTypeCode(typeDefinition.KnownTypeCode) == null) { + // We can optimize the search by looking only for the type references with the right identifier, + // but only if it's not a primitive type and we're not looking for indirect references (through an alias) searchTerm = typeDefinition.Name; + if (searchTerm.Length > 9 && searchTerm.EndsWith("Attribute", StringComparison.Ordinal)) { + // The type might be an attribute, so we also need to look for the short form: + string shortForm = searchTerm.Substring(0, searchTerm.Length - 9); + additionalScope = new SearchScope( + shortForm, + delegate (ICompilation compilation) { + ITypeDefinition imported = compilation.Import(typeDefinition); + if (imported != null) + return new FindTypeDefinitionReferencesNavigator(imported, shortForm); + else + return null; + }); + } } - return new SearchScope( searchTerm, delegate (ICompilation compilation) { @@ -404,7 +418,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (searchTerm == null && node is PrimitiveType) return true; - return node is TypeDeclaration || node is DelegateDeclaration; + TypeDeclaration typeDecl = node as TypeDeclaration; + if (typeDecl != null) + return searchTerm == null || typeDecl.Name == searchTerm; + + DelegateDeclaration delegateDecl = node as DelegateDeclaration; + if (delegateDecl != null) + return searchTerm == null || delegateDecl.Name == searchTerm; + + return false; } internal override bool IsMatch(ResolveResult rr) @@ -872,9 +894,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ctor = (IMethod)ctor.MemberDefinition; string searchTerm = null; - if (ReflectionHelper.GetTypeCode(ctor.DeclaringTypeDefinition) == TypeCode.Empty) { + if (KnownTypeReference.GetCSharpNameByTypeCode(ctor.DeclaringTypeDefinition.KnownTypeCode) == null) { // not a built-in type searchTerm = ctor.DeclaringTypeDefinition.Name; + if (searchTerm.Length > 9 && searchTerm.EndsWith("Attribute", StringComparison.Ordinal)) { + // we also need to look for the short form + searchTerm = null; + } } return new SearchScope( searchTerm, @@ -898,7 +924,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal override bool CanMatch(AstNode node) { - return node is ObjectCreateExpression || node is ConstructorDeclaration; + return node is ObjectCreateExpression || node is ConstructorDeclaration || node is Attribute; } internal override bool IsMatch(ResolveResult rr) diff --git a/ICSharpCode.NRefactory.Demo/CSDemo.cs b/ICSharpCode.NRefactory.Demo/CSDemo.cs index b712f1149b..144b4723e1 100644 --- a/ICSharpCode.NRefactory.Demo/CSDemo.cs +++ b/ICSharpCode.NRefactory.Demo/CSDemo.cs @@ -312,10 +312,12 @@ namespace ICSharpCode.NRefactory.Demo FindReferences fr = new FindReferences(); int referenceCount = 0; FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) { + Debug.WriteLine(matchNode.StartLocation + " - " + matchNode + " - " + result); referenceCount++; }; var searchScopes = fr.GetSearchScopes(entity); + Debug.WriteLine("Find references to " + entity.ReflectionName); fr.FindReferencesInFile(searchScopes, parsedFile, compilationUnit, compilation, callback, CancellationToken.None); MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName); diff --git a/ICSharpCode.NRefactory.GtkDemo/MainWindow.cs b/ICSharpCode.NRefactory.GtkDemo/MainWindow.cs index b9a9a4b0d7..adb3981a36 100644 --- a/ICSharpCode.NRefactory.GtkDemo/MainWindow.cs +++ b/ICSharpCode.NRefactory.GtkDemo/MainWindow.cs @@ -86,7 +86,12 @@ namespace ICSharpCode.NRefactory.GtkDemo buttonGenerate.Clicked += CSharpGenerateCodeButtonClick; HandleClicked (this, EventArgs.Empty); } - + protected override void OnDestroyed () + { + base.OnDestroyed (); + Application.Quit (); + } + void HandlePositionChanged (object sender, DocumentLocationEventArgs e) { var node = unit.GetNodeAt (editor.Caret.Line, editor.Caret.Column); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/KeywordTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/KeywordTests.cs index c5efa99280..8cb7a0e8b9 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/KeywordTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/KeywordTests.cs @@ -26,6 +26,8 @@ using System; using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp.Parser; +using System.Linq; namespace ICSharpCode.NRefactory.CSharp.CodeCompletion { diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs index 0860452be7..3f25881829 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs @@ -135,6 +135,34 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion #endregion } + class TypeParameterDataProvider : IParameterDataProvider + { + public IEnumerable Data { get; set; } + #region IParameterDataProvider implementation + public string GetMethodMarkup (int overload, string[] parameterMarkup, int currentParameter) + { + return ""; + } + + public string GetParameterMarkup (int overload, int paramIndex) + { + return ""; + } + + public int GetParameterCount (int overload) + { + var method = Data.ElementAt (overload); + return method.TypeParameterCount; + } + + public int OverloadCount { + get { + return Data.Count (); + } + } + #endregion + } + #region IParameterCompletionDataFactory implementation public IParameterDataProvider CreateConstructorProvider (ICSharpCode.NRefactory.TypeSystem.IType type) { @@ -173,6 +201,12 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion Data = type.GetProperties (p => p.IsIndexer) }; } + public IParameterDataProvider CreateTypeParameterDataProvider (IEnumerable types) + { + return new TypeParameterDataProvider () { + Data = types + }; + } #endregion } @@ -536,7 +570,129 @@ namespace Test Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (2, provider.OverloadCount); } + + [Test()] + public void TestTypeParameter () + { + IParameterDataProvider provider = CreateProvider ( +@"using System; + +namespace Test +{ + class A + { + void Method () + { + $Action<$ + } + } +}"); + Assert.IsNotNull (provider, "provider was not created."); + Assert.AreEqual (16, provider.OverloadCount); + } + + [Test()] + public void TestSecondTypeParameter () + { + IParameterDataProvider provider = CreateProvider ( +@"using System; +namespace Test +{ + class A + { + void Method () + { + $Action() + { + } + + void Method () + { + $TestMethod<$ + } + } +}"); + Assert.IsNotNull (provider, "provider was not created."); + Assert.AreEqual (1, provider.OverloadCount); + } + + [Ignore("TODO")] + [Test()] + public void TestSecondMethodTypeParameter () + { + IParameterDataProvider provider = CreateProvider ( +@"using System; + +namespace Test +{ + class A + { + void TestMethod() + { + } + + void Method () + { + $TestMethod + /// Gets all unresolved type definitions from the file. + /// For partial classes, each part is returned. + /// public static IEnumerable GetAllTypeDefinitions (this IParsedFile file) { return TreeTraversal.PreOrder(file.TopLevelTypeDefinitions, t => t.NestedTypes); } + /// + /// Gets all unresolved type definitions from the assembly. + /// For partial classes, each part is returned. + /// + public static IEnumerable GetAllTypeDefinitions (this IUnresolvedAssembly assembly) + { + return TreeTraversal.PreOrder(assembly.TopLevelTypeDefinitions, t => t.NestedTypes); + } + public static IEnumerable GetAllTypeDefinitions (this IAssembly assembly) { return TreeTraversal.PreOrder(assembly.TopLevelTypeDefinitions, t => t.NestedTypes); } + /// + /// Gets all type definitions in the compilation. + /// This may include types from referenced assemblies that are not accessible in the main assembly. + /// public static IEnumerable GetAllTypeDefinitions (this ICompilation compilation) { return compilation.MainAssembly.GetAllTypeDefinitions() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs index 2114f0c4b3..f32676c220 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs @@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of ISolutionSnapshot. /// - public sealed class DefaultSolutionSnapshot : ISolutionSnapshot + public class DefaultSolutionSnapshot : ISolutionSnapshot { ConcurrentDictionary dictionary = new ConcurrentDictionary();