protected virtual void OnParseComplete(InheritanceParseResultEventArgs e) { if (e == null) { throw new ArgumentNullException("e"); } var t = ParseComplete; if (t != null) { t(this, e); } }
/// <inheritdoc/> protected override void ReParseImpl() { Stopwatch stopwatch = Stopwatch.StartNew(); ITextSnapshot snapshot = TextBuffer.CurrentSnapshot; try { ITextDocument textDocument = TextDocument; string fileName = textDocument != null ? textDocument.FilePath : null; IDECompilerHost host = new IDECompilerHost(); IProject project = null; ILangService languageService; LangService_GetInstance(out languageService); if (languageService != null) { ICSharpTextBuffer csharpBuffer = languageService.FindTextBuffer(fileName); if (csharpBuffer != null) { project = csharpBuffer.Project; } } List <ITagSpan <IInheritanceTag> > tags = new List <ITagSpan <IInheritanceTag> >(); if (host != null && project != null && !string.IsNullOrEmpty(fileName)) { Compilation compilation = host.CreateCompiler(project).GetCompilation(); SourceFile sourceFile; if (!compilation.SourceFiles.TryGetValue(new FileName(fileName), out sourceFile)) { InheritanceParseResultEventArgs errorResult = new InheritanceParseResultEventArgs(snapshot, stopwatch.Elapsed, tags); OnParseComplete(errorResult); return; } ParseTree parseTree = sourceFile.GetParseTree(); SpecializedMatchingMemberCollector collector = new SpecializedMatchingMemberCollector(host.Compilers.Select(i => i.GetCompilation()), false); IEnumerable <ParseTreeNode> nodes = SelectTypes(parseTree); foreach (var node in nodes) { CSharpType type = null; type = compilation.GetTypeFromTypeDeclaration(node); if (type == null) { MarkDirty(true); return; } if (type.IsSealed) { continue; } // types which implement or derive from this type ISet <CSharpType> derivedClasses = collector.GetDerivedTypes(type.SymbolicIdentifier); if (derivedClasses.Count == 0) { continue; } StringBuilder builder = new StringBuilder(); string elementKindDisplayName = "types"; builder.AppendLine("Derived " + elementKindDisplayName + ":"); foreach (var derived in derivedClasses) { builder.AppendLine(" " + derived.GetFullTypeName()); } int nameIndex = node.Token; Token token = parseTree.LexData.Tokens[nameIndex]; ITextSnapshotLine line = snapshot.GetLineFromLineNumber(token.StartPosition.Line); SnapshotSpan span = new SnapshotSpan(snapshot, new Span(line.Start + token.StartPosition.Character, token.EndPosition.Character - token.StartPosition.Character)); InheritanceGlyph tag = type.IsInterface ? InheritanceGlyph.HasImplementations : InheritanceGlyph.Overridden; var targets = derivedClasses.Select(i => new TypeTarget(i.GetFullTypeName(), i.SymbolicIdentifier)); tags.Add(new TagSpan <IInheritanceTag>(span, _tagFactory.CreateTag(tag, builder.ToString().TrimEnd(), targets))); } nodes = parseTree.SelectMethodsPropertiesAndFields(); nodes = nodes.SelectMany(SelectDeclaratorsFromFields); foreach (var node in nodes) { if (node is AccessorDeclarationNode) { // these nodes always result in an ArgumentException in GetMemberFromMemberDeclaration continue; } CSharpMember member; try { member = compilation.GetMemberFromMemberDeclaration(node); } catch (ArgumentException) { continue; } if (member == null) { MarkDirty(true); return; } if (!SpecializedMatchingMemberCollector.IsSupportedMemberType(member)) { continue; } // methods which this method implements ISet <CSharpMemberIdentifier> implementedMethods = collector.GetImplementedInterfaceMembers(member.SymbolicIdentifier); // methods which this method overrides ISet <CSharpMemberIdentifier> overriddenMethods = collector.GetOverriddenBaseMembers(member.SymbolicIdentifier); // methods which override this method ISet <CSharpMemberIdentifier> overridingMethods = collector.GetOverridersFromDerivedTypes(member.SymbolicIdentifier); // methods which implement this method ISet <CSharpMemberIdentifier> implementingMethods = collector.GetImplementorsForInterfaceMember(member.SymbolicIdentifier); if (implementingMethods.Count == 0 && implementedMethods.Count == 0 && overriddenMethods.Count == 0 && overridingMethods.Count == 0) { continue; } StringBuilder builder = new StringBuilder(); string elementKindDisplayName = member.IsProperty ? "properties" : member.IsEvent ? "events" : "methods"; if (implementedMethods.Count > 0) { builder.AppendLine("Implemented " + elementKindDisplayName + ":"); foreach (var methodId in implementedMethods) { builder.AppendLine(" " + methodId.ToString()); } } if (overriddenMethods.Count > 0) { builder.AppendLine("Overridden " + elementKindDisplayName + ":"); foreach (var methodId in overriddenMethods) { builder.AppendLine(" " + methodId.ToString()); } } if (implementingMethods.Count > 0) { builder.AppendLine("Implementing " + elementKindDisplayName + " in derived types:"); foreach (var methodId in implementingMethods) { builder.AppendLine(" " + methodId.ToString()); } } if (overridingMethods.Count > 0) { builder.AppendLine("Overriding " + elementKindDisplayName + " in derived types:"); foreach (var methodId in overridingMethods) { builder.AppendLine(" " + methodId.ToString()); } } int nameIndex = node.Token; Token token = parseTree.LexData.Tokens[nameIndex]; ITextSnapshotLine line = snapshot.GetLineFromLineNumber(token.StartPosition.Line); SnapshotSpan span = new SnapshotSpan(snapshot, new Span(line.Start + token.StartPosition.Character, token.EndPosition.Character - token.StartPosition.Character)); InheritanceGlyph tag; if (implementedMethods.Count > 0) { if (overridingMethods.Count > 0) { tag = InheritanceGlyph.ImplementsAndOverridden; } else if (implementingMethods.Count > 0) { tag = InheritanceGlyph.ImplementsAndHasImplementations; } else { tag = InheritanceGlyph.Implements; } } else if (implementingMethods.Count > 0) { tag = InheritanceGlyph.HasImplementations; } else if (overriddenMethods.Count > 0) { if (overridingMethods.Count > 0) { tag = InheritanceGlyph.OverridesAndOverridden; } else { tag = InheritanceGlyph.Overrides; } } else { tag = InheritanceGlyph.Overridden; } List <CSharpMemberIdentifier> members = new List <CSharpMemberIdentifier>(); members.AddRange(implementedMethods); members.AddRange(overriddenMethods); members.AddRange(implementingMethods); members.AddRange(overridingMethods); var targets = members.Select(i => new MemberTarget(i)); tags.Add(new TagSpan <IInheritanceTag>(span, _tagFactory.CreateTag(tag, builder.ToString().TrimEnd(), targets))); } } InheritanceParseResultEventArgs result = new InheritanceParseResultEventArgs(snapshot, stopwatch.Elapsed, tags); OnParseComplete(result); } catch (InvalidOperationException) { MarkDirty(true); throw; } }
protected virtual void OnParseComplete(InheritanceParseResultEventArgs e) { if (e == null) throw new ArgumentNullException("e"); var t = ParseComplete; if (t != null) t(this, e); }
/// <inheritdoc/> protected override void ReParseImpl() { Stopwatch stopwatch = Stopwatch.StartNew(); ITextSnapshot snapshot = TextBuffer.CurrentSnapshot; try { ITextDocument textDocument = TextDocument; string fileName = textDocument != null ? textDocument.FilePath : null; Document document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); SourceTextContainer textContainer = document != null?document.GetTextAsync().Result.Container : null; Project project = document != null ? document.Project : null; Solution solution = project != null ? project.Solution : null; List <ITagSpan <IInheritanceTag> > tags = new List <ITagSpan <IInheritanceTag> >(); if (document != null && !string.IsNullOrEmpty(fileName)) { SyntaxTree syntaxTree = document.GetSyntaxTreeAsync().Result; SyntaxNode syntaxRoot = syntaxTree.GetRoot(); SemanticModel semanticModel = document.GetSemanticModelAsync().Result; Compilation compilation = semanticModel.Compilation; IDictionary <ISymbol, ISet <ISymbol> > interfaceImplementations = new Dictionary <ISymbol, ISet <ISymbol> >(); List <CSharpSyntaxNode> allMembers = new List <CSharpSyntaxNode>(); IEnumerable <BaseTypeDeclarationSyntax> typeNodes = syntaxRoot.DescendantNodes().OfType <BaseTypeDeclarationSyntax>(); foreach (var typeNode in typeNodes) { ISymbol symbol = semanticModel.GetDeclaredSymbol(typeNode); if (symbol == null) { MarkDirty(true); return; } INamedTypeSymbol typeSymbol = symbol as INamedTypeSymbol; if (typeSymbol == null) { continue; } // get implemented interface symbols foreach (INamedTypeSymbol namedTypeSymbol in typeSymbol.AllInterfaces) { foreach (ISymbol member in namedTypeSymbol.GetMembers()) { ISymbol implementation = typeSymbol.FindImplementationForInterfaceMember(member); if (implementation == null || !implementation.ContainingSymbol.Equals(typeSymbol)) { continue; } ISet <ISymbol> symbols; if (!interfaceImplementations.TryGetValue(implementation, out symbols)) { symbols = new HashSet <ISymbol>(); interfaceImplementations[implementation] = symbols; } symbols.Add(member); } } TypeDeclarationSyntax typeDeclarationSyntax = typeNode as TypeDeclarationSyntax; if (typeDeclarationSyntax != null) { allMembers.AddRange(typeDeclarationSyntax.Members); } if (typeSymbol.IsSealed) { continue; } // types which implement or derive from this type ISet <ITypeSymbol> derivedTypes = new HashSet <ITypeSymbol>(); derivedTypes.UnionWith(FindDerivedClassesAsync.Value(typeSymbol, solution, null, CancellationToken.None).Result); derivedTypes.UnionWith(FindDerivedInterfacesAsync.Value(typeSymbol, solution, null, CancellationToken.None).Result); derivedTypes.UnionWith(FindImplementingTypesAsync.Value(typeSymbol, solution, null, CancellationToken.None).Result); if (derivedTypes.Count == 0) { continue; } StringBuilder builder = new StringBuilder(); string elementKindDisplayName = "types"; builder.AppendLine("Derived " + elementKindDisplayName + ":"); foreach (var derived in derivedTypes) { builder.AppendLine(" " + derived.ToString()); } SyntaxToken identifier = typeNode.Accept(IdentifierSyntaxVisitor.Instance); SnapshotSpan span = new SnapshotSpan(snapshot, new Span(identifier.SpanStart, identifier.Span.Length)); InheritanceGlyph tag = typeSymbol.TypeKind == TypeKind.Interface ? InheritanceGlyph.HasImplementations : InheritanceGlyph.Overridden; var targets = derivedTypes.Select(i => new TypeTarget(textContainer, project, solution, i)); tags.Add(new TagSpan <IInheritanceTag>(span, _tagFactory.CreateTag(tag, builder.ToString().TrimEnd(), targets))); } foreach (var eventFieldDeclarationSyntax in allMembers.OfType <EventFieldDeclarationSyntax>().ToArray()) { allMembers.AddRange(eventFieldDeclarationSyntax.Declaration.Variables); } foreach (CSharpSyntaxNode memberNode in allMembers) { if (!(memberNode is MethodDeclarationSyntax) && !(memberNode is PropertyDeclarationSyntax) && !(memberNode is IndexerDeclarationSyntax) && !(memberNode is EventDeclarationSyntax) && !(memberNode is EventFieldDeclarationSyntax) && !(memberNode is VariableDeclaratorSyntax)) { continue; } ISymbol symbol = semanticModel.GetDeclaredSymbol(memberNode); if (symbol == null) { MarkDirty(true); return; } // members which this member implements ISet <ISymbol> implementedMethods = new HashSet <ISymbol>(); if (!interfaceImplementations.TryGetValue(symbol, out implementedMethods)) { implementedMethods = new HashSet <ISymbol>(); } ISet <ISymbol> overriddenMethods = new HashSet <ISymbol>(); IMethodSymbol methodSymbol = symbol as IMethodSymbol; if (methodSymbol != null) { // methods which this method overrides for (IMethodSymbol current = methodSymbol.OverriddenMethod; current != null; current = current.OverriddenMethod) { overriddenMethods.Add(current); } } else { IPropertySymbol propertySymbol = symbol as IPropertySymbol; if (propertySymbol != null) { // properties which this property overrides for (IPropertySymbol current = propertySymbol.OverriddenProperty; current != null; current = current.OverriddenProperty) { overriddenMethods.Add(current); } } else { IEventSymbol eventSymbol = symbol as IEventSymbol; if (eventSymbol != null) { // events which this event overrides for (IEventSymbol current = eventSymbol.OverriddenEvent; current != null; current = current.OverriddenEvent) { overriddenMethods.Add(current); } } } } ISet <ISymbol> implementingMethods = new HashSet <ISymbol>(SymbolFinder.FindImplementationsAsync(symbol, solution).Result); ISet <ISymbol> overridingMethods = new HashSet <ISymbol>(SymbolFinder.FindOverridesAsync(symbol, solution).Result); if (implementingMethods.Count == 0 && implementedMethods.Count == 0 && overriddenMethods.Count == 0 && overridingMethods.Count == 0) { continue; } StringBuilder builder = new StringBuilder(); string elementKindDisplayName = symbol is IPropertySymbol ? "properties" : symbol is IEventSymbol ? "events" : "methods"; if (implementedMethods.Count > 0) { builder.AppendLine("Implemented " + elementKindDisplayName + ":"); foreach (var methodId in implementedMethods) { builder.AppendLine(" " + methodId.ToString()); } } if (overriddenMethods.Count > 0) { builder.AppendLine("Overridden " + elementKindDisplayName + ":"); foreach (var methodId in overriddenMethods) { builder.AppendLine(" " + methodId.ToString()); } } if (implementingMethods.Count > 0) { builder.AppendLine("Implementing " + elementKindDisplayName + " in derived types:"); foreach (var methodId in implementingMethods) { builder.AppendLine(" " + methodId.ToString()); } } if (overridingMethods.Count > 0) { builder.AppendLine("Overriding " + elementKindDisplayName + " in derived types:"); foreach (var methodId in overridingMethods) { builder.AppendLine(" " + methodId.ToString()); } } SyntaxToken identifier = memberNode.Accept(IdentifierSyntaxVisitor.Instance); SnapshotSpan span = new SnapshotSpan(snapshot, new Span(identifier.SpanStart, identifier.Span.Length)); InheritanceGlyph tag; if (implementedMethods.Count > 0) { if (overridingMethods.Count > 0) { tag = InheritanceGlyph.ImplementsAndOverridden; } else if (implementingMethods.Count > 0) { tag = InheritanceGlyph.ImplementsAndHasImplementations; } else { tag = InheritanceGlyph.Implements; } } else if (implementingMethods.Count > 0) { tag = InheritanceGlyph.HasImplementations; } else if (overriddenMethods.Count > 0) { if (overridingMethods.Count > 0) { tag = InheritanceGlyph.OverridesAndOverridden; } else { tag = InheritanceGlyph.Overrides; } } else { tag = InheritanceGlyph.Overridden; } List <ISymbol> members = new List <ISymbol>(); members.AddRange(implementedMethods); members.AddRange(overriddenMethods); members.AddRange(implementingMethods); members.AddRange(overridingMethods); var targets = members.Select(i => new MemberTarget(textContainer, project, solution, i)); tags.Add(new TagSpan <IInheritanceTag>(span, _tagFactory.CreateTag(tag, builder.ToString().TrimEnd(), targets))); } } InheritanceParseResultEventArgs result = new InheritanceParseResultEventArgs(snapshot, stopwatch.Elapsed, tags); OnParseComplete(result); } catch (InvalidOperationException) { MarkDirty(true); throw; } }