예제 #1
0
        private static IReadOnlyCollection <LinterFailure> ComputeLinterFailures(Workspace workspace, BuildXL.FrontEnd.Script.Tracing.Logger logger, PathTable pathTable)
        {
            // Unfortunately all linter rules log using the logger directly, so we need to retrieve the event, map it to a typescript diagnostic and add it to the
            // failure list
            var failures = new List <LinterFailure>();

            foreach (var diagnostic in logger.CapturedDiagnostics)
            {
                var path = diagnostic.Location != null?AbsolutePath.Create(pathTable, diagnostic.Location.Value.File) : AbsolutePath.Invalid;

                if (path.IsValid && workspace.TryGetSourceFile(path, out var sourceFile))
                {
                    INode node;
                    DScriptNodeUtilities.TryGetNodeAtPosition(sourceFile, diagnostic.Location.Value.GetAbsolutePosition(sourceFile), out node);
                    Contract.Assert(node != null);

                    var startPosition = Scanner.SkipOverTrivia(sourceFile, node.Pos);

                    var typeScriptDiagnostic = new Diagnostic(
                        sourceFile,
                        startPosition,
                        node.GetWidth(),
                        diagnostic.FullMessage,
                        DiagnosticCategory.Error,
                        diagnostic.ErrorCode);

                    var descriptor = workspace.GetModuleBySpecFileName(path).Descriptor;
                    failures.Add(new LinterFailure(descriptor, sourceFile, typeScriptDiagnostic));
                }
            }

            return(failures);
        }
예제 #2
0
        /// <nodoc />
        public static bool IsInCommentHelper(ISourceFile sourceFile, int position, Func <ICommentRange, bool> predicate = null)
        {
            if (!DScriptNodeUtilities.TryGetNodeAtPosition(sourceFile, position, out var token) || position > GetTokenPosOfNode(token, sourceFile))
            {
                return(false);
            }

            var commentRanges = Scanner.GetLeadingCommentRanges(sourceFile.Text, token.Pos);

            // The end marker of a single-line comment does not include the newline character.
            // In the following case, we are inside a comment (^ denotes the cursor position):
            //
            //    // asdf   ^\n
            //
            // But for multi-line comments, we don't want to be inside the comment in the following case:
            //
            //    /* asdf */^
            //
            // Internally, we represent the end of the comment at the newline and closing '/', respectively.
            foreach (var c in commentRanges)
            {
                if (c.Pos < position &&
                    (c.Kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.End : position < c.End) &&
                    (predicate == null || predicate(c)))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #3
0
        /// <nodoc />
        public static bool IsInString(ISourceFile sourceFile, int position)
        {
            INode token;

            return(DScriptNodeUtilities.TryGetNodeAtPosition(sourceFile, position, out token) &&
                   (token?.Kind == SyntaxKind.StringLiteral || token?.Kind == SyntaxKind.StringLiteralType) &&
                   position > GetTokenPosOfNode(token, token.GetSourceFile()));
        }
예제 #4
0
        /// <summary>
        /// Tries to resolve a node by the given <paramref name="documentPosition"/>.
        /// </summary>
        /// <remarks>
        /// The function emits a log entry if the given source file is missing from the <see cref="Workspace"/>.
        /// </remarks>
        protected bool TryFindNode(TextDocumentPositionParams documentPosition, out INode currentNode)
        {
            Contract.Requires(documentPosition.Position != null);

            var lineAndColumn = documentPosition.Position.ToLineAndColumn();

            if (!TryFindSourceFile(documentPosition.TextDocument.Uri, out var sourceFile))
            {
                // The message that the file is missing was logged.
                currentNode = null;
                return(false);
            }

            return(DScriptNodeUtilities.TryGetNodeAtPosition(sourceFile, lineAndColumn, out currentNode));
        }
예제 #5
0
        private static bool TryCreateImportStatementCommand(
            Workspace workspace,
            PathTable pathTable,
            CodeActionParams actionParams,
            out dynamic[] commandArguments)
        {
            commandArguments = default(dynamic[]);

            var typeChecker = workspace.GetSemanticModel().TypeChecker;

            if (!actionParams.TextDocument.Uri.TryGetSourceFile(workspace, pathTable, out var sourceUri))
            {
                return(false);
            }

            Contract.Assert(actionParams.Range?.Start != null);
            if (!DScriptNodeUtilities.TryGetNodeAtPosition(sourceUri, actionParams.Range.Start.ToLineAndColumn(), out var node))
            {
                return(false);
            }

            var nodeFlags = NodeUtilities.GetCombinedNodeFlags(node);

            if ((nodeFlags & NodeFlags.ScriptPublic) == NodeFlags.None)
            {
                return(false);
            }

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

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

            var symbolFullName = typeChecker.GetFullyQualifiedName(symbol);

            // The import statement can only contain a single identifier, so if the symbol's full name
            // is Namespace.Subnamespace.value, we care about just 'Namespace'
            var identifier = GetFirstIdentifier(symbolFullName);

            var module = workspace.TryGetModuleBySpecFileName(sourceUri.GetAbsolutePath(pathTable));

            if (module == null)
            {
                return(false);
            }

            var importString = string.Format(
                CultureInfo.InvariantCulture,
                "import {{{0}}} from \"{1}\";",
                identifier,
                module.Definition.Descriptor.Name);

            var bannerString = FormattableStringEx.I($"Import string for '{symbolFullName}' placed on clipboard");

            commandArguments = new dynamic[]
            {
                importString,
                bannerString,
            };

            return(true);
        }