private void Visit(INamespaceOrTypeSymbol type)
		{
			foreach (var method in type.GetMembers().OfType<IMethodSymbol>())
			{
				Visit(method);
			}
		}
        /// <summary>
        /// If container is a tuple type, any of its tuple element which has a friendly name will cause
        /// the suppression of the corresponding default name (ItemN).
        /// In that case, Rest is also removed.
        /// </summary>
        protected static ImmutableArray<ISymbol> SuppressDefaultTupleElements(
            INamespaceOrTypeSymbol container, ImmutableArray<ISymbol> symbols)
        {
            if (container?.IsType != true)
            {
                return symbols;
            }

            var type = (ITypeSymbol)container;
            if (!type.IsTupleType)
            {
                return symbols;
            }

            var tuple = (INamedTypeSymbol)type;
            var elementNames = tuple.TupleElementNames;
            if (elementNames.IsDefault)
            {
                return symbols;
            }

            // TODO This should be revised once we have a good public API for tuple fields
            // See https://github.com/dotnet/roslyn/issues/13229
            var fieldsToRemove = elementNames.Select((n, i) => IsFriendlyName(i, n) ? "Item" + (i + 1) : null)
                .Where(n => n != null).Concat("Rest").ToSet();

            return symbols.WhereAsArray(
                s => s.Kind != SymbolKind.Field ||
                     elementNames.Contains(s.Name) || 
                     !fieldsToRemove.Contains(s.Name));
        }
        public static int CompareTo(this INamespaceOrTypeSymbol n1, INamespaceOrTypeSymbol n2)
        {
            var names1 = s_namespaceOrTypeToNameMap.GetValue(n1, s_getNamePartsCallBack);
            var names2 = s_namespaceOrTypeToNameMap.GetValue(n2, s_getNamePartsCallBack);

            return CompareNameParts(names1, names2);
        }
 public static TypeDiff CompareTo(this INamespaceOrTypeSymbol symbol, INamespaceOrTypeSymbol comparedTo)
 {
     var result = new TypeDiff();
     result.Original = symbol;
     result.ComparedTo = comparedTo;
     result.MethodDifferences = symbol.GetAllContractMembers().FullOuterJoin(comparedTo.GetAllContractMembers(), SymbolComparer.Instance, (a, b) => a.CompareTo(b));
     return result;
 }
		public static Task<Document> AddNamespaceOrTypeDeclarationAsync(Solution solution, INamespaceSymbol destination, INamespaceOrTypeSymbol namespaceOrType, CodeGenerationOptions options = default(CodeGenerationOptions), CancellationToken cancellationToken = default(CancellationToken))
		{
			try {
				return (Task<Document>)addNamespaceOrTypeDeclarationAsyncMethod.Invoke (null, new object[] { solution, destination, namespaceOrType, options != null ? options.Instance : null, cancellationToken });
			} catch (TargetInvocationException ex) {
				ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
				return null;
			}
		}
        private static void GetNameParts(INamespaceOrTypeSymbol namespaceOrTypeSymbol, List<string> result)
        {
            if (namespaceOrTypeSymbol == null || (namespaceOrTypeSymbol.IsNamespace && ((INamespaceSymbol)namespaceOrTypeSymbol).IsGlobalNamespace))
            {
                return;
            }

            GetNameParts(namespaceOrTypeSymbol.ContainingNamespace, result);
            result.Add(namespaceOrTypeSymbol.Name);
        }
