示例#1
0
        /// <nodoc />
        public Possible <IReadOnlyList <SymbolLocation> > GetDefinitionAtPosition(INode node)
        {
            // TODO: consider special hint/message if the current node is a template expression with interpolated expressions.
            if (node.Kind == SyntaxKind.NoSubstitutionTemplateLiteral && node.Parent.Kind == SyntaxKind.TaggedTemplateExpression &&
                node.Parent.Cast <ITaggedTemplateExpression>().IsWellKnownTemplateExpression(out var name))
            {
                return(DefinitionForTemplateExpression(node, name));
            }

            var result = GetDefinitionFromVariableDeclarationList(node);

            if (result.Succeeded)
            {
                return(result);
            }

            if (Utilities.IsJumpStatementTarget(node))
            {
                var labelName = node.Cast <IIdentifier>().Text;
                var label     = Utilities.GetTargetLabel(node.Parent, labelName);

                // TODO: saqadri - Port
                // return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined;
                return(Success(new[]
                {
                    GetLocationFromNode(label, symbol: null),
                }));
            }

            var symbol = TypeChecker.GetSymbolAtLocation(node) ?? node.Symbol ?? node.ResolvedSymbol;

            // Could not find a symbol e.g. node is string or number keyword,
            // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
            if (symbol == null)
            {
                // return null;
                return(SilentError());
            }

            // If this is an alias, and the request came at the declaration location
            // get the aliased symbol instead. This allows for goto def on an import e.g.
            //   import {A, B} from "mod";
            // to jump to the implementation directly.
            if ((symbol.Flags & SymbolFlags.Alias) != SymbolFlags.None)
            {
                var declaration = symbol.Declarations.FirstOrDefault();

                // Go to the original declaration for cases:
                //
                //   (1) when the aliased symbol was declared in the location(parent).
                //   (2) when the aliased symbol is originating from a named import.
                if (node.Kind == SyntaxKind.Identifier &&
                    declaration != null &&
                    (node.Parent.ResolveUnionType() == declaration.ResolveUnionType() ||
                     (declaration.Kind == SyntaxKind.ImportSpecifier && declaration?.Parent.Kind == SyntaxKind.NamedImports)))
                {
                    symbol = TypeChecker.GetAliasedSymbol(symbol);
                }
                else if (node.Kind == SyntaxKind.Identifier && declaration?.Kind == SyntaxKind.NamespaceImport && declaration.Name != null)
                {
                    return(new[] { GetLocationFromNode(declaration.Name, symbol) });
                }
            }

            // Because name in short-hand property assignment has two different meanings: property name and property value,
            // using go-to-definition at such position should go to the variable declaration of the property value rather than
            // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition
            // is performed at the location of property access, we would like to go to definition of the property in the short-hand
            // assignment. This case and others are handled by the following code.
            if (node.Parent.Kind == SyntaxKind.ShorthandPropertyAssignment)
            {
                var shorthandSymbol = TypeChecker.GetShorthandAssignmentValueSymbol(symbol.ValueDeclaration);
                if (shorthandSymbol == null)
                {
                    return(Success(new SymbolLocation[] { }));
                }

                var shorthandDeclaratons = shorthandSymbol.GetDeclarations();

                // var shorthandSymbolKind = GetSymbolKind(shorthandSymbol, node);
                // var shorthandSymbolName = TypeChecker.SymbolToString(shorthandSymbol);
                // var shorthandContainerName = TypeChecker.SymbolToString(shorthandSymbol.Parent, node);
                return(Success(shorthandDeclaratons.Select(
                                   declaration => GetLocationFromNode(declaration, shorthandSymbol)).ToArray()));
            }

            if (Utilities.IsNameOfPropertyAssignment(node))
            {
                return(GetDefinitionForPropertyAssignment(node));
            }

            return(GetDefinitionFromSymbol(symbol, node));
        }
示例#2
0
 /// <summary>
 /// Finds the actual symbol for an aliased symbol.
 /// </summary>
 /// <remarks>
 /// If a symbol is a type alias (for example Foo in this statement):
 /// import {Foo} from "Module.Foo";
 /// this function will return the symbol from inside the "Module.Foo" module.
 /// Ported from TypeScript implementation.
 /// </remarks>
 public static ISymbol SkipAlias(ISymbol symbol, ITypeChecker typeChecker)
 {
     return((symbol.Flags & SymbolFlags.Alias) != SymbolFlags.None ? typeChecker.GetAliasedSymbol(symbol) : symbol);
 }