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