Exemple #7
0
 private void dfs_through_members(TreeNodeCollection treenode, INamespaceOrTypeSymbol symbol)
 {
     if (symbol != null && symbol.GetMembers() != null)
     foreach (var el in symbol.GetMembers()) {
         var cur = el as INamespaceOrTypeSymbol;
         if (cur != null) {
             treenode.Add(cur.Name.ToString());
             dfs_through_members(treenode[treenode.Count - 1].Nodes, cur);
         }
     }
 }
        /// <summary>
        /// If container is a tuple type, any of its tuple element which has a friendly name will cause
        /// the suppression of the corresponding default name (ItemN).
        /// In that case, Rest is also removed.
        /// </summary>
        protected static ImmutableArray<ISymbol> SuppressDefaultTupleElements(
            INamespaceOrTypeSymbol container, ImmutableArray<ISymbol> symbols)
        {
            var namedType = container as INamedTypeSymbol;
            if (namedType?.IsTupleType != true)
            {
                // container is not a tuple
                return symbols;
            }

            //return tuple elements followed by other members that are not fields
            return ImmutableArray<ISymbol>.CastUp(namedType.TupleElements).
                Concat(symbols.WhereAsArray(s => s.Kind != SymbolKind.Field));
        }
        public static bool TryGetAliasSymbol(SemanticModel semanticModel, int namespaceId, INamespaceOrTypeSymbol targetSymbol, out IAliasSymbol aliasSymbol)
        {
            // TODO: given semantic model must be not speculative semantic model for now. 
            // currently it can't be checked since it is not exposed to common layer yet.
            // once exposed, this method itself will make sure it use original semantic model
            aliasSymbol = null;
            if (!s_treeAliasMap.TryGetValue(semanticModel.Compilation, out var treeMap) ||
                !treeMap.TryGetValue((semanticModel.SyntaxTree, namespaceId), out var symbolMap))
            {
                return false;
            }

            symbolMap.TryGetValue(targetSymbol, out aliasSymbol);
            return true;
        }
        public static int CompareTo(this INamespaceOrTypeSymbol n1, INamespaceOrTypeSymbol n2)
        {
            var names1 = s_namespaceOrTypeToNameMap.GetValue(n1, GetNameParts);
            var names2 = s_namespaceOrTypeToNameMap.GetValue(n2, GetNameParts);

            for (var i = 0; i < Math.Min(names1.Count, names2.Count); i++)
            {
                var comp = names1[i].CompareTo(names2[i]);
                if (comp != 0)
                {
                    return comp;
                }
            }

            return names1.Count - names2.Count;
        }
            private static IEnumerable<INamedTypeSymbol> Resolve(
                SymbolKeyReader reader,
                INamespaceOrTypeSymbol container,
                string metadataName,
                int arity,
                TypeKind typeKind,
                bool isUnboundGenericType,
                ImmutableArray<SymbolKeyResolution> typeArguments)
            {
                var types = container.GetTypeMembers(GetName(metadataName), arity);
                var result = InstantiateTypes(
                    reader.Compilation, reader.IgnoreAssemblyKey, types, arity, typeArguments);

                return isUnboundGenericType
                    ? result.Select(t => t.ConstructUnboundGenericType())
                    : result;
            }
 public void FindTypeCompilations(INamespaceOrTypeSymbol symbol)
 {
     if (symbol.IsNamespace)
     {
         foreach (var member in (symbol as INamespaceSymbol).GetMembers())
         {
             FindTypeCompilations(member);
         }
     }
     else
     {
         var typeSymbol = symbol as ITypeSymbol;
         foreach (var attribute in typeSymbol.GetAttributes())
         {
             if (attribute.AttributeClass.Name == "AssemblyNeutralAttribute")
             {
                 _typeCompilationContexts.Add(new TypeCompilationContext(this, typeSymbol));
             }
         }
     }
 }
        public static string GetFullMetadataName(INamespaceOrTypeSymbol symbol)
        {
            ISymbol s = symbol;
            var sb = new StringBuilder(s.MetadataName);

            var last = s;
            s = s.ContainingSymbol;
            while (!IsRootNamespace(s))
            {
                if (s is ITypeSymbol && last is ITypeSymbol)
                {
                    sb.Insert(0, '+');
                }
                else
                {
                    sb.Insert(0, '.');
                }
                sb.Insert(0, s.MetadataName);
                s = s.ContainingSymbol;
            }

            return sb.ToString();
        }
        public static IAliasSymbol GetAliasForSymbol(INamespaceOrTypeSymbol symbol, SyntaxToken token, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var originalSemanticModel = semanticModel.GetOriginalSemanticModel();
            if (!originalSemanticModel.SyntaxTree.HasCompilationUnitRoot)
            {
                return null;
            }

            IAliasSymbol aliasSymbol;
            var namespaceId = GetNamespaceIdForAliasSearch(semanticModel, token, cancellationToken);
            if (namespaceId < 0)
            {
                return null;
            }

            if (!AliasSymbolCache.TryGetAliasSymbol(originalSemanticModel, namespaceId, symbol, out aliasSymbol))
            {
                // add cache
                AliasSymbolCache.AddAliasSymbols(originalSemanticModel, namespaceId, semanticModel.LookupNamespacesAndTypes(token.SpanStart).OfType<IAliasSymbol>());

                // retry
                AliasSymbolCache.TryGetAliasSymbol(originalSemanticModel, namespaceId, symbol, out aliasSymbol);
            }

            return aliasSymbol;
        }
 protected abstract Task<Document> AddImportAsync(SyntaxNode contextNode, INamespaceOrTypeSymbol symbol, Document documemt, bool specialCaseSystem, CancellationToken cancellationToken);
Exemple #16
0
 internal static ISymbol GetMember(this INamespaceOrTypeSymbol namespaceOrType, string name)
 => namespaceOrType.GetMembers(name).FirstOrDefault();
Exemple #17
0
 public static IEnumerable <INamedTypeSymbol> Types <T>(this INamespaceOrTypeSymbol symbol) => symbol.Types(typeof(T));
Exemple #18
0
 public static INamedTypeSymbol GenericType(this INamespaceOrTypeSymbol symbol, string name, int parameters) =>
 symbol.Type(name, type => type.IsGenericType && type.TypeArguments.Length == parameters);
Exemple #19
0
 public static INamedTypeSymbol Type(this INamespaceOrTypeSymbol symbol, string name) =>
 symbol.Types(name).FirstOrDefault();
 public static TypeSyntax GenerateTypeSyntax(
     this INamespaceOrTypeSymbol symbol, bool allowVar = true)
 {
     return(GenerateTypeSyntax(symbol, nameSyntax: false, allowVar: allowVar));
 }
