private NodeMapBuilder(OrderPreservingMultiDictionary<CSharpSyntaxNode, BoundNode> map, CSharpSyntaxNode thisSyntaxNodeOnly)
 {
     _map = map;
     _thisSyntaxNodeOnly = thisSyntaxNodeOnly;
 }
 private NodeMapBuilder(OrderPreservingMultiDictionary <SyntaxNode, BoundNode> map, SyntaxTree tree, SyntaxNode thisSyntaxNodeOnly)
 {
     _map  = map;
     _tree = tree;
     _thisSyntaxNodeOnly = thisSyntaxNodeOnly;
 }
            public static void AddToMap(BoundNode root, Dictionary <SyntaxNode, ImmutableArray <BoundNode> > map, SyntaxTree tree, SyntaxNode node = null)
            {
                Debug.Assert(node == null || root == null || !(root.Syntax is StatementSyntax), "individually added nodes are not supposed to be statements.");

                if (root == null || map.ContainsKey(root.Syntax))
                {
                    // root node is already in the map, children must be in the map too.
                    return;
                }

                var additionMap = OrderPreservingMultiDictionary <SyntaxNode, BoundNode> .GetInstance();

                var builder = new NodeMapBuilder(additionMap, tree, node);

                builder.Visit(root);

                foreach (CSharpSyntaxNode key in additionMap.Keys)
                {
                    if (map.ContainsKey(key))
                    {
#if DEBUG
                        // It's possible that AddToMap was previously called with a subtree of root.  If this is the case,
                        // then we'll see an entry in the map.  Since the incremental binder should also have seen the
                        // pre-existing map entry, the entry in addition map should be identical.
                        // Another, more unfortunate, possibility is that we've had to re-bind the syntax and the new bound
                        // nodes are equivalent, but not identical, to the existing ones.  In such cases, we prefer the
                        // existing nodes so that the cache will always return the same bound node for a given syntax node.

                        // EXAMPLE: Suppose we have the statement P.M(1);
                        // First, we ask for semantic info about "P".  We'll walk up to the statement level and bind that.
                        // We'll end up with map entries for "1", "P", "P.M(1)", and "P.M(1);".
                        // Next, we ask for semantic info about "P.M".  That isn't in our map, so we walk up to the statement
                        // level - again - and bind that - again.
                        // Once again, we'll end up with map entries for "1", "P", "P.M(1)", and "P.M(1);".  They will
                        // have the same structure as the original map entries, but will not be ReferenceEquals.

                        var existing = map[key];
                        var added    = additionMap[key];
                        Debug.Assert(existing.Length == added.Length, "existing.Length == added.Length");
                        for (int i = 0; i < existing.Length; i++)
                        {
                            // TODO: it would be great if we could check !ReferenceEquals(existing[i], added[i]) (DevDiv #11584).
                            // Known impediments include:
                            //   1) Field initializers aren't cached because they're not in statements.
                            //   2) Single local declarations (e.g. "int x = 1;" vs "int x = 1, y = 2;") aren't found in the cache
                            //      since nothing is cached for the statement syntax.
                            if (existing[i].Kind != added[i].Kind)
                            {
                                Debug.Assert(!(key is StatementSyntax), "!(key is StatementSyntax)");

                                // This also seems to be happening when we get equivalent BoundTypeExpression and BoundTypeOrValueExpression nodes.
                                if (existing[i].Kind == BoundKind.TypeExpression && added[i].Kind == BoundKind.TypeOrValueExpression)
                                {
                                    Debug.Assert(
                                        TypeSymbol.Equals(((BoundTypeExpression)existing[i]).Type, ((BoundTypeOrValueExpression)added[i]).Type, TypeCompareKind.ConsiderEverything2),
                                        string.Format(
                                            System.Globalization.CultureInfo.InvariantCulture,
                                            "((BoundTypeExpression)existing[{0}]).Type == ((BoundTypeOrValueExpression)added[{0}]).Type", i));
                                }
                                else if (existing[i].Kind == BoundKind.TypeOrValueExpression && added[i].Kind == BoundKind.TypeExpression)
                                {
                                    Debug.Assert(
                                        TypeSymbol.Equals(((BoundTypeOrValueExpression)existing[i]).Type, ((BoundTypeExpression)added[i]).Type, TypeCompareKind.ConsiderEverything2),
                                        string.Format(
                                            System.Globalization.CultureInfo.InvariantCulture,
                                            "((BoundTypeOrValueExpression)existing[{0}]).Type == ((BoundTypeExpression)added[{0}]).Type", i));
                                }
                                else
                                {
                                    Debug.Assert(false, "New bound node does not match existing bound node");
                                }
                            }
                            else
                            {
                                Debug.Assert(
                                    (object)existing[i] == added[i] || !(key is StatementSyntax),
                                    string.Format(
                                        System.Globalization.CultureInfo.InvariantCulture,
                                        "(object)existing[{0}] == added[{0}] || !(key is StatementSyntax)", i));
                            }
                        }
#endif
                    }
                    else
                    {
                        map[key] = additionMap[key];
                    }
                }

                additionMap.Free();
            }
