// Internal for unit tests only. internal MergedNamespaceDeclaration CalculateMergedRoot(CSharpCompilation compilation) { var oldRoot = _cache.MergedRoot.Value; if (_latestLazyRootDeclaration == null) { return(oldRoot); } else if (oldRoot == null) { return(MergedNamespaceDeclaration.Create(_latestLazyRootDeclaration.Value)); } else { var oldRootDeclarations = oldRoot.Declarations; var builder = ArrayBuilder <SingleNamespaceDeclaration> .GetInstance(oldRootDeclarations.Length + 1); builder.AddRange(oldRootDeclarations); builder.Add(_latestLazyRootDeclaration.Value); // Sort the root namespace declarations to match the order of SyntaxTrees. if (compilation != null) { builder.Sort(new RootNamespaceLocationComparer(compilation)); } return(MergedNamespaceDeclaration.Create(builder.ToImmutableAndFree())); } }
public static bool ContainsName( MergedNamespaceDeclaration mergedRoot, Func <string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken ) { return(ContainsNameHelper( mergedRoot, predicate, filter, t => { foreach (var name in t.MemberNames) { if (predicate(name)) { return true; } } return false; }, cancellationToken )); }
public static bool ContainsName( MergedNamespaceDeclaration mergedRoot, string name, SymbolFilter filter, CancellationToken cancellationToken) { return(ContainsNameHelper( mergedRoot, n => n == name, filter, t => t.MemberNames.Contains(name), cancellationToken)); }
public Cache(DeclarationTable table) { this.MergedRoot = new Lazy <MergedNamespaceDeclaration>( () => MergedNamespaceDeclaration.Create(table._allOlderRootDeclarations.InInsertionOrder.AsImmutable <SingleNamespaceDeclaration>())); this.TypeNames = new Lazy <ISet <string> >( () => GetTypeNames(this.MergedRoot.Value)); this.NamespaceNames = new Lazy <ISet <string> >( () => GetNamespaceNames(this.MergedRoot.Value)); this.ReferenceDirectives = new Lazy <ImmutableArray <ReferenceDirective> >( () => MergedRoot.Value.Declarations.OfType <RootSingleNamespaceDeclaration>().SelectMany(r => r.ReferenceDirectives).AsImmutable()); }
// The merged-tree-reuse story goes like this. We have a "forest" of old declarations, and // possibly a lone tree of new declarations. We construct a merged declaration by merging // together everything in the forest. This we can re-use from edit to edit, provided that // nothing is added to or removed from the forest. We construct a merged declaration from // the lone tree if there is one. (The lone tree might have nodes inside it that need // merging, if there are two halves of one partial class.) Once we have two merged trees, we // construct the full merged tree by merging them both together. So, diagrammatically, we // have: // // MergedRoot // / \ // old merged root new merged root // / | | | \ \ // old singles forest new single tree private MergedNamespaceDeclaration GetMergedRoot() { var oldRoot = this.cache.MergedRoot.Value; if (latestLazyRootDeclaration == null) { return(oldRoot); } else if (oldRoot == null) { return(MergedNamespaceDeclaration.Create(latestLazyRootDeclaration.Value)); } else { return(MergedNamespaceDeclaration.Create(oldRoot, latestLazyRootDeclaration.Value)); } }
private ImmutableArray <MergedNamespaceOrTypeDeclaration> MakeChildren() { ArrayBuilder <SingleNamespaceDeclaration> namespaces = null; ArrayBuilder <SingleTypeDeclaration> types = null; bool allNamespacesHaveSameName = true; bool allTypesHaveSameIdentity = true; foreach (var decl in declarations) { foreach (var child in decl.Children) { // it is either a type (more likely) var asType = child as SingleTypeDeclaration; if (asType != null) { // handle types if (types == null) { types = ArrayBuilder <SingleTypeDeclaration> .GetInstance(); } else if (allTypesHaveSameIdentity && !asType.Identity.Equals(types[0].Identity)) { allTypesHaveSameIdentity = false; } types.Add(asType); continue; } // or it is a namespace var asNamespace = child as SingleNamespaceDeclaration; if (asNamespace != null) { // handle namespace if (namespaces == null) { namespaces = ArrayBuilder <SingleNamespaceDeclaration> .GetInstance(); } else if (allNamespacesHaveSameName && !asNamespace.Name.Equals(namespaces[0].Name)) { allNamespacesHaveSameName = false; } namespaces.Add(asNamespace); continue; } // Not sure if we can get here, perhaps, if we have errors, // but we care only about types and namespaces anyways. } } var children = ArrayBuilder <MergedNamespaceOrTypeDeclaration> .GetInstance(); if (namespaces != null) { if (allNamespacesHaveSameName) { children.Add(MergedNamespaceDeclaration.Create(namespaces.ToImmutableAndFree())); } else { var namespaceGroups = namespaces.ToDictionary(n => n.Name); namespaces.Free(); foreach (var namespaceGroup in namespaceGroups.Values) { children.Add(MergedNamespaceDeclaration.Create(namespaceGroup)); } } } if (types != null) { if (allTypesHaveSameIdentity) { children.Add(new MergedTypeDeclaration(types.ToImmutableAndFree())); } else { var typeGroups = types.ToDictionary(t => t.Identity); types.Free(); foreach (var typeGroup in typeGroups.Values) { children.Add(new MergedTypeDeclaration(typeGroup)); } } } return(children.ToImmutableAndFree()); }
public static MergedNamespaceDeclaration Create( MergedNamespaceDeclaration mergedDeclaration, SingleNamespaceDeclaration declaration) { return(new MergedNamespaceDeclaration(mergedDeclaration.declarations.Add(declaration))); }
public static MergedNamespaceDeclaration Create( MergedNamespaceDeclaration mergedDeclaration, SingleNamespaceDeclaration declaration) { return new MergedNamespaceDeclaration(mergedDeclaration._declarations.Add(declaration)); }
private static bool ContainsNameHelper( MergedNamespaceDeclaration mergedRoot, Func <string, bool> predicate, SymbolFilter filter, Func <SingleTypeDeclaration, bool> typePredicate, CancellationToken cancellationToken) { var includeNamespace = (filter & SymbolFilter.Namespace) == SymbolFilter.Namespace; var includeType = (filter & SymbolFilter.Type) == SymbolFilter.Type; var includeMember = (filter & SymbolFilter.Member) == SymbolFilter.Member; var stack = new Stack <MergedNamespaceOrTypeDeclaration>(); stack.Push(mergedRoot); while (stack.Count > 0) { cancellationToken.ThrowIfCancellationRequested(); var current = stack.Pop(); if (current == null) { continue; } if (current.Kind == DeclarationKind.Namespace) { if (includeNamespace && predicate(current.Name)) { return(true); } } else { if (includeType && predicate(current.Name)) { return(true); } if (includeMember) { var mergedType = (MergedTypeDeclaration)current; foreach (var typeDecl in mergedType.Declarations) { if (typePredicate(typeDecl)) { return(true); } } } } foreach (var child in current.Children) { if (child is MergedNamespaceOrTypeDeclaration childNamespaceOrType) { if (includeMember || includeType || childNamespaceOrType.Kind == DeclarationKind.Namespace) { stack.Push(childNamespaceOrType); } } } } return(false); }