Exemple #21
0
        private UsingDirectiveSyntax TryGetUsingDirective(
            Document document,
            INamespaceOrTypeSymbol namespaceOrTypeSymbol,
            SemanticModel semanticModel,
            CompilationUnitSyntax root,
            SyntaxNode contextNode)
        {
            var addImportService = document.GetLanguageService <IAddImportsService>();

            var nameSyntax = namespaceOrTypeSymbol.GenerateNameSyntax();

            // We need to create our using in two passes.  This is because we need a using
            // directive so we can figure out where to put it.  Then, once we figure out
            // where to put it, we might need to change it a bit (e.g. removing 'global'
            // from it if necessary).  So we first create a dummy using directive just to
            // determine which container we're going in.  Then we'll use the container to
            // help create the final using.
            var dummyUsing = SyntaxFactory.UsingDirective(nameSyntax);

            var container        = addImportService.GetImportContainer(root, contextNode, dummyUsing);
            var namespaceToAddTo = container as NamespaceDeclarationSyntax;

            // Replace the alias that GenerateTypeSyntax added if we want this to be looked
            // up off of an extern alias.
            var externAliasDirective = TryGetExternAliasDirective(
                namespaceOrTypeSymbol, semanticModel, contextNode,
                checkForExistingExternAlias: false);

            var externAlias = externAliasDirective?.Identifier.ValueText;

            if (externAlias != null)
            {
                nameSyntax = AddOrReplaceAlias(nameSyntax, SyntaxFactory.IdentifierName(externAlias));
            }
            else
            {
                // The name we generated will have the global:: alias on it.  We only need
                // that if the name of our symbol is actually ambiguous in this context.
                // If so, keep global:: on it, otherwise remove it.
                //
                // Note: doing this has a couple of benefits.  First, it's easy for us to see
                // if we have an existing using for this with the same syntax.  Second,
                // it's easy to sort usings properly.  If "global::" was attached to the
                // using directive, then it would make both of those operations more difficult
                // to achieve.
                nameSyntax = RemoveGlobalAliasIfUnnecessary(semanticModel, nameSyntax, namespaceToAddTo);
            }

            var usingDirective = SyntaxFactory.UsingDirective(nameSyntax)
                                 .WithAdditionalAnnotations(Formatter.Annotation);

            usingDirective = namespaceOrTypeSymbol.IsKind(SymbolKind.Namespace)
                ? usingDirective
                : usingDirective.WithStaticKeyword(SyntaxFactory.Token(SyntaxKind.StaticKeyword));

            if (addImportService.HasExistingImport(semanticModel.Compilation, root, contextNode, usingDirective))
            {
                return(null);
            }

            return(usingDirective);
        }
Exemple #22
0
        private static ImmutableArray <ISymbol> GetMembers(INamespaceOrTypeSymbol container, string qualifiedName, out INamespaceOrTypeSymbol lastContainer)
        {
            var parts = SplitMemberName(qualifiedName);

            lastContainer = container;
            for (int i = 0; i < parts.Length - 1; i++)
            {
                var nestedContainer = (INamespaceOrTypeSymbol)lastContainer.GetMember(parts[i]);
                if (nestedContainer == null)
                {
                    // If there wasn't a nested namespace or type with that name, assume it's a
                    // member name that includes dots (e.g. explicit interface implementation).
                    return(lastContainer.GetMembers(string.Join(".", parts.Skip(i))));
                }
                else
                {
                    lastContainer = nestedContainer;
                }
            }

            return(lastContainer.GetMembers(parts[parts.Length - 1]));
        }
Exemple #23
0
 public static T GetMember <T>(this INamespaceOrTypeSymbol symbol, string qualifiedName) where T : ISymbol
 {
     return((T)symbol.GetMember(qualifiedName));
 }
Exemple #24
0
        public Task <Document> AddNamespaceOrTypeAsync(Solution solution, INamespaceSymbol destination, INamespaceOrTypeSymbol namespaceOrType, CodeGenerationOptions options, CancellationToken cancellationToken)
        {
            if (namespaceOrType == null)
            {
                throw new ArgumentNullException(nameof(namespaceOrType));
            }

            if (namespaceOrType is INamespaceSymbol)
            {
                return(AddNamespaceAsync(solution, destination, (INamespaceSymbol)namespaceOrType, options, cancellationToken));
            }
            else
            {
                return(AddNamedTypeAsync(solution, destination, (INamedTypeSymbol)namespaceOrType, options, cancellationToken));
            }
        }
 protected AbstractWrappedNamespaceOrTypeSymbol(INamespaceOrTypeSymbol symbol, bool canImplementImplicitly, IDocumentationCommentFormattingService docCommentFormattingService)
     : base(symbol, canImplementImplicitly, docCommentFormattingService)
 {
     _symbol = symbol;
 }
        public static List <string> LookupNames(this SemanticModel model, int position, INamespaceOrTypeSymbol container = null, bool namespacesAndTypesOnly = false, bool useBaseReferenceAccessibility = false)
        {
            Assert.True(!useBaseReferenceAccessibility || (object)container == null);
            Assert.True(!useBaseReferenceAccessibility || !namespacesAndTypesOnly);
            var symbols = useBaseReferenceAccessibility
                ? model.LookupBaseMembers(position)
                : namespacesAndTypesOnly
                    ? model.LookupNamespacesAndTypes(position, container)
                    : model.LookupSymbols(position, container);

            return(symbols.Select(s => s.Name).Distinct().ToList());
        }
 private static bool NotNull(INamespaceOrTypeSymbol symbol)
 {
     return symbol != null;
 }
Exemple #28
0
 static IEnumerable <INamedTypeSymbol> Descend(INamespaceOrTypeSymbol symbol) => symbol switch
 {
Exemple #29
0
        // returns all the symbols in the container corresponding to the node
        private void Bind(int index, INamespaceOrTypeSymbol rootContainer, List<ISymbol> results, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var node = _nodes[index];

            if (_nodes[node.ParentIndex].IsRoot)
            {
                results.AddRange(rootContainer.GetMembers(node.Name));
            }
            else
            {
                using (var containerSymbols = SharedPools.Default<List<ISymbol>>().GetPooledObject())
                {
                    Bind(node.ParentIndex, rootContainer, containerSymbols.Object, cancellationToken);

                    foreach (var containerSymbol in containerSymbols.Object.OfType<INamespaceOrTypeSymbol>())
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        results.AddRange(containerSymbol.GetMembers(node.Name));
                    }
                }
            }
        }
