public static void Create(ISymbol symbol, SymbolKeyWriter visitor) { var containingSymbol = symbol.ContainingSymbol; while (!containingSymbol.DeclaringSyntaxReferences.Any()) { containingSymbol = containingSymbol.ContainingSymbol; } var kind = symbol.Kind; var localName = symbol.Name; Contract.ThrowIfNull( visitor.Compilation, message: $"visitor cannot be created with a null compilation and visit a {nameof(BodyLevelSymbolKey)}."); var ordinal = 0; foreach (var possibleSymbol in EnumerateSymbols(visitor.Compilation, containingSymbol, kind, localName, visitor.CancellationToken)) { if (possibleSymbol.Item1.Equals(symbol)) { ordinal = possibleSymbol.Item2; break; } } visitor.WriteString(localName); visitor.WriteSymbolKey(containingSymbol); visitor.WriteInteger(ordinal); visitor.WriteInteger((int)kind); }
// The containing symbol can be one of many things. // 1) Null when this is the global namespace for a compilation. // 2) The SymbolId for an assembly symbol if this is the global namespace for an // assembly. // 3) The SymbolId for a module symbol if this is the global namespace for a module. // 4) The SymbolId for the containing namespace symbol if this is not a global // namespace. public static void Create(INamespaceSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); if (symbol.ContainingNamespace != null) { visitor.WriteBoolean(false); visitor.WriteSymbolKey(symbol.ContainingNamespace); } else { // A global namespace can either belong to a module or to a compilation. Debug.Assert(symbol.IsGlobalNamespace); switch (symbol.NamespaceKind) { case NamespaceKind.Module: visitor.WriteBoolean(false); visitor.WriteSymbolKey(symbol.ContainingModule); break; case NamespaceKind.Assembly: visitor.WriteBoolean(false); visitor.WriteSymbolKey(symbol.ContainingAssembly); break; case NamespaceKind.Compilation: visitor.WriteBoolean(true); visitor.WriteSymbolKey(null); break; default: throw new NotImplementedException(); } } }
public static void Create(IMethodSymbol symbol, SymbolKeyWriter visitor) { Debug.Assert(symbol.Equals(symbol.ConstructedFrom)); visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingSymbol); visitor.WriteInteger(symbol.Arity); visitor.WriteBoolean(symbol.PartialDefinitionPart != null); visitor.WriteRefKindArray(symbol.Parameters); // Mark that we're writing out the signature of a method. This way if we hit a // method type parameter in our parameter-list or return type, we won't recurse // into it, but will instead only write out the type parameter ordinal. This // happens with cases like Foo<T>(T t); Debug.Assert(!visitor.WritingSignature); visitor.WritingSignature = true; visitor.WriteParameterTypesArray(symbol.OriginalDefinition.Parameters); if (symbol.MethodKind == MethodKind.Conversion) { visitor.WriteSymbolKey(symbol.ReturnType); } else { visitor.WriteSymbolKey(null); } // Done writing the signature. Go back to normal mode. Debug.Assert(visitor.WritingSignature); visitor.WritingSignature = false; }
public static void Create(IPropertySymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingSymbol); visitor.WriteBoolean(symbol.IsIndexer); visitor.WriteRefKindArray(symbol.Parameters); visitor.WriteParameterTypesArray(symbol.OriginalDefinition.Parameters); }
public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.Name); visitor.WriteSymbolKey(symbol.ContainingSymbol as INamespaceOrTypeSymbol); visitor.WriteInteger(symbol.Arity); if (!symbol.Equals(symbol.ConstructedFrom)) { visitor.WriteSymbolKeyArray(symbol.TypeArguments); } else { visitor.WriteSymbolKeyArray(default(ImmutableArray<ITypeSymbol>)); } }
public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.Name); visitor.WriteSymbolKey(symbol.ContainingSymbol as INamespaceOrTypeSymbol); visitor.WriteInteger(symbol.Arity); if (!symbol.Equals(symbol.ConstructedFrom)) { visitor.WriteSymbolKeyArray(symbol.TypeArguments); } else { visitor.WriteSymbolKeyArray(default(ImmutableArray <ITypeSymbol>)); } }
public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingSymbol); visitor.WriteInteger(symbol.Arity); visitor.WriteBoolean(symbol.IsUnboundGenericType); if (!symbol.Equals(symbol.ConstructedFrom) && !symbol.IsUnboundGenericType) { visitor.WriteSymbolKeyArray(symbol.TypeArguments); } else { visitor.WriteSymbolKeyArray(ImmutableArray <ITypeSymbol> .Empty); } }
public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingSymbol); visitor.WriteInteger(symbol.Arity); visitor.WriteInteger((int)symbol.TypeKind); visitor.WriteBoolean(symbol.IsUnboundGenericType); if (!symbol.Equals(symbol.ConstructedFrom) && !symbol.IsUnboundGenericType) { visitor.WriteSymbolKeyArray(symbol.TypeArguments); } else { visitor.WriteSymbolKeyArray(default(ImmutableArray<ITypeSymbol>)); } }
public static void Create(ISymbol symbol, SymbolKeyWriter visitor) { var containingSymbol = symbol.ContainingSymbol; while (containingSymbol.DeclaringSyntaxReferences.IsDefaultOrEmpty) { containingSymbol = containingSymbol.ContainingSymbol; } var compilation = ((ISourceAssemblySymbol)symbol.ContainingAssembly).Compilation; var kind = symbol.Kind; var localName = symbol.Name; // Use two mechanisms to try to find the symbol across compilations. First, we use a whitespace // insensitive system where we keep track of the list of all locals in the container and we just store // our index in it. // // The above works for cases where the symbol has a real declaration and can be found by walking the // declarations of the container. However, not all symbols can be found that way. For example, error // locals in VB can't be found using GetDeclaredSymbol. For those, we store the actual local span and // use GetSymbolInfo to find it. var ordinal = GetOrdinal(); visitor.WriteString(localName); visitor.WriteSymbolKey(containingSymbol); visitor.WriteInteger(ordinal); visitor.WriteLocation(symbol.Locations[0]); visitor.WriteInteger((int)kind); return; int GetOrdinal() { foreach (var possibleSymbol in EnumerateSymbols(compilation, containingSymbol, kind, localName, visitor.CancellationToken)) { if (possibleSymbol.symbol.Equals(symbol)) { return(possibleSymbol.ordinal); } } return(int.MaxValue); } }
public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.Name); switch (symbol.ContainingSymbol) { case INamedTypeSymbol parentType: visitor.WriteInteger(0); visitor.WriteSymbolKey(parentType); break; case INamespaceSymbol parentNamespace: visitor.WriteInteger(1); visitor.WriteStringArray( GetContainingNamespaceNamesInReverse(parentNamespace) ); break; default: visitor.WriteInteger(2); break; } var isConstructed = !symbol.Equals(symbol.ConstructedFrom); visitor.WriteInteger(symbol.Arity); visitor.WriteBoolean(isConstructed); if (isConstructed) { visitor.WriteSymbolKeyArray(symbol.TypeArguments); } else { visitor.WriteSymbolKeyArray(ImmutableArray <ITypeSymbol> .Empty); } }
public static void Create(IAssemblySymbol symbol, SymbolKeyWriter visitor) { // If the format of this ever changed, then it's necessary to fixup the // SymbolKeyComparer.RemoveAssemblyKeys function. visitor.WriteString(symbol.Identity.Name); }
public static void Create(IParameterSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingSymbol); }
public static void Create(IEventSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingType); }
public sealed override void Create(IAliasSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.Name); visitor.WriteSymbolKey(symbol.Target); visitor.WriteString(symbol.DeclaringSyntaxReferences.FirstOrDefault()?.SyntaxTree.FilePath ?? ""); }
public static void Create(ISymbol symbol, SymbolKeyWriter visitor) { // Store the body level symbol in two forms. The first, a highly precise form that should find explicit // symbols for the case of resolving a symbol key back in the *same* solution snapshot it was created // from. The second, in a more query-oriented form that can allow the symbol to be found in some cases // even if the solution changed (which is a supported use case for SymbolKey). // // The first way just stores the location of the symbol, which we can then validate during resolution // maps back to the same symbol kind/name. // // The second determines the sequence of symbols of the same kind and same name in the file and keeps // track of our index in that sequence. That way, if trivial edits happen, or symbols with different // names/types are added/removed, we can still find what is likely to be this symbol after the edit. var kind = symbol.Kind; var localName = symbol.Name; visitor.WriteString(localName); visitor.WriteInteger((int)kind); // write out the locations for precision Contract.ThrowIfTrue( symbol.DeclaringSyntaxReferences.IsEmpty && symbol.Locations.IsEmpty ); var locations = GetBodyLevelSourceLocations(symbol, visitor.CancellationToken); Contract.ThrowIfFalse(locations.All(loc => loc.IsInSource)); visitor.WriteLocationArray(locations.Distinct()); // and the ordinal for resilience visitor.WriteInteger(GetOrdinal()); return; int GetOrdinal() { var syntaxTree = locations[0].SourceTree; var compilation = ((ISourceAssemblySymbol)symbol.ContainingAssembly).Compilation; // Ensure that the tree we're looking at is actually in this compilation. It may not be in the // compilation in the case of work done with a speculative model. if (TryGetSemanticModel(compilation, syntaxTree, out var semanticModel)) { foreach ( var possibleSymbol in EnumerateSymbols( semanticModel, kind, localName, visitor.CancellationToken ) ) { if (possibleSymbol.symbol.Equals(symbol)) { return(possibleSymbol.ordinal); } } } return(int.MaxValue); } }
public static void Create(IAliasSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.Name); visitor.WriteSymbolKey(symbol.Target); visitor.WriteString(symbol.DeclaringSyntaxReferences.FirstOrDefault()?.SyntaxTree.FilePath ?? ""); }
public sealed override void Create(IFieldSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingType); }