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); }
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);
internal static ISymbol GetMember(this INamespaceOrTypeSymbol namespaceOrType, string name) => namespaceOrType.GetMembers(name).FirstOrDefault();
public static IEnumerable <INamedTypeSymbol> Types <T>(this INamespaceOrTypeSymbol symbol) => symbol.Types(typeof(T));
public static INamedTypeSymbol GenericType(this INamespaceOrTypeSymbol symbol, string name, int parameters) => symbol.Type(name, type => type.IsGenericType && type.TypeArguments.Length == parameters);
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)); }
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); }
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])); }
public static T GetMember <T>(this INamespaceOrTypeSymbol symbol, string qualifiedName) where T : ISymbol { return((T)symbol.GetMember(qualifiedName)); }
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; }
static IEnumerable <INamedTypeSymbol> Descend(INamespaceOrTypeSymbol symbol) => symbol switch {
// 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)); } } } }
protected abstract (string description, bool hasExistingImport) GetDescription(Document document, INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root, CancellationToken cancellationToken);
public static INamedTypeSymbol Type <T>(this INamespaceOrTypeSymbol symbol) => symbol.Type(typeof(T));
/// <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); }
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()); }
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('.'); }
public static INamedTypeSymbol Type(this INamespaceOrTypeSymbol symbol, string name, Func <INamedTypeSymbol, bool> filter) => symbol.Types(name).FirstOrDefault(filter);
private static NameSyntax GenerateName(INamespaceOrTypeSymbol symbol) { if (symbol is ITypeSymbol) { return ((ITypeSymbol)symbol).GenerateTypeSyntax() as NameSyntax; } else { return SyntaxFactory.ParseName(symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); } }
public static INamedTypeSymbol GetTypeMember(this INamespaceOrTypeSymbol symbol, string name) { return(symbol.GetTypeMembers(name).Single()); }
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; } }
/// <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); } } }
/// <summary> /// Backing implementation of <see cref="LookupNamespacesAndTypes"/>. /// </summary> protected abstract ImmutableArray<ISymbol> LookupNamespacesAndTypesCore( int position, INamespaceOrTypeSymbol container, string name);
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; }
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; }
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; }
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); }
/// <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);
// 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); }
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); }