Exemple #30
0
 protected abstract (string description, bool hasExistingImport) GetDescription(Document document, INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root, CancellationToken cancellationToken);
Exemple #31
0
 public static INamedTypeSymbol Type <T>(this INamespaceOrTypeSymbol symbol) => symbol.Type(typeof(T));
Exemple #32
0
 /// <summary>
 /// Gets the available named namespace and type symbols in the context of the specified location and optional container.
 /// Only members that are accessible and visible from the given location are returned.
 /// </summary>
 /// <param name="position">The character position for determining the enclosing declaration scope and
 /// accessibility.</param>
 /// <param name="container">The container to search for symbols within. If null then the enclosing declaration
 /// scope around position is used.</param>
 /// <param name="name">The name of the symbol to find. If null is specified then symbols
 /// with any names are returned.</param>
 /// <returns>A list of symbols that were found. If no symbols were found, an empty list is returned.</returns>
 /// <remarks>
 /// The "position" is used to determine what variables are visible and accessible. Even if "container" is
 /// specified, the "position" location is significant for determining which members of "containing" are
 /// accessible. 
 /// 
 /// Does not return INamespaceOrTypeSymbol, because there could be aliases.
 /// </remarks>
 public ImmutableArray<ISymbol> LookupNamespacesAndTypes(
     int position,
     INamespaceOrTypeSymbol container = null,
     string name = null)
 {
     return LookupNamespacesAndTypesCore(position, container, name);
 }
Exemple #33
0
 public static IEnumerable <INamedTypeSymbol> Types(this INamespaceOrTypeSymbol symbol, string name) =>
 symbol.GetTypeMembers().Where(member => member.Name == name);
 private void TestGlyph(
     StandardGlyphGroup expectedGlyphGroup,
     SymbolKind kind = SymbolKind.Method,
     Accessibility declaredAccessibility = Accessibility.NotApplicable,
     bool isExtensionMethod = true,
     MethodKind methodKind = MethodKind.Ordinary,
     INamedTypeSymbol containingType = null,
     bool isConst = false,
     ITypeSymbol elementType = null,
     INamespaceOrTypeSymbol target = null,
     ITypeSymbol pointedAtType = null,
     bool isWithEvents = false,
     TypeKind typeKind = TypeKind.Unknown)
 {
     var symbol = CreateSymbolMock(kind, declaredAccessibility, isExtensionMethod, methodKind, containingType, isConst, elementType, target, pointedAtType, isWithEvents, typeKind);
     Assert.Equal(expectedGlyphGroup, symbol.GetGlyph().GetStandardGlyphGroup());
 }
Exemple #35
0
 public static INamedTypeSymbol GenericType(this INamespaceOrTypeSymbol symbol, string name) =>
 symbol.Type(name, type => type.IsGenericType);
 private static IList<string> GetNameParts(INamespaceOrTypeSymbol symbol)
 {
     return symbol.ToNameDisplayString().Split('.');
 }
Exemple #37
0
 public static INamedTypeSymbol Type(this INamespaceOrTypeSymbol symbol, string name, Func <INamedTypeSymbol, bool> filter) =>
 symbol.Types(name).FirstOrDefault(filter);