예제 #4
0
 private NodeMapBuilder(OrderPreservingMultiDictionary <CSharpSyntaxNode, BoundNode> map, CSharpSyntaxNode thisSyntaxNodeOnly)
 {
     _map = map;
     _thisSyntaxNodeOnly = thisSyntaxNodeOnly;
 }
예제 #5
0
        private static SymbolTreeInfo TryReadSymbolTreeInfo(
            ObjectReader reader,
            Checksum checksum,
            Func <string, ImmutableArray <Node>, Task <SpellChecker> > createSpellCheckerTask)
        {
            try
            {
                var concatenatedNames = reader.ReadString();

                var nodeCount = reader.ReadInt32();
                var nodes     = ArrayBuilder <Node> .GetInstance(nodeCount);

                for (var i = 0; i < nodeCount; i++)
                {
                    var start       = reader.ReadInt32();
                    var length      = reader.ReadInt32();
                    var parentIndex = reader.ReadInt32();

                    nodes.Add(new Node(new TextSpan(start, length), parentIndex));
                }

                var inheritanceMap         = new OrderPreservingMultiDictionary <int, int>();
                var inheritanceMapKeyCount = reader.ReadInt32();
                for (var i = 0; i < inheritanceMapKeyCount; i++)
                {
                    var key        = reader.ReadInt32();
                    var valueCount = reader.ReadInt32();

                    for (var j = 0; j < valueCount; j++)
                    {
                        var value = reader.ReadInt32();
                        inheritanceMap.Add(key, value);
                    }
                }

                MultiDictionary <string, ExtensionMethodInfo> simpleTypeNameToExtensionMethodMap;
                ImmutableArray <ExtensionMethodInfo>          extensionMethodOfComplexType;

                var keyCount = reader.ReadInt32();
                if (keyCount == 0)
                {
                    simpleTypeNameToExtensionMethodMap = null;
                }
                else
                {
                    simpleTypeNameToExtensionMethodMap = new MultiDictionary <string, ExtensionMethodInfo>();

                    for (var i = 0; i < keyCount; i++)
                    {
                        var typeName   = reader.ReadString();
                        var valueCount = reader.ReadInt32();

                        for (var j = 0; j < valueCount; j++)
                        {
                            var containerName = reader.ReadString();
                            var name          = reader.ReadString();

                            simpleTypeNameToExtensionMethodMap.Add(typeName, new ExtensionMethodInfo(containerName, name));
                        }
                    }
                }

                var arrayLength = reader.ReadInt32();
                if (arrayLength == 0)
                {
                    extensionMethodOfComplexType = ImmutableArray <ExtensionMethodInfo> .Empty;
                }
                else
                {
                    var builder = ArrayBuilder <ExtensionMethodInfo> .GetInstance(arrayLength);

                    for (var i = 0; i < arrayLength; ++i)
                    {
                        var containerName = reader.ReadString();
                        var name          = reader.ReadString();
                        builder.Add(new ExtensionMethodInfo(containerName, name));
                    }

                    extensionMethodOfComplexType = builder.ToImmutableAndFree();
                }

                var nodeArray        = nodes.ToImmutableAndFree();
                var spellCheckerTask = createSpellCheckerTask(concatenatedNames, nodeArray);
                return(new SymbolTreeInfo(
                           checksum, concatenatedNames, nodeArray, spellCheckerTask, inheritanceMap,
                           extensionMethodOfComplexType, simpleTypeNameToExtensionMethodMap));
            }
            catch
            {
                Logger.Log(FunctionId.SymbolTreeInfo_ExceptionInCacheRead);
            }

            return(null);
        }
        private static void LookupMetadataDefinitions(
            MetadataReader reader, TypeDefinition typeDefinition,
            OrderPreservingMultiDictionary<string, MetadataDefinition> definitionMap)
        {
            // Only bother looking for extension methods in static types.
            if ((typeDefinition.Attributes & TypeAttributes.Abstract) != 0 &&
                (typeDefinition.Attributes & TypeAttributes.Sealed) != 0)
            {
                foreach (var child in typeDefinition.GetMethods())
                {
                    var method = reader.GetMethodDefinition(child);
                    if ((method.Attributes & MethodAttributes.SpecialName) != 0 ||
                        (method.Attributes & MethodAttributes.RTSpecialName) != 0)
                    {
                        continue;
                    }

                    // SymbolTreeInfo is only searched for types and extension methods.
                    // So we don't want to pull in all methods here.  As a simple approximation
                    // we just pull in methods that have attributes on them.
                    if ((method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public &&
                        (method.Attributes & MethodAttributes.Static) != 0 &&
                        method.GetCustomAttributes().Count > 0)
                    {
                        var definition = new MetadataDefinition(
                            MetadataDefinitionKind.Member, reader.GetString(method.Name));

                        definitionMap.Add(definition.Name, definition);
                    }
                }
            }

            foreach (var child in typeDefinition.GetNestedTypes())
            {
                var type = reader.GetTypeDefinition(child);

                // We don't include internals from metadata assemblies.  It's less likely that
                // a project would have IVT to it and so it helps us save on memory.  It also
                // means we can avoid loading lots and lots of obfuscated code in the case the
                // dll was obfuscated.
                if (IsPublic(type.Attributes))
                {
                    var definition = MetadataDefinition.Create(reader, type);
                    definitionMap.Add(definition.Name, definition);
                }
            }
        }
        private static void LookupMetadataDefinitions(
            MetadataReader reader, NamespaceDefinition namespaceDefinition,
            OrderPreservingMultiDictionary<string, MetadataDefinition> definitionMap)
        {
            foreach (var child in namespaceDefinition.NamespaceDefinitions)
            {
                var definition = MetadataDefinition.Create(reader, child);
                definitionMap.Add(definition.Name, definition);
            }

            foreach (var child in namespaceDefinition.TypeDefinitions)
            {
                var typeDefinition = reader.GetTypeDefinition(child);
                if (IsPublic(typeDefinition.Attributes))
                {
                    var definition = MetadataDefinition.Create(reader, typeDefinition);
                    definitionMap.Add(definition.Name, definition);
                }
            }
        }
        private static void GenerateMetadataNodes(
            MetadataReader reader,
            string name,
            int parentIndex,
            OrderPreservingMultiDictionary<string, MetadataDefinition>.ValueSet definitionsWithSameName,
            List<Node> unsortedNodes)
        {
            var node = new Node(name, parentIndex);
            var nodeIndex = unsortedNodes.Count;
            unsortedNodes.Add(node);

            // Add all child members
            var definitionMap = OrderPreservingMultiDictionary<string, MetadataDefinition>.GetInstance();
            try
            {
                foreach (var definition in definitionsWithSameName)
                {
                    LookupMetadataDefinitions(reader, definition, definitionMap);
                }

                foreach (var kvp in definitionMap)
                {
                    if (UnicodeCharacterUtilities.IsValidIdentifier(kvp.Key))
                    {
                        GenerateMetadataNodes(reader, kvp.Key, nodeIndex, kvp.Value, unsortedNodes);
                    }
                }
            }
            finally
            {
                definitionMap.Free();
            }
        }
 private static void LookupMetadataDefinitions(
     MetadataReader reader, MetadataDefinition definition,
     OrderPreservingMultiDictionary<string, MetadataDefinition> definitionMap)
 {
     switch (definition.Kind)
     {
         case MetadataDefinitionKind.Namespace:
             LookupMetadataDefinitions(reader, definition.Namespace, definitionMap);
             break;
         case MetadataDefinitionKind.Type:
             LookupMetadataDefinitions(reader, definition.Type, definitionMap);
             break;
     }
 }
예제 #10
0
 private SymbolTreeInfo(
     VersionStamp version,
     string concatenatedNames,
     Node[] sortedNodes,
     Task<SpellChecker> spellCheckerTask,
     OrderPreservingMultiDictionary<string, string> inheritanceMap)
     : this(version, concatenatedNames, sortedNodes, spellCheckerTask)
 {
     var indexBasedInheritanceMap = CreateIndexBasedInheritanceMap(inheritanceMap);
     _inheritanceMap = indexBasedInheritanceMap;
 }
예제 #11
0
 private SymbolTreeInfo(
     VersionStamp version,
     string concatenatedNames,
     Node[] sortedNodes,
     Task<SpellChecker> spellCheckerTask,
     OrderPreservingMultiDictionary<int, int> inheritanceMap)
     : this(version, concatenatedNames, sortedNodes, spellCheckerTask)
 {
     _inheritanceMap = inheritanceMap;
 }
예제 #12
0
        private OrderPreservingMultiDictionary<int, int> CreateIndexBasedInheritanceMap(
            OrderPreservingMultiDictionary<string, string> inheritanceMap)
        {
            // All names in metadata will be case sensitive.  
            var comparer = GetComparer(ignoreCase: false);
            var result = new OrderPreservingMultiDictionary<int, int>();

            foreach (var kvp in inheritanceMap)
            {
                var baseName = kvp.Key;
                var baseNameIndex = BinarySearch(baseName);
                Debug.Assert(baseNameIndex >= 0);

                foreach (var derivedName in kvp.Value)
                {
                    foreach (var derivedNameIndex in FindNodeIndices(derivedName, comparer))
                    {
                        result.Add(baseNameIndex, derivedNameIndex);
                    }
                }
            }

            return result;
        }
예제 #13
0
        private static SymbolTreeInfo CreateSymbolTreeInfo(
            Solution solution, VersionStamp version, 
            string filePath, ImmutableArray<BuilderNode> unsortedNodes,
            OrderPreservingMultiDictionary<string, string> inheritanceMap)
        {
            string concatenatedNames;
            Node[] sortedNodes;
            SortNodes(unsortedNodes, out concatenatedNames, out sortedNodes);
            var createSpellCheckerTask = GetSpellCheckerTask(
                solution, version, filePath, concatenatedNames, sortedNodes);

            return new SymbolTreeInfo(
                version, concatenatedNames, sortedNodes, createSpellCheckerTask, inheritanceMap);
        }
예제 #14
0
            private void GenerateMetadataNodes(
                MetadataNode parentNode,
                string nodeName,
                OrderPreservingMultiDictionary<string, MetadataDefinition>.ValueSet definitionsWithSameName)
            {
                if (!UnicodeCharacterUtilities.IsValidIdentifier(nodeName))
                {
                    return;
                }

                var childNode = MetadataNode.Allocate(nodeName);
                _parentToChildren.Add(parentNode, childNode);

                // Add all child members
                var definitionMap = OrderPreservingMultiDictionary<string, MetadataDefinition>.GetInstance();
                try
                {
                    foreach (var definition in definitionsWithSameName)
                    {
                        LookupMetadataDefinitions(definition, definitionMap);
                    }

                    foreach (var kvp in definitionMap)
                    {
                        GenerateMetadataNodes(childNode,kvp.Key, kvp.Value);
                    }
                }
                finally
                {
                    definitionMap.Free();
                }
            }
예제 #15
0
            public MetadataInfoCreator(
                Solution solution, VersionStamp version, PortableExecutableReference reference, CancellationToken cancellationToken)
            {
                _solution = solution;
                _version = version;
                _reference = reference;
                _cancellationToken = cancellationToken;
                _metadataReader = null;
                _allTypeDefinitions = new List<MetadataDefinition>();

                _inheritanceMap = OrderPreservingMultiDictionary<string, string>.GetInstance();
                _parentToChildren = OrderPreservingMultiDictionary<MetadataNode, MetadataNode>.GetInstance();
                _rootNode = MetadataNode.Allocate(name: "");
            }
예제 #16
0
            private void LookupMetadataDefinitions(
                TypeDefinition typeDefinition,
                OrderPreservingMultiDictionary <string, MetadataDefinition> definitionMap)
            {
                // Only bother looking for extension methods in static types.
                // Note this check means we would ignore extension methods declared in assemblies
                // compiled from VB code, since a module in VB is compiled into class with
                // "sealed" attribute but not "abstract".
                // Although this can be addressed by checking custom attributes,
                // we believe this is not a common scenario to warrant potential perf impact.
                if ((typeDefinition.Attributes & TypeAttributes.Abstract) != 0 &&
                    (typeDefinition.Attributes & TypeAttributes.Sealed) != 0)
                {
                    foreach (var child in typeDefinition.GetMethods())
                    {
                        var method = _metadataReader.GetMethodDefinition(child);
                        if ((method.Attributes & MethodAttributes.SpecialName) != 0 ||
                            (method.Attributes & MethodAttributes.RTSpecialName) != 0)
                        {
                            continue;
                        }

                        // SymbolTreeInfo is only searched for types and extension methods.
                        // So we don't want to pull in all methods here.  As a simple approximation
                        // we just pull in methods that have attributes on them.
                        if ((method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public &&
                            (method.Attributes & MethodAttributes.Static) != 0 &&
                            method.GetParameters().Count > 0 &&
                            method.GetCustomAttributes().Count > 0)
                        {
                            // Decode method signature to get the receiver type name (i.e. type name for the first parameter)
                            var blob      = _metadataReader.GetBlobReader(method.Signature);
                            var decoder   = new SignatureDecoder <ParameterTypeInfo, object>(ParameterTypeInfoProvider.Instance, _metadataReader, genericContext: null);
                            var signature = decoder.DecodeMethodSignature(ref blob);

                            // It'd be good if we don't need to go through all parameters and make unnecessary allocations.
                            // However, this is not possible with meatadata reader API right now (although it's possible by copying code from meatadata reader implementaion)
                            if (signature.ParameterTypes.Length > 0)
                            {
                                _containsExtensionsMethod = true;
                                var firstParameterTypeInfo = signature.ParameterTypes[0];
                                var definition             = new MetadataDefinition(MetadataDefinitionKind.Member, _metadataReader.GetString(method.Name), firstParameterTypeInfo);
                                definitionMap.Add(definition.Name, definition);
                            }
                        }
                    }
                }

                foreach (var child in typeDefinition.GetNestedTypes())
                {
                    var type = _metadataReader.GetTypeDefinition(child);

                    // We don't include internals from metadata assemblies.  It's less likely that
                    // a project would have IVT to it and so it helps us save on memory.  It also
                    // means we can avoid loading lots and lots of obfuscated code in the case the
                    // dll was obfuscated.
                    if (IsPublic(type.Attributes))
                    {
                        var definition = MetadataDefinition.Create(_metadataReader, type);
                        definitionMap.Add(definition.Name, definition);
                        _allTypeDefinitions.Add(definition);
                    }
                }
            }