internal ExtendedErrorTypeSymbol(NamespaceOrTypeSymbol containingSymbol, ImmutableArray<Symbol> candidateSymbols, LookupResultKind resultKind, DiagnosticInfo errorInfo, int arity, bool unreported = false) : this(containingSymbol, candidateSymbols[0].Name, arity, errorInfo, unreported) { _candidateSymbols = UnwrapErrorCandidates(candidateSymbols); _resultKind = resultKind; Debug.Assert(candidateSymbols.IsEmpty || resultKind != LookupResultKind.Viable, "Shouldn't use LookupResultKind.Viable with candidate symbols"); }
internal SynthesizedContainer(MethodSymbol topLevelMethod, string name, TypeKind typeKind) { this.typeKind = typeKind; this.containingSymbol = topLevelMethod.ContainingType; this.name = name; this.TypeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out this.typeParameters); }
/// <summary> /// Creates a binder with given import computation function. /// </summary> internal InContainerBinder(Binder next, Func<ConsList<Symbol>, Imports> computeImports) : base(next) { Debug.Assert(computeImports != null); _container = null; _computeImports = computeImports; }
internal SynthesizedContainer(NamedTypeSymbol containingType, string name, TypeKind typeKind) { this.typeKind = typeKind; this.containingSymbol = containingType; this.name = name; this.TypeMap = TypeMap.Empty; this.typeParameters = ImmutableArray<TypeParameterSymbol>.Empty; }
/// <summary> /// Creates a binder with given imports. /// </summary> internal InContainerBinder(NamespaceOrTypeSymbol container, Binder next, Imports imports = null) : base(next) { Debug.Assert((object)container != null); _container = container; _imports = imports ?? Imports.Empty; }
internal List<ISymbol> GetLookupSymbols(string testSrc, NamespaceOrTypeSymbol container = null, string name = null, int? arity = null, bool isScript = false, IEnumerable<string> globalUsings = null) { var tree = Parse(testSrc, options: isScript ? TestOptions.Script : TestOptions.Regular); var compilation = CreateCompilationWithMscorlib(tree, options: TestOptions.ReleaseDll.WithUsings(globalUsings)); var model = compilation.GetSemanticModel(tree); var position = testSrc.Contains("/*<bind>*/") ? GetPositionForBinding(tree) : GetPositionForBinding(testSrc); return model.LookupSymbols(position, container, name).Where(s => !arity.HasValue || arity == ((Symbol)s).GetMemberArity()).ToList(); }
internal ImplicitNamedTypeSymbol(NamespaceOrTypeSymbol containingSymbol, MergedTypeDeclaration declaration, DiagnosticBag diagnostics) : base(containingSymbol, declaration, diagnostics) { Debug.Assert(declaration.Kind == DeclarationKind.ImplicitClass || declaration.Kind == DeclarationKind.Submission || declaration.Kind == DeclarationKind.Script); state.NotePartComplete(CompletionPart.EnumUnderlyingType); // No work to do for this. }
/// <summary> /// Creates a binder for a container with imports (usings and extern aliases) that can be /// retrieved from <paramref name="declarationSyntax"/>. /// </summary> internal InContainerBinder(NamespaceOrTypeSymbol container, Binder next, CSharpSyntaxNode declarationSyntax, bool inUsing) : base(next) { Debug.Assert((object)container != null); Debug.Assert(declarationSyntax != null); _container = container; _computeImports = basesBeingResolved => Imports.FromSyntax(declarationSyntax, this, basesBeingResolved, inUsing); }
private ExtendedErrorTypeSymbol(NamespaceOrTypeSymbol containingSymbol, string name, int arity, DiagnosticInfo errorInfo, bool unreported, bool variableUsedBeforeDeclaration, ImmutableArray<Symbol> candidateSymbols, LookupResultKind resultKind) { _name = name; _errorInfo = errorInfo; _containingSymbol = containingSymbol; _arity = arity; _unreported = unreported; this.VariableUsedBeforeDeclaration = variableUsedBeforeDeclaration; _candidateSymbols = candidateSymbols; _resultKind = resultKind; }
/// <summary> /// Creates a binder for a container with imports (usings and extern aliases) that can be /// retrieved from <paramref name="declarationSyntax"/>. /// </summary> internal InContainerBinder(NamespaceOrTypeSymbol container, Binder next, CSharpSyntaxNode declarationSyntax, bool allowStaticClassUsings, bool inUsing) : base(next) { Debug.Assert((object)container != null); Debug.Assert(declarationSyntax != null); _declarationSyntax = declarationSyntax; _container = container; _allowStaticClassUsings = allowStaticClassUsings; _inUsing = inUsing; }
// constructor for dynamic call-site delegate: public SynthesizedDelegateSymbol( NamespaceOrTypeSymbol containingSymbol, string name, TypeSymbol objectType, TypeSymbol intPtrType, TypeSymbol voidReturnTypeOpt, int parameterCount, BitArray byRefParameters) : base(containingSymbol, name, parameterCount, returnsVoid: (object)voidReturnTypeOpt != null) { this.constructor = new DelegateConstructor(this, objectType, intPtrType); this.invoke = new InvokeMethod(this, byRefParameters, voidReturnTypeOpt); }
internal SourceNamedTypeSymbol(NamespaceOrTypeSymbol containingSymbol, MergedTypeDeclaration declaration, DiagnosticBag diagnostics) : base(containingSymbol, declaration, diagnostics) { Debug.Assert(declaration.Kind == DeclarationKind.Struct || declaration.Kind == DeclarationKind.Interface || declaration.Kind == DeclarationKind.Enum || declaration.Kind == DeclarationKind.Delegate || declaration.Kind == DeclarationKind.Class); if (containingSymbol.Kind == SymbolKind.NamedType) { // Nested types are never unified. _lazyIsExplicitDefinitionOfNoPiaLocalType = ThreeState.False; } }
internal static NamespaceOrTypeSymbol OfMinimalArity(this IEnumerable <NamespaceOrTypeSymbol> symbols) { NamespaceOrTypeSymbol minAritySymbol = null; int minArity = Int32.MaxValue; foreach (var symbol in symbols) { int arity = GetMemberArity(symbol); if (arity < minArity) { minArity = arity; minAritySymbol = symbol; } } return(minAritySymbol); }
internal ExtendedErrorTypeSymbol(NamespaceOrTypeSymbol containingSymbol, string name, int arity, DiagnosticInfo errorInfo, bool unreported = false, bool variableUsedBeforeDeclaration = false) { Debug.Assert(((object)containingSymbol == null) || (containingSymbol.Kind == SymbolKind.Namespace) || (containingSymbol.Kind == SymbolKind.NamedType) || (containingSymbol.Kind == SymbolKind.ErrorType)); Debug.Assert(name != null); Debug.Assert(unreported == false || errorInfo != null); _name = name; _errorInfo = errorInfo; _containingSymbol = containingSymbol; _arity = arity; _unreported = unreported; this.VariableUsedBeforeDeclaration = variableUsedBeforeDeclaration; _resultKind = LookupResultKind.Empty; }
/// <summary> /// Used for <see cref="SynthesizedDelegateSymbol"/> construction. /// </summary> protected SynthesizedContainer(NamespaceOrTypeSymbol containingSymbol, string name, int parameterCount, bool returnsVoid) { var typeParameters = new TypeParameterSymbol[parameterCount + (returnsVoid ? 0 : 1)]; for (int i = 0; i < parameterCount; i++) { typeParameters[i] = new AnonymousTypeManager.AnonymousTypeParameterSymbol(this, i, "T" + (i + 1)); } if (!returnsVoid) { typeParameters[parameterCount] = new AnonymousTypeManager.AnonymousTypeParameterSymbol(this, parameterCount, "TResult"); } this.containingSymbol = containingSymbol; this.name = name; this.TypeMap = TypeMap.Empty; this.typeParameters = typeParameters.AsImmutableOrNull(); }
public Dictionary <String, ImmutableArray <NamespaceOrTypeSymbol> > CreateMap() { var result = new Dictionary <String, ImmutableArray <NamespaceOrTypeSymbol> >(_dictionary.Count, StringOrdinalComparer.Instance); foreach (var kvp in _dictionary) { object value = kvp.Value; ImmutableArray <NamespaceOrTypeSymbol> members; var builder = value as ArrayBuilder <NamespaceOrTypeSymbol>; if (builder != null) { Debug.Assert(builder.Count > 1); bool hasNamespaces = false; for (int i = 0; (i < builder.Count) && !hasNamespaces; i++) { hasNamespaces |= (builder[i].Kind == SymbolKind.Namespace); } members = hasNamespaces ? builder.ToImmutable() : StaticCast <NamespaceOrTypeSymbol> .From(builder.ToDowncastedImmutable <NamedTypeSymbol>()); builder.Free(); } else { NamespaceOrTypeSymbol symbol = (NamespaceOrTypeSymbol)value; #region PackageTemplate - SourceNamespaceSymbol - SymbolKind.Template members = (symbol.Kind == SymbolKind.Namespace || symbol.Kind == SymbolKind.Template) ? ImmutableArray.Create <NamespaceOrTypeSymbol>(symbol) : StaticCast <NamespaceOrTypeSymbol> .From(ImmutableArray.Create <NamedTypeSymbol>((NamedTypeSymbol)symbol)); #endregion } result.Add(kvp.Key, members); } return(result); }
/// <summary> /// Finds types or namespaces described by a qualified name. /// </summary> /// <param name="qualifiedName">Sequence of simple plain names.</param> /// <returns> /// A set of namespace or type symbols with given qualified name (might comprise of types with multiple generic arities), /// or an empty set if the member can't be found (the qualified name is ambiguous or the symbol doesn't exist). /// </returns> /// <remarks> /// "C.D" matches C.D, C{T}.D, C{S,T}.D{U}, etc. /// </remarks> internal IEnumerable <NamespaceOrTypeSymbol> GetNamespaceOrTypeByQualifiedName(IEnumerable <string> qualifiedName) { NamespaceOrTypeSymbol namespaceOrType = this; IEnumerable <NamespaceOrTypeSymbol> symbols = null; foreach (string name in qualifiedName) { if (symbols != null) { // there might be multiple types of different arity, prefer a non-generic type: namespaceOrType = symbols.OfMinimalArity(); if ((object)namespaceOrType == null) { return(SpecializedCollections.EmptyEnumerable <NamespaceOrTypeSymbol>()); } } symbols = namespaceOrType.GetMembers(name).OfType <NamespaceOrTypeSymbol>(); } return(symbols); }
public void Add(NamespaceOrTypeSymbol symbol) { string name = symbol.Name; object item; if (_dictionary.TryGetValue(name, out item)) { var builder = item as ArrayBuilder <NamespaceOrTypeSymbol>; if (builder == null) { builder = ArrayBuilder <NamespaceOrTypeSymbol> .GetInstance(); builder.Add((NamespaceOrTypeSymbol)item); _dictionary[name] = builder; } builder.Add(symbol); } else { _dictionary[name] = symbol; } }
public Dictionary <String, ImmutableArray <NamespaceOrTypeSymbol> > CreateMap() { var result = new Dictionary <String, ImmutableArray <NamespaceOrTypeSymbol> >(this.dictionary.Count); foreach (var kvp in this.dictionary) { object value = kvp.Value; ImmutableArray <NamespaceOrTypeSymbol> members; var builder = value as ArrayBuilder <NamespaceOrTypeSymbol>; if (builder != null) { Debug.Assert(builder.Count > 1); bool hasNamespaces = false; for (int i = 0; (i < builder.Count) && !hasNamespaces; i++) { hasNamespaces |= (builder[i].Kind == SymbolKind.Namespace); } members = hasNamespaces ? builder.ToImmutable() : StaticCast <NamespaceOrTypeSymbol> .From(builder.ToDowncastedImmutable <NamedTypeSymbol>()); builder.Free(); } else { NamespaceOrTypeSymbol symbol = (NamespaceOrTypeSymbol)value; members = symbol.Kind == SymbolKind.Namespace ? ImmutableArray.Create <NamespaceOrTypeSymbol>(symbol) : StaticCast <NamespaceOrTypeSymbol> .From(ImmutableArray.Create <NamedTypeSymbol>((NamedTypeSymbol)symbol)); } result.Add(kvp.Key, members); } return(result); }
internal SourceNamedTypeSymbol(NamespaceOrTypeSymbol containingSymbol, MergedTypeDeclaration declaration, DiagnosticBag diagnostics) : base(containingSymbol, declaration, diagnostics) { Debug.Assert(declaration.Kind == DeclarationKind.Struct || declaration.Kind == DeclarationKind.Interface || declaration.Kind == DeclarationKind.Enum || declaration.Kind == DeclarationKind.Delegate || declaration.Kind == DeclarationKind.Class); if (containingSymbol.Kind == SymbolKind.NamedType) { // Nested types are never unified. _lazyIsExplicitDefinitionOfNoPiaLocalType = ThreeState.False; } if (declaration.Arity == 0 && declaration.HasConstraints) { foreach (var syntaxRef in this.SyntaxReferences) { var constraintClauses = GetConstraintClauses((CSharpSyntaxNode)syntaxRef.GetSyntax()); ReportErrorIfHasConstraints(constraintClauses, diagnostics); } } }
/// <summary> /// Lookup an immediately nested type referenced from metadata, names should be /// compared case-sensitively. /// </summary> /// <param name="emittedTypeName"> /// Simple type name, possibly with generic name mangling. /// </param> /// <returns> /// Symbol for the type, or MissingMetadataSymbol if the type isn't found. /// </returns> internal virtual NamedTypeSymbol LookupMetadataType(ref MetadataTypeName emittedTypeName) { Debug.Assert(!emittedTypeName.IsNull); NamespaceOrTypeSymbol scope = this; if (scope.Kind == SymbolKind.ErrorType) { return(new MissingMetadataTypeSymbol.Nested((NamedTypeSymbol)scope, ref emittedTypeName)); } NamedTypeSymbol namedType = null; ImmutableArray <NamedTypeSymbol> namespaceOrTypeMembers; bool isTopLevel = scope.IsNamespace; Debug.Assert(!isTopLevel || scope.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat) == emittedTypeName.NamespaceName); if (emittedTypeName.IsMangled) { Debug.Assert(!emittedTypeName.UnmangledTypeName.Equals(emittedTypeName.TypeName) && emittedTypeName.InferredArity > 0); if (emittedTypeName.ForcedArity == -1 || emittedTypeName.ForcedArity == emittedTypeName.InferredArity) { // Let's handle mangling case first. namespaceOrTypeMembers = scope.GetTypeMembers(emittedTypeName.UnmangledTypeName); foreach (var named in namespaceOrTypeMembers) { if (emittedTypeName.InferredArity == named.Arity && named.MangleName) { if ((object)namedType != null) { namedType = null; break; } namedType = named; } } } } else { Debug.Assert(ReferenceEquals(emittedTypeName.UnmangledTypeName, emittedTypeName.TypeName) && emittedTypeName.InferredArity == 0); } // Now try lookup without removing generic arity mangling. int forcedArity = emittedTypeName.ForcedArity; if (emittedTypeName.UseCLSCompliantNameArityEncoding) { // Only types with arity 0 are acceptable, we already examined types with mangled names. if (emittedTypeName.InferredArity > 0) { goto Done; } else if (forcedArity == -1) { forcedArity = 0; } else if (forcedArity != 0) { goto Done; } else { Debug.Assert(forcedArity == emittedTypeName.InferredArity); } } namespaceOrTypeMembers = scope.GetTypeMembers(emittedTypeName.TypeName); foreach (var named in namespaceOrTypeMembers) { if (!named.MangleName && (forcedArity == -1 || forcedArity == named.Arity)) { if ((object)namedType != null) { namedType = null; break; } namedType = named; } } Done: if ((object)namedType == null) { if (isTopLevel) { return(new MissingMetadataTypeSymbol.TopLevel(scope.ContainingModule, ref emittedTypeName)); } else { return(new MissingMetadataTypeSymbol.Nested((NamedTypeSymbol)scope, ref emittedTypeName)); } } return(namedType); }
public void Add(NamespaceOrTypeSymbol symbol) { string name = symbol.Name; object item; if (_dictionary.TryGetValue(name, out item)) { var builder = item as ArrayBuilder<NamespaceOrTypeSymbol>; if (builder == null) { builder = ArrayBuilder<NamespaceOrTypeSymbol>.GetInstance(); builder.Add((NamespaceOrTypeSymbol)item); _dictionary[name] = builder; } builder.Add(symbol); } else { _dictionary[name] = symbol; } }
private Symbol GetDeclaredMember(NamespaceOrTypeSymbol container, TextSpan declarationSpan, NameSyntax name) { switch (name.Kind()) { case SyntaxKind.GenericName: case SyntaxKind.IdentifierName: return GetDeclaredMember(container, declarationSpan, ((SimpleNameSyntax)name).Identifier.ValueText); case SyntaxKind.QualifiedName: var qn = (QualifiedNameSyntax)name; var left = GetDeclaredMember(container, declarationSpan, qn.Left) as NamespaceOrTypeSymbol; Debug.Assert((object)left != null); return GetDeclaredMember(left, declarationSpan, qn.Right); case SyntaxKind.AliasQualifiedName: // this is not supposed to happen, but we allow for errors don't we! var an = (AliasQualifiedNameSyntax)name; return GetDeclaredMember(container, declarationSpan, an.Name); default: throw ExceptionUtilities.UnexpectedValue(name.Kind()); } }
private static bool TryAddImport( string alias, NamespaceOrTypeSymbol targetSymbol, ArrayBuilder<NamespaceOrTypeAndUsingDirective> usingsBuilder, ImmutableDictionary<string, AliasAndUsingDirective>.Builder usingAliases, InContainerBinder binder, ImportRecord importRecord) { if (alias == null) { usingsBuilder.Add(new NamespaceOrTypeAndUsingDirective(targetSymbol, usingDirective: null)); } else { IdentifierNameSyntax aliasSyntax; if (!TryParseIdentifierNameSyntax(alias, out aliasSyntax)) { Debug.WriteLine($"Import record '{importRecord}' has syntactically invalid alias '{alias}'"); return false; } var aliasSymbol = AliasSymbol.CreateCustomDebugInfoAlias(targetSymbol, aliasSyntax.Identifier, binder); usingAliases.Add(alias, new AliasAndUsingDirective(aliasSymbol, usingDirective: null)); } return true; }
internal ExtendedErrorTypeSymbol(NamespaceOrTypeSymbol guessSymbol, LookupResultKind resultKind, DiagnosticInfo errorInfo, bool unreported = false) : this(guessSymbol.ContainingNamespaceOrType(), guessSymbol, resultKind, errorInfo, unreported) { }
private void AppendSymbolsWithNameAndArity( ArrayBuilder<Symbol> results, string name, int arity, Binder binder, NamespaceOrTypeSymbol container, LookupOptions options) { Debug.Assert(results != null); // Don't need to de-dup since AllMethodsOnArityZero can't be set at this point (not exposed in CommonLookupOptions). Debug.Assert((options & LookupOptions.AllMethodsOnArityZero) == 0); var lookupResult = LookupResult.GetInstance(); HashSet<DiagnosticInfo> useSiteDiagnostics = null; binder.LookupSymbolsSimpleName( lookupResult, container, name, arity, basesBeingResolved: null, options: options & ~LookupOptions.IncludeExtensionMethods, diagnose: false, useSiteDiagnostics: ref useSiteDiagnostics); if (lookupResult.IsMultiViable) { if (lookupResult.Symbols.Any(t => t.Kind == SymbolKind.NamedType || t.Kind == SymbolKind.Namespace || t.Kind == SymbolKind.ErrorType)) { // binder.ResultSymbol is defined only for type/namespace lookups bool wasError; var diagnostics = DiagnosticBag.GetInstance(); // client code never expects a null diagnostic bag. Symbol singleSymbol = binder.ResultSymbol(lookupResult, name, arity, this.Root, diagnostics, true, out wasError, container, options); diagnostics.Free(); if (!wasError) { results.Add(singleSymbol); } else { results.AddRange(lookupResult.Symbols); } } else { results.AddRange(lookupResult.Symbols); } } lookupResult.Free(); }
private void AppendSymbolsWithName(ArrayBuilder<Symbol> results, string name, Binder binder, NamespaceOrTypeSymbol container, LookupOptions options, LookupSymbolsInfo info) { LookupSymbolsInfo.IArityEnumerable arities; Symbol uniqueSymbol; if (info.TryGetAritiesAndUniqueSymbol(name, out arities, out uniqueSymbol)) { if ((object)uniqueSymbol != null) { // This name mapped to something unique. We don't need to proceed // with a costly lookup. Just add it straight to the results. results.Add(uniqueSymbol); } else { // The name maps to multiple symbols. Actually do a real lookup so // that we will properly figure out hiding and whatnot. if (arities != null) { foreach (var arity in arities) { this.AppendSymbolsWithNameAndArity(results, name, arity, binder, container, options); } } else { //non-unique symbol with non-zero arity doesn't seem possible. this.AppendSymbolsWithNameAndArity(results, name, 0, binder, container, options); } } } }
/// <summary> /// Gets the available named symbols in the context of the specified location and optional /// container. Only symbols 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> /// <param name="options">Additional options that affect the lookup process.</param> /// <param name="useBaseReferenceAccessibility">Ignore 'throughType' in accessibility checking. /// Used in checking accessibility of symbols accessed via 'MyBase' or 'base'.</param> /// <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. /// </remarks> /// <exception cref="ArgumentException">Throws an argument exception if the passed lookup options are invalid.</exception> private ImmutableArray<Symbol> LookupSymbolsInternal( int position, NamespaceOrTypeSymbol container, string name, LookupOptions options, bool useBaseReferenceAccessibility) { Debug.Assert((options & LookupOptions.UseBaseReferenceAccessibility) == 0, "Use the useBaseReferenceAccessibility parameter."); if (useBaseReferenceAccessibility) { options |= LookupOptions.UseBaseReferenceAccessibility; } Debug.Assert(!options.IsAttributeTypeLookup()); // Not exposed publicly. options.ThrowIfInvalid(); SyntaxToken token; position = CheckAndAdjustPosition(position, out token); if ((object)container == null || container.Kind == SymbolKind.Namespace) { options &= ~LookupOptions.IncludeExtensionMethods; } var binder = GetEnclosingBinder(position); if (binder == null) { return ImmutableArray<Symbol>.Empty; } if (useBaseReferenceAccessibility) { Debug.Assert((object)container == null); TypeSymbol containingType = binder.ContainingType; TypeSymbol baseType = null; // For a script class or a submission class base should have no members. if ((object)containingType != null && containingType.Kind == SymbolKind.NamedType && ((NamedTypeSymbol)containingType).IsScriptClass) { return ImmutableArray<Symbol>.Empty; } if ((object)containingType == null || (object)(baseType = containingType.BaseTypeNoUseSiteDiagnostics) == null) { throw new ArgumentException( "Not a valid position for a call to LookupBaseMembers (must be in a type with a base type)", nameof(position)); } container = baseType; } if (!binder.IsInMethodBody && (options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.NamespacesOrTypesOnly | LookupOptions.LabelsOnly)) == 0) { // Method type parameters are not in scope outside a method // body unless the position is either: // a) in a type-only context inside an expression, or // b) inside of an XML name attribute in an XML doc comment. var parentExpr = token.Parent as ExpressionSyntax; if (parentExpr != null && !(parentExpr.Parent is XmlNameAttributeSyntax) && !SyntaxFacts.IsInTypeOnlyContext(parentExpr)) { options |= LookupOptions.MustNotBeMethodTypeParameter; } } var info = LookupSymbolsInfo.GetInstance(); if ((object)container == null) { binder.AddLookupSymbolsInfo(info, options); } else { binder.AddMemberLookupSymbolsInfo(info, container, options, binder); } var results = ArrayBuilder<Symbol>.GetInstance(info.Count); if (name == null) { // If they didn't provide a name, then look up all names and associated arities // and find all the corresponding symbols. foreach (string foundName in info.Names) { AppendSymbolsWithName(results, foundName, binder, container, options, info); } } else { // They provided a name. Find all the arities for that name, and then look all of those up. AppendSymbolsWithName(results, name, binder, container, options, info); } info.Free(); if ((options & LookupOptions.IncludeExtensionMethods) != 0) { var lookupResult = LookupResult.GetInstance(); options |= LookupOptions.AllMethodsOnArityZero; options &= ~LookupOptions.MustBeInstance; HashSet<DiagnosticInfo> useSiteDiagnostics = null; binder.LookupExtensionMethods(lookupResult, name, 0, options, ref useSiteDiagnostics); if (lookupResult.IsMultiViable) { TypeSymbol containingType = (TypeSymbol)container; foreach (MethodSymbol extensionMethod in lookupResult.Symbols) { var reduced = extensionMethod.ReduceExtensionMethod(containingType); if ((object)reduced != null) { results.Add(reduced); } } } lookupResult.Free(); } ImmutableArray<Symbol> sealedResults = results.ToImmutableAndFree(); return name == null ? FilterNotReferencable(sealedResults) : sealedResults; }
private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics) { SimpleNameSyntax nameSyntax = syntax.Name as SimpleNameSyntax; int arity; string memberName; if (nameSyntax != null) { arity = nameSyntax.Arity; memberName = nameSyntax.Identifier.ValueText; } else { // If the name isn't a SimpleNameSyntax, then we must have a type name followed by a parameter list. // Thus, we're looking for a constructor. Debug.Assert((object)containerOpt == null); // Could be an error type, but we'll just lookup fail below. containerOpt = BindNamespaceOrTypeSymbolInCref(syntax.Name); arity = 0; memberName = WellKnownMemberNames.InstanceConstructorName; } if (string.IsNullOrEmpty(memberName)) { ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, arity, syntax.Parameters != null, diagnostics); if (sortedSymbols.IsEmpty) { ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } return ProcessCrefMemberLookupResults( sortedSymbols, arity, syntax, typeArgumentListSyntax: arity == 0 ? null : ((GenericNameSyntax)nameSyntax).TypeArgumentList, parameterListSyntax: syntax.Parameters, ambiguityWinner: out ambiguityWinner, diagnostics: diagnostics); }
private ImmutableArray<Symbol> BindIndexerMemberCref(IndexerMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics) { const int arity = 0; ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, WellKnownMemberNames.Indexer, arity, syntax.Parameters != null, diagnostics); if (sortedSymbols.IsEmpty) { ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } // Since only indexers are named WellKnownMemberNames.Indexer. Debug.Assert(sortedSymbols.All(SymbolExtensions.IsIndexer)); // NOTE: guaranteed to be a property, because only indexers are considered. return ProcessCrefMemberLookupResults( sortedSymbols, arity, syntax, typeArgumentListSyntax: null, parameterListSyntax: syntax.Parameters, ambiguityWinner: out ambiguityWinner, diagnostics: diagnostics); }
internal ExtendedErrorTypeSymbol(NamespaceOrTypeSymbol containingSymbol, Symbol guessSymbol, LookupResultKind resultKind, DiagnosticInfo errorInfo, bool unreported = false) : this(containingSymbol, ImmutableArray.Create <Symbol>(guessSymbol), resultKind, errorInfo, GetArity(guessSymbol), unreported) { }
// NOTE: not guaranteed to be a method (e.g. class op_Addition) // NOTE: constructor fallback logic applies private ImmutableArray<Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics) { const int arity = 0; CrefParameterListSyntax parameterListSyntax = syntax.Parameters; // NOTE: Prefer binary to unary, unless there is exactly one parameter. // CONSIDER: we're following dev11 by never using a binary operator name if there's // exactly one parameter, but doing so would allow us to match single-parameter constructors. SyntaxKind operatorTokenKind = syntax.OperatorToken.CSharpKind(); string memberName = parameterListSyntax != null && parameterListSyntax.Parameters.Count == 1 ? null : OperatorFacts.BinaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind); memberName = memberName ?? OperatorFacts.UnaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind); if (memberName == null) { ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, arity, syntax.Parameters != null, diagnostics); if (sortedSymbols.IsEmpty) { ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } return ProcessCrefMemberLookupResults( sortedSymbols, arity, syntax, typeArgumentListSyntax: null, parameterListSyntax: parameterListSyntax, ambiguityWinner: out ambiguityWinner, diagnostics: diagnostics); }
private void AppendMembers(StringBuilder result, NamespaceOrTypeSymbol container, string indent) { string memberIndent; if (container is NamedTypeSymbol) { memberIndent = indent + " "; result.Append(indent); result.AppendLine("{"); AppendCustomAttributes(result, container, indent, inBlock: true); if (container.GetAttributes().Length > 0) { result.AppendLine(); } } else { memberIndent = indent; } foreach (var member in container.GetMembers().OrderBy(m => m.Name, System.StringComparer.InvariantCulture)) { switch (member.Kind) { case SymbolKind.NamedType: var namedType = (PENamedTypeSymbol)member; result.Append(memberIndent); result.Append(".class "); MetadataSignatureHelper.AppendTypeAttributes(result, namedType.Flags); result.Append(" "); result.Append(member); if (namedType.BaseType != null) { result.AppendLine(); result.Append(memberIndent); result.Append(" extends "); result.Append(namedType.BaseType); } if (namedType.Interfaces.Length > 0) { result.AppendLine(); result.Append(memberIndent); result.Append(" implements "); result.Append(string.Join(", ", namedType.Interfaces)); } result.AppendLine(); AppendMembers(result, namedType, memberIndent); break; case SymbolKind.Namespace: var ns = member as PENamespaceSymbol; if ((object)ns != null) { AppendMembers(result, ns, indent); } break; case SymbolKind.Method: var method = member as PEMethodSymbol; if ((object)method != null && method.AssociatedSymbol == null) { result.Append(memberIndent); result.Append(".method "); AppendMethod(result, method, memberIndent); AppendCustomAttributes(result, member, memberIndent, inBlock: false); } break; case SymbolKind.Field: var field = (PEFieldSymbol)member; result.Append(memberIndent); result.Append(".field "); MetadataSignatureHelper.AppendFieldAttributes(result, field.Flags); result.Append(" "); result.Append(field.Type); result.Append(" "); result.Append(member.Name); result.AppendLine(); AppendCustomAttributes(result, member, memberIndent, inBlock: false); break; case SymbolKind.Property: var property = (PEPropertySymbol)member; string propertyName; result.Append(memberIndent); result.Append(".property "); PropertyAttributes propertyAttrs; ((PEModuleSymbol)container.ContainingModule).Module.GetPropertyDefPropsOrThrow(property.Handle, out propertyName, out propertyAttrs); if (MetadataSignatureHelper.AppendPropertyAttributes(result, propertyAttrs)) { result.Append(" "); } result.Append(property.Type); result.Append(" "); result.Append(property.Name); result.AppendLine(); result.Append(memberIndent); result.AppendLine("{"); AppendCustomAttributes(result, member, memberIndent, inBlock: true); if (property.GetMethod != null) { result.Append(memberIndent); result.Append(" .get "); AppendMethod(result, (PEMethodSymbol)property.GetMethod, memberIndent); } if (property.SetMethod != null) { result.Append(memberIndent); result.Append(" .set "); AppendMethod(result, (PEMethodSymbol)property.SetMethod, memberIndent); } result.Append(memberIndent); result.AppendLine("}"); break; case SymbolKind.Event: var evnt = (PEEventSymbol)member; result.Append(memberIndent); result.Append(".event "); string eventName; EventAttributes eventAttrs; EntityHandle type; ((PEModuleSymbol)container.ContainingModule).Module.GetEventDefPropsOrThrow(evnt.Handle, out eventName, out eventAttrs, out type); if (MetadataSignatureHelper.AppendEventAttributes(result, eventAttrs)) { result.Append(" "); } result.Append(evnt.Type); result.Append(" "); result.Append(evnt.Name); result.AppendLine(); result.Append(memberIndent); result.Append("{"); result.AppendLine(); AppendCustomAttributes(result, member, memberIndent, inBlock: true); if (evnt.RemoveMethod != null) { result.Append(memberIndent); result.Append(" .removeon "); AppendMethod(result, (PEMethodSymbol)evnt.RemoveMethod, memberIndent); } if (evnt.AddMethod != null) { result.Append(memberIndent); result.Append(" .addon "); AppendMethod(result, (PEMethodSymbol)evnt.AddMethod, memberIndent); } result.Append(memberIndent); result.AppendLine("}"); break; } } if (container is NamedTypeSymbol) { result.Append(indent); result.AppendLine("}"); } }
// NOTE: not guaranteed to be a method (e.g. class op_Implicit) private ImmutableArray<Symbol> BindConversionOperatorMemberCref(ConversionOperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics) { const int arity = 0; string memberName = syntax.ImplicitOrExplicitKeyword.CSharpKind() == SyntaxKind.ImplicitKeyword ? WellKnownMemberNames.ImplicitConversionName : WellKnownMemberNames.ExplicitConversionName; ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, arity, syntax.Parameters != null, diagnostics); if (sortedSymbols.IsEmpty) { ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } TypeSymbol returnType = BindCrefParameterOrReturnType(syntax.Type, syntax, diagnostics); // Filter out methods with the wrong return type, since overload resolution won't catch these. sortedSymbols = sortedSymbols.WhereAsArray(symbol => symbol.Kind != SymbolKind.Method || ((MethodSymbol)symbol).ReturnType == returnType); if (!sortedSymbols.Any()) { ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } return ProcessCrefMemberLookupResults( sortedSymbols, arity, syntax, typeArgumentListSyntax: null, parameterListSyntax: syntax.Parameters, ambiguityWinner: out ambiguityWinner, diagnostics: diagnostics); }
/// <summary> /// Finds the member in the containing symbol which is inside the given declaration span. /// </summary> private Symbol GetDeclaredMember(NamespaceOrTypeSymbol container, TextSpan declarationSpan, string name = null) { if ((object)container == null) { return null; } // look for any member with same declaration location var collection = name != null ? container.GetMembers(name) : container.GetMembersUnordered(); Symbol zeroWidthMatch = null; foreach (var symbol in collection) { var namedType = symbol as ImplicitNamedTypeSymbol; if ((object)namedType != null && namedType.IsImplicitClass) { // look inside wrapper around illegally placed members in namespaces var result = GetDeclaredMember(namedType, declarationSpan, name); if ((object)result != null) { return result; } } foreach (var loc in symbol.Locations) { if (loc.IsInSource && loc.SourceTree == this.SyntaxTree && declarationSpan.Contains(loc.SourceSpan)) { if (loc.SourceSpan.IsEmpty && loc.SourceSpan.End == declarationSpan.Start) { // exclude decls created via syntax recovery zeroWidthMatch = symbol; } else { return symbol; } } } // Handle the case of the implementation of a partial method. var partial = symbol.Kind == SymbolKind.Method ? ((MethodSymbol)symbol).PartialImplementationPart : null; if ((object)partial != null) { var loc = partial.Locations[0]; if (loc.IsInSource && loc.SourceTree == this.SyntaxTree && declarationSpan.Contains(loc.SourceSpan)) { return partial; } } } // If we didn't find anything better than the symbol that matched because of syntax error recovery, then return that. // Otherwise, if there's a name, try again without a name. // Otherwise, give up. return zeroWidthMatch ?? (name != null ? GetDeclaredMember(container, declarationSpan) : null); }
/// <summary> /// Perform lookup (optionally, in a specified container). If nothing is found and the member name matches the containing type /// name, then use the instance constructors of the type instead. The resulting symbols are sorted since tie-breaking is based /// on order and we want cref binding to be repeatable. /// </summary> /// <remarks> /// Never returns null. /// </remarks> private ImmutableArray<Symbol> ComputeSortedCrefMembers(CSharpSyntaxNode syntax, NamespaceOrTypeSymbol containerOpt, string memberName, int arity, bool hasParameterList, DiagnosticBag diagnostics) { HashSet<DiagnosticInfo> useSiteDiagnostics = null; var result = ComputeSortedCrefMembers(containerOpt, memberName, arity, hasParameterList, ref useSiteDiagnostics); diagnostics.Add(syntax, useSiteDiagnostics); return result; }
/// <summary> /// Lookup an immediately nested type referenced from metadata, names should be /// compared case-sensitively. /// </summary> /// <param name="emittedTypeName"> /// Simple type name, possibly with generic name mangling. /// </param> /// <returns> /// Symbol for the type, or MissingMetadataSymbol if the type isn't found. /// </returns> internal virtual NamedTypeSymbol LookupMetadataType(ref MetadataTypeName emittedTypeName) { Debug.Assert(!emittedTypeName.IsNull); NamespaceOrTypeSymbol scope = this; Debug.Assert(scope is not MergedNamespaceSymbol); if (scope.Kind == SymbolKind.ErrorType) { return(new MissingMetadataTypeSymbol.Nested((NamedTypeSymbol)scope, ref emittedTypeName)); } NamedTypeSymbol?namedType = null; ImmutableArray <NamedTypeSymbol> namespaceOrTypeMembers; bool isTopLevel = scope.IsNamespace; Debug.Assert(!isTopLevel || scope.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat) == emittedTypeName.NamespaceName); if (emittedTypeName.IsMangled) { Debug.Assert(!emittedTypeName.UnmangledTypeName.Equals(emittedTypeName.TypeName) && emittedTypeName.InferredArity > 0); if (emittedTypeName.ForcedArity == -1 || emittedTypeName.ForcedArity == emittedTypeName.InferredArity) { // Let's handle mangling case first. namespaceOrTypeMembers = scope.GetTypeMembers(emittedTypeName.UnmangledTypeName); foreach (var named in namespaceOrTypeMembers) { if (emittedTypeName.InferredArity == named.Arity && named.MangleName) { if ((object?)namedType != null) { namedType = null; break; } namedType = named; } } } } else { Debug.Assert(ReferenceEquals(emittedTypeName.UnmangledTypeName, emittedTypeName.TypeName) && emittedTypeName.InferredArity == 0); } // Now try lookup without removing generic arity mangling. int forcedArity = emittedTypeName.ForcedArity; if (emittedTypeName.UseCLSCompliantNameArityEncoding) { // Only types with arity 0 are acceptable, we already examined types with mangled names. if (emittedTypeName.InferredArity > 0) { goto Done; } else if (forcedArity == -1) { forcedArity = 0; } else if (forcedArity != 0) { goto Done; } else { Debug.Assert(forcedArity == emittedTypeName.InferredArity); } } namespaceOrTypeMembers = scope.GetTypeMembers(emittedTypeName.TypeName); foreach (var named in namespaceOrTypeMembers) { if (!named.MangleName && (forcedArity == -1 || forcedArity == named.Arity)) { if ((object?)namedType != null) { namedType = null; break; } namedType = named; } } Done: if (isTopLevel && scope is not PENamespaceSymbol && (emittedTypeName.ForcedArity == -1 || emittedTypeName.ForcedArity == emittedTypeName.InferredArity) && GeneratedNameParser.TryParseFileTypeName( emittedTypeName.UnmangledTypeName, out string?displayFileName, out int ordinal, out string?sourceName)) { // also do a lookup for file types from source. namespaceOrTypeMembers = scope.GetTypeMembers(sourceName); foreach (var named in namespaceOrTypeMembers) { if (named.AssociatedSyntaxTree is SyntaxTree tree && getDisplayName(tree) == displayFileName && named.DeclaringCompilation.GetSyntaxTreeOrdinal(tree) == ordinal && named.Arity == emittedTypeName.InferredArity) { if ((object?)namedType != null) { namedType = null; break; } namedType = named; } } } if ((object?)namedType == null) { if (isTopLevel) { return(new MissingMetadataTypeSymbol.TopLevel(scope.ContainingModule, ref emittedTypeName)); } else { return(new MissingMetadataTypeSymbol.Nested((NamedTypeSymbol)scope, ref emittedTypeName)); } } return(namedType);
private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol containerOpt, string memberName, int arity, bool hasParameterList, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { // Since we may find symbols without going through the lookup API, // expose the symbols via an ArrayBuilder. ArrayBuilder<Symbol> builder; { LookupResult result = LookupResult.GetInstance(); this.LookupSymbolsOrMembersInternal( result, containerOpt, name: memberName, arity: arity, basesBeingResolved: null, options: LookupOptions.AllMethodsOnArityZero, diagnose: false, useSiteDiagnostics: ref useSiteDiagnostics); // CONSIDER: Dev11 also checks for a constructor in the event of an ambiguous result. if (result.IsMultiViable) { // Dev11 doesn't consider members from System.Object when the container is an interface. // Lookup should already have dropped such members. builder = ArrayBuilder<Symbol>.GetInstance(); builder.AddRange(result.Symbols); result.Free(); } else { result.Free(); // Won't be using this. // Dev11 has a complicated two-stage process for determining when a cref is really referring to a constructor. // Under two sets of conditions, XmlDocCommentBinder::bindXMLReferenceName will decide that a name refers // to a constructor and under one set of conditions, the calling method, XmlDocCommentBinder::bindXMLReference, // will roll back that decision and return null. // In XmlDocCommentBinder::bindXMLReferenceName: // 1) If an unqualified, non-generic name didn't bind to anything and the name matches the name of the type // to which the doc comment is applied, then bind to a constructor. // 2) If a qualified, non-generic name didn't bind to anything and the LHS of the qualified name is a type // with the same name, then bind to a constructor. // Quoted from XmlDocCommentBinder::bindXMLReference: // Filtering out the case where specifying the name of a generic type without specifying // any arity returns a constructor. This case shouldn't return anything. Note that // returning the constructors was a fix for the wonky constructor behavior, but in order // to not introduce a regression and breaking change we return NULL in this case. // e.g. // // /// <see cref="Foo"/> // class Foo<T> { } // // This cref used not to bind to anything, because before it was looking for a type and // since there was no arity, it didn't find Foo<T>. Now however, it finds Foo<T>.ctor, // which is arguably correct, but would be a breaking change (albeit with minimal impact) // so we catch this case and chuck out the symbol found. // In Roslyn, we're doing everything in one pass, rather than guessing and rolling back. // As in the native compiler, we treat this as a fallback case - something that actually has the // specified name is preferred. NamedTypeSymbol constructorType = null; if (arity == 0) // Member arity { NamedTypeSymbol containerType = containerOpt as NamedTypeSymbol; if ((object)containerType != null) { // Case 1: If the name is qualified by a type with the same name, then we want a // constructor (unless the type is generic, the cref is on/in the type (but not // on/in a nested type), and there were no parens after the member name). if (containerType.Name == memberName && (hasParameterList || containerType.Arity == 0 || this.ContainingType != containerType.OriginalDefinition)) { constructorType = containerType; } } else if ((object)containerOpt == null && hasParameterList) { // Case 2: If the name is not qualified by anything, but we're in the scope // of a type with the same name (regardless of arity), then we want a constructor, // as long as there were parens after the member name. NamedTypeSymbol binderContainingType = this.ContainingType; if ((object)binderContainingType != null && memberName == binderContainingType.Name) { constructorType = binderContainingType; } } } if ((object)constructorType != null) { ImmutableArray<MethodSymbol> instanceConstructors = constructorType.InstanceConstructors; int numInstanceConstructors = instanceConstructors.Length; if (numInstanceConstructors == 0) { return ImmutableArray<Symbol>.Empty; } builder = ArrayBuilder<Symbol>.GetInstance(numInstanceConstructors); builder.AddRange(instanceConstructors); } else { return ImmutableArray<Symbol>.Empty; } } } Debug.Assert(builder != null); // Since we resolve ambiguities by just picking the first symbol we encounter, // the order of the symbols matters for repeatability. if (builder.Count > 1) { builder.Sort(ConsistentSymbolOrder.Instance); } return builder.ToImmutableAndFree(); }
public NamespaceOrTypeAndUsingDirective(NamespaceOrTypeSymbol namespaceOrType, UsingDirectiveSyntax usingDirective) { this.NamespaceOrType = namespaceOrType; this.UsingDirective = usingDirective; }
private ImmutableArray<Symbol> BindMemberCref(MemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics) { if ((object)containerOpt != null && containerOpt.Kind == SymbolKind.TypeParameter) { // As in normal lookup (see CreateErrorIfLookupOnTypeParameter), you can't dot into a type parameter // (though you can dot into an expression of type parameter type). CrefSyntax crefSyntax = GetRootCrefSyntax(syntax); var noTrivia = syntax.WithLeadingTrivia(null).WithTrailingTrivia(null); diagnostics.Add(ErrorCode.WRN_BadXMLRef, crefSyntax.Location, noTrivia.ToFullString()); ambiguityWinner = null; return ImmutableArray<Symbol>.Empty; } ImmutableArray<Symbol> result; switch (syntax.Kind) { case SyntaxKind.NameMemberCref: result = BindNameMemberCref((NameMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics); break; case SyntaxKind.IndexerMemberCref: result = BindIndexerMemberCref((IndexerMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics); break; case SyntaxKind.OperatorMemberCref: result = BindOperatorMemberCref((OperatorMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics); break; case SyntaxKind.ConversionOperatorMemberCref: result = BindConversionOperatorMemberCref((ConversionOperatorMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics); break; default: Debug.Assert(false, "Unexpected member cref kind " + syntax.Kind); ambiguityWinner = null; result = ImmutableArray<Symbol>.Empty; break; } if (!result.Any()) { CrefSyntax crefSyntax = GetRootCrefSyntax(syntax); var noTrivia = syntax.WithLeadingTrivia(null).WithTrailingTrivia(null); diagnostics.Add(ErrorCode.WRN_BadXMLRef, crefSyntax.Location, noTrivia.ToFullString()); } return result; }
internal static AliasSymbol CreateCustomDebugInfoAlias(NamespaceOrTypeSymbol targetSymbol, SyntaxToken aliasToken, InContainerBinder binder) { return(new AliasSymbol(binder, targetSymbol, aliasToken, ImmutableArray.Create(aliasToken.GetLocation()))); }
internal static AliasSymbol CreateCustomDebugInfoAlias(NamespaceOrTypeSymbol targetSymbol, SyntaxToken aliasToken, Symbol containingSymbol, bool isExtern) { return(new AliasSymbolFromResolvedTarget(targetSymbol, aliasToken.ValueText, containingSymbol, ImmutableArray.Create(aliasToken.GetLocation()), isExtern)); }