Exemple #1
0
        private Result <ArrayOrObject <Location, Location>, ResponseError> GetDefinitionForPropertyAssignment(INode node)
        {
            var symbol = DScriptUtilities.GetPropertySymbolsFromContextualType(node, TypeChecker).FirstOrDefault();

            if (symbol == null)
            {
                return(SilentError());
            }

            return(GetDefinitionFromSymbol(symbol, node));
        }
Exemple #2
0
        private Result <ArrayOrObject <Location, Location>, ResponseError> GetDefinitionFromSymbol([NotNull] ISymbol symbol, INode node)
        {
            var result          = new List <Location>();
            var declarations    = symbol.GetDeclarations();
            var symbolName      = TypeChecker.SymbolToString(symbol);
            var symbolKind      = DScriptUtilities.GetSymbolKind(symbol, node);
            var containerSymbol = symbol.Parent;
            var containerName   = containerSymbol != null?TypeChecker.SymbolToString(containerSymbol, node) : string.Empty;

            if (!TryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
                !TryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result))
            {
                // Just add all the declarations
                foreach (var declaration in declarations)
                {
                    result.Add(GetLocationFromNode(declaration));
                }
            }

            return(Success(result.ToArray()));
        }
Exemple #3
0
        private static bool TryAddCallSignature(
            ISymbol symbol,
            INode location,
            string symbolKind,
            string symbolName,
            string containerName,
            List <Location> result)
        {
            if (DScriptUtilities.IsCallExpressionTarget(location) ||
                DScriptUtilities.IsNewExpressionTarget(location) ||
                DScriptUtilities.IsNameOfFunctionDeclaration(location))
            {
                return(TryAddSignature(
                           symbol.Declarations,
                           /*selectConstructors*/ false,
                           symbolKind,
                           symbolName,
                           containerName,
                           result));
            }

            return(false);
        }
Exemple #4
0
        private static bool TryAddConstructSignature(
            ISymbol symbol,
            INode location,
            string symbolKind,
            string symbolName,
            string containerName,
            List <Location> result)
        {
            // Applicable only if we are in a new expression, or we are on a constructor declaration
            // and in either case the symbol has a construct signature definition, i.e. class
            if (DScriptUtilities.IsNewExpressionTarget(location) || location.Kind == SyntaxKind.ConstructorKeyword)
            {
                if ((symbol.Flags & SymbolFlags.Class) != SymbolFlags.None)
                {
                    // Find the first class-like declaration and try to get the construct signature.
                    foreach (var declaration in symbol.GetDeclarations())
                    {
                        var classLikeDeclaration = NodeUtilities.IsClassLike(declaration);
                        if (classLikeDeclaration != null)
                        {
                            return(TryAddSignature(
                                       classLikeDeclaration.Members.Elements,
                                       /*selectConstructors*/ true,
                                       symbolKind,
                                       symbolName,
                                       containerName,
                                       result));
                        }
                    }

                    Debug.Fail("Expected declaration to have at least one class-like declaration");
                }
            }

            return(false);
        }
Exemple #5
0
        /// <nodoc />
        public Result <ArrayOrObject <Location, Location>, ResponseError> GetDefinitionAtPosition(TextDocumentPositionParams @params, CancellationToken token)
        {
            // TODO: support cancellation
            if (!TryFindNode(@params, out var node))
            {
                return(SilentError());
            }

            // 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 != null)
            {
                return(result);
            }

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

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

            // TODO: saqadri - port
            // Triple slash reference comments
            // const comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined);
            // if (comment)
            // {
            //    const referenceFile = tryResolveScriptReference(program, sourceFile, comment);
            //    if (referenceFile)
            //    {
            //        return [{
            //            fileName: referenceFile.fileName,
            //            textSpan: createTextSpanFromBounds(0, 0),
            //            kind: ScriptElementKind.scriptElement,
            //            name: comment.fileName,
            //            containerName: undefined,
            //            containerKind: undefined
            //        }];
            //    }
            //    return undefined;
            // }
            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);
                }
            }

            // 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 Location[] { }));
                }

                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)).ToArray()));
            }

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

            return(GetDefinitionFromSymbol(symbol, node));
        }