Exemple #38
0
 private static NameSyntax GenerateName(INamespaceOrTypeSymbol symbol)
 {
     if (symbol is ITypeSymbol)
     {
         return ((ITypeSymbol)symbol).GenerateTypeSyntax() as NameSyntax;
     }
     else
     {
         return SyntaxFactory.ParseName(symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
     }
 }
Exemple #39
0
 public static INamedTypeSymbol GetTypeMember(this INamespaceOrTypeSymbol symbol, string name)
 {
     return(symbol.GetTypeMembers(name).Single());
 }
Exemple #40
0
 public static INamedTypeSymbol Type(this INamespaceOrTypeSymbol symbol, Type type) => symbol.Types(type).FirstOrDefault();
        private static ImmutableArray <ISymbol> GetSymbolsOffOfBoundExpression(
            CSharpSyntaxContext context,
            ExpressionSyntax originalExpression,
            ExpressionSyntax expression,
            SymbolInfo leftHandBinding,
            INamespaceOrTypeSymbol container,
            CancellationToken cancellationToken)
        {
            var useBaseReferenceAccessibility = false;
            var excludeInstance = false;
            var excludeStatic   = false;
            var symbol          = leftHandBinding.GetBestOrAllSymbols().FirstOrDefault();

            if (symbol != null)
            {
                // If the thing on the left is a type, namespace or alias and the original
                // expression was parenthesized, we shouldn't show anything in IntelliSense.
                if (originalExpression.IsKind(SyntaxKind.ParenthesizedExpression) &&
                    symbol.MatchesKind(SymbolKind.NamedType,
                                       SymbolKind.Namespace,
                                       SymbolKind.Alias))
                {
                    return(ImmutableArray <ISymbol> .Empty);
                }

                // If the thing on the left is a lambda expression, we shouldn't show anything.
                if (symbol.Kind == SymbolKind.Method &&
                    ((IMethodSymbol)symbol).MethodKind == MethodKind.AnonymousFunction)
                {
                    return(ImmutableArray <ISymbol> .Empty);
                }

                // If the thing on the left is an event that can't be used as a field, we shouldn't show anything
                if (symbol.Kind == SymbolKind.Event &&
                    !context.SemanticModel.IsEventUsableAsField(originalExpression.SpanStart, (IEventSymbol)symbol))
                {
                    return(ImmutableArray <ISymbol> .Empty);
                }

                // If the thing on the left is a this parameter (e.g. this or base) and we're in a static context,
                // we shouldn't show anything
                if (symbol.IsThisParameter() &&
                    expression.IsInStaticContext())
                {
                    return(ImmutableArray <ISymbol> .Empty);
                }

                // What is the thing on the left?
                switch (symbol.Kind)
                {
                case SymbolKind.NamedType:
                case SymbolKind.Namespace:
                    excludeInstance = true;
                    container       = (INamespaceOrTypeSymbol)symbol;
                    break;

                case SymbolKind.Alias:
                    excludeInstance = true;
                    container       = ((IAliasSymbol)symbol).Target;
                    break;

                case SymbolKind.Parameter:
                    var parameter = (IParameterSymbol)symbol;

                    excludeStatic = true;

                    // case:
                    //    base.|
                    if (parameter.IsThis && !object.Equals(parameter.Type, container))
                    {
                        useBaseReferenceAccessibility = true;
                    }

                    break;

                default:
                    excludeStatic = true;
                    break;
                }
            }
            else if (container != null)
            {
                excludeStatic = true;
            }
            else
            {
                return(ImmutableArray <ISymbol> .Empty);
            }

            Debug.Assert(!excludeInstance || !excludeStatic);
            Debug.Assert(!excludeInstance || !useBaseReferenceAccessibility);

            // nameof(X.|
            // Show static and instance members.
            if (context.IsNameOfContext)
            {
                excludeInstance = false;
                excludeStatic   = false;
            }

            var position = originalExpression.SpanStart;

            var symbols = useBaseReferenceAccessibility
                ? context.SemanticModel.LookupBaseMembers(position)
                : excludeInstance
                    ? context.SemanticModel.LookupStaticMembers(position, container)
                    : SuppressDefaultTupleElements(container,
                                                   context.SemanticModel.LookupSymbols(position, container, includeReducedExtensionMethods: true));

            // If we're showing instance members, don't include nested types
            return(excludeStatic
                ? symbols.WhereAsArray(s => !s.IsStatic && !(s is ITypeSymbol))
                : symbols);
        }
            public void Resolve(IList <ISymbol> results)
            {
                if (string.IsNullOrEmpty(_name))
                {
                    return;
                }

                // Try to parse the name as declaration ID generated from symbol's documentation comment Id.
                List <ISymbol> docIdResults;

                if (DocumentationCommentId.TryGetSymbolsForDeclarationId(RemovePrefix(_name, s_suppressionPrefix), _compilation, out docIdResults))
                {
                    foreach (var result in docIdResults)
                    {
                        results.Add(result);
                    }

                    return;
                }

                // Parse 'e:' prefix used by FxCop to differentiate between event and non-event symbols of the same name.
                bool isEvent = false;

                if (_name.Length >= 2 && _name[0] == 'e' && _name[1] == ':')
                {
                    isEvent = true;
                    _index  = 2;
                }

                INamespaceOrTypeSymbol containingSymbol = _compilation.GlobalNamespace;
                bool?segmentIsNamedTypeName             = null;

                while (true)
                {
                    var segment = ParseNextNameSegment();

                    // Special case: Roslyn names indexers "this[]" in CSharp, FxCop names them "Item" with parameters in [] brackets
                    bool isIndexerProperty = false;
                    if (segment == "Item" && PeekNextChar() == '[')
                    {
                        isIndexerProperty = true;
                        if (_compilation.Language == LanguageNames.CSharp)
                        {
                            segment = "this[]";
                        }
                    }

                    var candidateMembers = containingSymbol.GetMembers(segment);
                    if (candidateMembers.Length == 0)
                    {
                        return;
                    }

                    if (segmentIsNamedTypeName.HasValue)
                    {
                        candidateMembers = segmentIsNamedTypeName.Value ?
                                           candidateMembers.Where(s => s.Kind == SymbolKind.NamedType).ToImmutableArray() :
                                           candidateMembers.Where(s => s.Kind != SymbolKind.NamedType).ToImmutableArray();

                        segmentIsNamedTypeName = null;
                    }

                    int?            arity      = null;
                    ParameterInfo[] parameters = null;

                    // Check for generic arity
                    if (_scope != TargetScope.Namespace && PeekNextChar() == '`')
                    {
                        ++_index;
                        arity = ReadNextInteger();
                    }

                    // Check for method or indexer parameter list
                    var nextChar = PeekNextChar();

                    if (!isIndexerProperty && nextChar == '(' || isIndexerProperty && nextChar == '[')
                    {
                        parameters = ParseParameterList();
                        if (parameters == null)
                        {
                            // Failed to resolve parameter list
                            return;
                        }
                    }
                    else if (nextChar == '.' || nextChar == '+')
                    {
                        ++_index;

                        if (arity > 0 || nextChar == '+')
                        {
                            // The name continues and either has an arity or specifically continues with a '+'
                            // so segment must be the name of a named type
                            containingSymbol = GetFirstMatchingNamedType(candidateMembers, arity ?? 0);
                        }
                        else
                        {
                            // The name continues with a '.' and does not specify a generic arity
                            // so segment must be the name of a namespace or a named type
                            containingSymbol = GetFirstMatchingNamespaceOrType(candidateMembers);
                        }

                        if (containingSymbol == null)
                        {
                            // If we cannot resolve the name on the left of the delimiter, we have no
                            // hope of finding the symbol.
                            return;
                        }
                        else if (containingSymbol.Kind == SymbolKind.NamedType)
                        {
                            // If segment resolves to a named type, that restricts what the next segment
                            // can resolve to depending on whether the name continues with '+' or '.'
                            segmentIsNamedTypeName = nextChar == '+';
                        }

                        continue;
                    }

                    if (_scope == TargetScope.Member && !isIndexerProperty && parameters != null)
                    {
                        TypeInfo?returnType = null;
                        if (PeekNextChar() == ':')
                        {
                            ++_index;
                            returnType = ParseNamedType(null);
                        }

                        foreach (var method in GetMatchingMethods(candidateMembers, arity, parameters, returnType))
                        {
                            results.Add(method);
                        }

                        return;
                    }

                    ISymbol singleResult = null;

                    switch (_scope)
                    {
                    case TargetScope.Namespace:
                        singleResult = candidateMembers.FirstOrDefault(s => s.Kind == SymbolKind.Namespace);
                        break;

                    case TargetScope.Type:
                        singleResult = GetFirstMatchingNamedType(candidateMembers, arity ?? 0);
                        break;

                    case TargetScope.Member:
                        if (isIndexerProperty)
                        {
                            singleResult = GetFirstMatchingIndexer(candidateMembers, parameters);
                        }
                        else if (isEvent)
                        {
                            singleResult = candidateMembers.FirstOrDefault(s => s.Kind == SymbolKind.Event);
                        }
                        else
                        {
                            singleResult = candidateMembers.FirstOrDefault(s =>
                                                                           s.Kind != SymbolKind.Namespace &&
                                                                           s.Kind != SymbolKind.NamedType);
                        }
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(_scope);
                    }

                    if (singleResult != null)
                    {
                        results.Add(singleResult);
                    }

                    return;
                }
            }
Exemple #43
0
 /// <summary>
 /// Backing implementation of <see cref="LookupSymbols"/>.
 /// </summary>
 protected abstract ImmutableArray<ISymbol> LookupSymbolsCore(
     int position,
     INamespaceOrTypeSymbol container,
     string name,
     bool includeReducedExtensionMethods);
            private TypeInfo?ParseNamedType(ISymbol bindingContext)
            {
                INamespaceOrTypeSymbol containingSymbol = _compilation.GlobalNamespace;
                INamedTypeSymbol       typeSymbol       = null;

                int startIndex = _index;

                while (true)
                {
                    var segment          = ParseNextNameSegment();
                    var candidateMembers = containingSymbol.GetMembers(segment);
                    if (candidateMembers.Length == 0)
                    {
                        return(TypeInfo.CreateUnbound(startIndex));
                    }

                    int        arity         = 0;
                    TypeInfo[] typeArguments = null;

                    // Check for generic arity
                    if (PeekNextChar() == '`')
                    {
                        ++_index;
                        arity = ReadNextInteger();
                    }

                    // Check for type argument list
                    if (PeekNextChar() == '<')
                    {
                        typeArguments = ParseTypeArgumentList(bindingContext);
                        if (typeArguments == null)
                        {
                            return(null);
                        }

                        if (typeArguments.Any(a => !a.IsBound))
                        {
                            return(TypeInfo.CreateUnbound(startIndex));
                        }
                    }

                    var nextChar = PeekNextChar();
                    if (nextChar == '.' || nextChar == '+')
                    {
                        ++_index;

                        if (arity > 0 || nextChar == '+')
                        {
                            // Segment is the name of a named type since the name has an arity or continues with a '+'
                            containingSymbol = GetFirstMatchingNamedType(candidateMembers, arity);
                        }
                        else
                        {
                            // Segment is the name of a namespace or type because the name continues with a '.'
                            containingSymbol = GetFirstMatchingNamespaceOrType(candidateMembers);
                        }

                        if (containingSymbol == null)
                        {
                            // If we cannot resolve the name on the left of the delimiter, we have no
                            // hope of finding the symbol.
                            return(null);
                        }
                        else
                        {
                            continue;
                        }
                    }

                    typeSymbol = GetFirstMatchingNamedType(candidateMembers, arity);
                    if (typeSymbol != null)
                    {
                        if (typeArguments != null)
                        {
                            typeSymbol = typeSymbol.Construct(typeArguments.Select(t => t.Type).ToArray());
                        }

                        return(TypeInfo.Create(typeSymbol));
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
Exemple #45
0
 /// <summary>
 /// Backing implementation of <see cref="LookupNamespacesAndTypes"/>.
 /// </summary>
 protected abstract ImmutableArray<ISymbol> LookupNamespacesAndTypesCore(
     int position,
     INamespaceOrTypeSymbol container,
     string name);
Exemple #46
0
 protected abstract string GetDescription(INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root);
        private static ISymbol CreateSymbolMock(
            SymbolKind kind,
            Accessibility declaredAccessibility = Accessibility.NotApplicable,
            bool isExtensionMethod = false,
            MethodKind methodKind = MethodKind.Ordinary,
            INamedTypeSymbol containingType = null,
            bool isConst = false,
            ITypeSymbol elementType = null,
            INamespaceOrTypeSymbol target = null,
            ITypeSymbol pointedAtType = null,
            bool isWithEvents = false,
            TypeKind typeKind = TypeKind.Unknown)
        {
            var symbolMock = new Mock<ISymbol>();

            symbolMock.SetupGet(s => s.Kind).Returns(kind);
            symbolMock.SetupGet(s => s.DeclaredAccessibility).Returns(declaredAccessibility);
            symbolMock.SetupGet(s => s.ContainingType).Returns(containingType);

            if (kind == SymbolKind.ArrayType)
            {
                var arrayTypeMock = symbolMock.As<IArrayTypeSymbol>();
                arrayTypeMock.SetupGet(s => s.ElementType).Returns(elementType);
            }

            if (kind == SymbolKind.Alias)
            {
                var aliasMock = symbolMock.As<IAliasSymbol>();
                aliasMock.SetupGet(s => s.Target).Returns(target);
            }

            if (kind == SymbolKind.Method)
            {
                var methodTypeMock = symbolMock.As<IMethodSymbol>();
                methodTypeMock.SetupGet(s => s.MethodKind).Returns(methodKind);
                methodTypeMock.SetupGet(s => s.IsExtensionMethod).Returns(isExtensionMethod);
            }

            if (kind == SymbolKind.NamedType)
            {
                var namedTypeMock = symbolMock.As<INamedTypeSymbol>();
                namedTypeMock.SetupGet(s => s.TypeKind).Returns(typeKind);
            }

            if (kind == SymbolKind.Field)
            {
                var fieldMock = symbolMock.As<IFieldSymbol>();
                fieldMock.SetupGet(s => s.IsConst).Returns(isConst);
            }

            if (kind == SymbolKind.PointerType)
            {
                var pointerTypeMock = symbolMock.As<IPointerTypeSymbol>();
                pointerTypeMock.SetupGet(s => s.PointedAtType).Returns(pointedAtType);
            }

            if (kind == SymbolKind.Property)
            {
                var propertyMock = symbolMock.As<IPropertySymbol>();
                propertyMock.SetupGet(s => s.IsWithEvents).Returns(isWithEvents);
            }

            return symbolMock.Object;
        }
Exemple #48
0
 private static bool NotGlobalNamespace(INamespaceOrTypeSymbol symbol)
 {
     return(symbol.IsNamespace ? !((INamespaceSymbol)symbol).IsGlobalNamespace : true);
 }
        private int Compare(INamespaceOrTypeSymbol n1, INamespaceOrTypeSymbol n2)
        {
            Contract.Requires(n1 is INamespaceSymbol || !((INamedTypeSymbol)n1).IsGenericType);
            Contract.Requires(n2 is INamespaceSymbol || !((INamedTypeSymbol)n2).IsGenericType);

            if (n1 is INamedTypeSymbol && n2 is INamespaceSymbol)
            {
                return -1;
            }
            else if (n1 is INamespaceSymbol && n2 is INamedTypeSymbol)
            {
                return 1;
            }

            var names1 = s_symbolToNameMap.GetValue(n1, GetNameParts);
            var names2 = s_symbolToNameMap.GetValue(n2, GetNameParts);

            for (var i = 0; i < Math.Min(names1.Count, names2.Count); i++)
            {
                var comp = names1[i].CompareTo(names2[i]);
                if (comp != 0)
                {
                    return comp;
                }
            }

            return names1.Count - names2.Count;
        }
Exemple #50
0
 private static bool NotNull(INamespaceOrTypeSymbol symbol)
 {
     return(symbol != null);
 }
        private static ImmutableArray<ISymbol> GetSymbolsOffOfBoundExpression(
            CSharpSyntaxContext context,
            ExpressionSyntax originalExpression,
            ExpressionSyntax expression,
            SymbolInfo leftHandBinding,
            INamespaceOrTypeSymbol container,
            CancellationToken cancellationToken)
        {
            var useBaseReferenceAccessibility = false;
            var excludeInstance = false;
            var excludeStatic = false;
            var symbol = leftHandBinding.GetBestOrAllSymbols().FirstOrDefault();

            if (symbol != null)
            {
                // If the thing on the left is a type, namespace or alias and the original
                // expression was parenthesized, we shouldn't show anything in IntelliSense.
                if (originalExpression.IsKind(SyntaxKind.ParenthesizedExpression) &&
                    symbol.MatchesKind(SymbolKind.NamedType,
                                       SymbolKind.Namespace,
                                       SymbolKind.Alias))
                {
                    return ImmutableArray<ISymbol>.Empty;
                }

                // If the thing on the left is a lambda expression, we shouldn't show anything.
                if (symbol.Kind == SymbolKind.Method &&
                    ((IMethodSymbol)symbol).MethodKind == MethodKind.AnonymousFunction)
                {
                    return ImmutableArray<ISymbol>.Empty;
                }

                // If the thing on the left is an event that can't be used as a field, we shouldn't show anything
                if (symbol.Kind == SymbolKind.Event &&
                    !context.SemanticModel.IsEventUsableAsField(originalExpression.SpanStart, (IEventSymbol)symbol))
                {
                    return ImmutableArray<ISymbol>.Empty;
                }

                // If the thing on the left is a this parameter (e.g. this or base) and we're in a static context,
                // we shouldn't show anything
                if (symbol.IsThisParameter() &&
                    expression.IsInStaticContext())
                {
                    return ImmutableArray<ISymbol>.Empty;
                }

                // What is the thing on the left?
                switch (symbol.Kind)
                {
                    case SymbolKind.NamedType:
                    case SymbolKind.Namespace:
                        excludeInstance = true;
                        container = (INamespaceOrTypeSymbol)symbol;
                        break;

                    case SymbolKind.Alias:
                        excludeInstance = true;
                        container = ((IAliasSymbol)symbol).Target;
                        break;

                    case SymbolKind.Parameter:
                        var parameter = (IParameterSymbol)symbol;

                        excludeStatic = true;

                        // case:
                        //    base.|
                        if (parameter.IsThis && !object.Equals(parameter.Type, container))
                        {
                            useBaseReferenceAccessibility = true;
                        }

                        break;

                    default:
                        excludeStatic = true;
                        break;
                }
            }
            else if (container != null)
            {
                excludeStatic = true;
            }
            else
            {
                return ImmutableArray<ISymbol>.Empty;
            }

            Debug.Assert(!excludeInstance || !excludeStatic);
            Debug.Assert(!excludeInstance || !useBaseReferenceAccessibility);

            // nameof(X.|
            // Show static and instance members.
            if (context.IsNameOfContext)
            {
                excludeInstance = false;
                excludeStatic = false;
            }

            var position = originalExpression.SpanStart;

            var symbols = useBaseReferenceAccessibility
                ? context.SemanticModel.LookupBaseMembers(position)
                : excludeInstance
                    ? context.SemanticModel.LookupStaticMembers(position, container)
                    : SuppressDefaultTupleElements(container,
                        context.SemanticModel.LookupSymbols(position, container, includeReducedExtensionMethods: true));

            // If we're showing instance members, don't include nested types
            return excludeStatic
                ? symbols.WhereAsArray(s => !s.IsStatic && !(s is ITypeSymbol))
                : symbols;
        }
Exemple #52
0
        public static bool TryGetAliasSymbol(SemanticModel semanticModel, int namespaceId, INamespaceOrTypeSymbol targetSymbol, out IAliasSymbol aliasSymbol)
        {
            // TODO: given semantic model must be not speculative semantic model for now.
            // currently it can't be checked since it is not exposed to common layer yet.
            // once exposed, this method itself will make sure it use original semantic model
            aliasSymbol = null;
            if (!s_treeAliasMap.TryGetValue(semanticModel.Compilation, out var treeMap) ||
                !treeMap.TryGetValue((semanticModel.SyntaxTree, namespaceId), out var symbolMap))
            {
                return(false);
            }

            symbolMap.TryGetValue(targetSymbol, out aliasSymbol);
            return(true);
        }
 protected abstract string GetDescription(INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root);
 /// <summary>
 /// Create a new solution where the declaration of the destination symbol has an additional namespace or type of the same signature as the specified namespace or type symbol.
 /// Returns the document in the new solution where the destination symbol is declared.
 /// </summary>
 public static Task <Document> AddNamespaceOrTypeDeclarationAsync(Solution solution, INamespaceSymbol destination, INamespaceOrTypeSymbol namespaceOrType, CodeGenerationOptions options = null, CancellationToken cancellationToken = default)
 => GetCodeGenerationService(solution.Workspace, destination.Language).AddNamespaceOrTypeAsync(solution, destination, namespaceOrType, options, cancellationToken);
 private static bool NotGlobalNamespace(INamespaceOrTypeSymbol symbol)
 {
     return symbol.IsNamespace ? !((INamespaceSymbol)symbol).IsGlobalNamespace : true;
 }
 protected abstract Task <Document> AddImportAsync(SyntaxNode contextNode, INamespaceOrTypeSymbol symbol, Document document, bool specialCaseSystem, CancellationToken cancellationToken);
Exemple #57
0
        // returns all the symbols in the container corresponding to the node
        private IEnumerable<ISymbol> Bind(int index, INamespaceOrTypeSymbol rootContainer, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            using (var symbols = SharedPools.Default<List<ISymbol>>().GetPooledObject())
            {
                Bind(index, rootContainer, symbols.Object, cancellationToken);

                foreach (var symbol in symbols.Object)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    yield return symbol;
                }
            }
        }
 protected abstract string TryGetDescription(INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root, bool checkForExistingImport);
 public override INamedTypeSymbol CreateErrorTypeSymbol(INamespaceOrTypeSymbol container, string name, int arity)
 {
     return new ExtendedErrorTypeSymbol((NamespaceOrTypeSymbol)container, name, arity, null);
 }
Exemple #60
0
        private async Task <Document> GetEditAsync(
            Solution solution,
            INamespaceOrTypeSymbol destination,
            Func <
                SyntaxNode,
                CodeGenerationOptions,
                IList <bool>?,
                CancellationToken,
                SyntaxNode
                > declarationTransform,
            CodeGenerationOptions?options,
            CancellationToken cancellationToken
            )
        {
            options ??= CodeGenerationOptions.Default;

            var(destinationDeclaration, availableIndices) =
                await this.FindMostRelevantDeclarationAsync(
                    solution,
                    destination,
                    options,
                    cancellationToken
                    )
                .ConfigureAwait(false);

            if (destinationDeclaration == null)
            {
                throw new ArgumentException(
                          WorkspacesResources.Could_not_find_location_to_generation_symbol_into
                          );
            }

            var destinationTree = destinationDeclaration.SyntaxTree;
            var oldDocument     = solution.GetRequiredDocument(destinationTree);

            if (options.Options is null)
            {
                var documentOptions = await oldDocument
                                      .GetOptionsAsync(cancellationToken)
                                      .ConfigureAwait(false);

                options = options.With(options: documentOptions);
            }

            var transformedDeclaration = declarationTransform(
                destinationDeclaration,
                options,
                availableIndices,
                cancellationToken
                );

            var root = await destinationTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            var currentRoot = root.ReplaceNode(destinationDeclaration, transformedDeclaration);

            var newDocument = oldDocument.WithSyntaxRoot(currentRoot);

            if (options.AddImports)
            {
                newDocument = await ImportAdder
                              .AddImportsFromSymbolAnnotationAsync(
                    newDocument,
                    await newDocument.GetOptionsAsync(cancellationToken).ConfigureAwait(false),
                    cancellationToken
                    )
                              .ConfigureAwait(false);
            }

            return(newDocument);
        }