Exemple #1
0
 public Task <Hover> Hover(TextDocumentIdentifier textDocument, Position position, CancellationToken ct)
 {
     using (new DebugMeasureTime("textDocument/hover")) {
         var doc = Documents.GetDocument(textDocument.Uri);
         return(doc != null?doc.GetHoverAsync(position, ct) : Task.FromResult((Hover)null));
     }
 }
Exemple #2
0
 public SymbolInformation[] documentSymbol(TextDocumentIdentifier textDocument, FormattingOptions options)
 {
     using (new DebugMeasureTime("textDocument/documentSymbol")) {
         var doc = Documents.GetDocument(textDocument.Uri);
         return(doc != null?doc.GetSymbols(textDocument.Uri) : new SymbolInformation[0]);
     }
 }
        private async Task <int[]?> GetMatchingCSharpResponseAsync(
            TextDocumentIdentifier textDocumentIdentifier,
            long documentVersion,
            Range csharpRange,
            CancellationToken cancellationToken)
        {
            var parameter = new ProvideSemanticTokensRangeParams(textDocumentIdentifier, documentVersion, csharpRange);
            var request   = await _languageServer.SendRequestAsync(LanguageServerConstants.RazorProvideSemanticTokensRangeEndpoint, parameter);

            var csharpResponse = await request.Returning <ProvideSemanticTokensResponse>(cancellationToken);

            if (csharpResponse is null)
            {
                // C# isn't ready yet, don't make Razor wait for it. Once C# is ready they'll send a refresh notification.
                return(Array.Empty <int>());
            }
            else if (csharpResponse.HostDocumentSyncVersion != null && csharpResponse.HostDocumentSyncVersion != documentVersion)
            {
                // No C# response or C# is out of sync with us. Unrecoverable, return null to indicate no change.
                // Once C# syncs up they'll send a refresh notification.
                return(null);
            }

            var response = csharpResponse.Tokens ?? Array.Empty <int>();

            return(response);
        }
        /// <summary>
        /// To be called whenever a file is closed in the editor.
        /// Does nothing if the given file is listed as to be ignored.
        /// Otherwise the file content is reloaded from disk (in case changes in the editor are discarded without closing), and the diagnostics are updated.
        /// Invokes the given Action onError with a suitable message if the given file is not listed as being open in the editor.
        /// Throws an ArgumentException if the uri of the given text document identifier is null or not an absolute file uri.
        /// </summary>
        internal Task CloseFileAsync(TextDocumentIdentifier textDocument, Action <string, MessageType> onError = null)
        {
            if (!ValidFileUri(textDocument?.Uri))
            {
                throw new ArgumentException("invalid text document identifier");
            }
            _ = this.Projects.ManagerTaskAsync(textDocument.Uri, (manager, associatedWithProject) => // needs to be *first* (due to the modification of OpenFiles)
            {
                if (IgnoreFile(textDocument.Uri))
                {
                    return;
                }

                // Currently it is not possible to handle both the behavior of VS and VS Code for changes on disk in a manner that will never fail.
                // To mitigate the impact of failures we choose to ignore them silently.
                var removed = this.OpenFiles.TryRemove(textDocument.Uri, out FileContentManager __);
                #if DEBUG
                if (!removed)
                {
                    onError?.Invoke($"Attempting to close file '{textDocument.Uri.LocalPath}' that is not currently listed as open in the editor.", MessageType.Error);
                }
                #endif
                if (!associatedWithProject)
                {
                    _ = manager.TryRemoveSourceFileAsync(textDocument.Uri);
                }
                this.Publish(new PublishDiagnosticParams {
                    Uri = textDocument.Uri, Diagnostics = new Diagnostic[0]
                });
            });
            // When edits are made in a file, but those are discarded by closing the file and hitting "no, don't save",
            // no notification is sent for the now discarded changes;
            // hence we reload the file content from disk upon closing.
            return(this.Projects.SourceFileChangedOnDiskAsync(textDocument.Uri, GetOpenFile)); // NOTE: relies on that the manager task is indeed executed first!
        }
        public static async Task AssertHover(Server s, TextDocumentIdentifier document, SourceLocation position, string hoverText, IEnumerable <string> typeNames, SourceSpan?range = null, string expr = null)
        {
            var hover = await s.Hover(new TextDocumentPositionParams {
                textDocument = document,
                position     = position,
                _expr        = expr
            });

            if (hoverText.EndsWith("*"))
            {
                // Check prefix first, but then show usual message for mismatched value
                if (!hover.contents.value.StartsWith(hoverText.Remove(hoverText.Length - 1)))
                {
                    Assert.AreEqual(hoverText, hover.contents.value);
                }
            }
            else
            {
                Assert.AreEqual(hoverText, hover.contents.value);
            }
            if (typeNames != null)
            {
                AssertUtil.ContainsExactly(hover._typeNames, typeNames.ToArray());
            }
            if (range.HasValue)
            {
                Assert.AreEqual(range.Value, (SourceSpan)hover.range);
            }
        }
Exemple #6
0
        public async Task RazorSemanticTokensRangeScrollingAsync()
        {
            var textDocumentIdentifier = new TextDocumentIdentifier(DocumentUri);
            var cancellationToken      = CancellationToken.None;
            var documentVersion        = 1;

            await UpdateDocumentAsync(documentVersion, DocumentSnapshot).ConfigureAwait(false);

            var documentLineCount = Range.End.Line;

            var lineCount = 0;

            while (lineCount != documentLineCount)
            {
                var   newLineCount = Math.Min(lineCount + WindowSize, documentLineCount);
                var   range = new Range(lineCount, 0, newLineCount, 0);
                await RazorSemanticTokenService !.GetSemanticTokensAsync(
                    textDocumentIdentifier,
                    range,
                    DocumentSnapshot,
                    documentVersion,
                    cancellationToken);

                lineCount = newLineCount;
            }
        }
Exemple #7
0
 public void HideDiagnostics(TextDocumentIdentifier documentId)
 {
     languageServer.TextDocument.PublishDiagnostics(new PublishDiagnosticsParams {
         Uri         = documentId.Uri,
         Diagnostics = new Container <Diagnostic>()
     });
 }
Exemple #8
0
        public static Document?GetDocument(this Solution solution, TextDocumentIdentifier documentIdentifier, string?clientName = null)
        {
            var documents = solution.GetDocuments(documentIdentifier.Uri, clientName);

            if (documents.Length == 0)
            {
                return(null);
            }

            if (documents.Length > 1)
            {
                // We have more than one document; try to find the one that matches the right context
                if (documentIdentifier is VSTextDocumentIdentifier vsDocumentIdentifier)
                {
                    if (vsDocumentIdentifier.ProjectContext != null)
                    {
                        var projectId        = ProtocolConversions.ProjectContextToProjectId(vsDocumentIdentifier.ProjectContext);
                        var matchingDocument = documents.FirstOrDefault(d => d.Project.Id == projectId);

                        if (matchingDocument != null)
                        {
                            return(matchingDocument);
                        }
                    }
                }
            }

            // We either have only one document or have multiple, but none of them  matched our context. In the
            // latter case, we'll just return the first one arbitrarily since this might just be some temporary mis-sync
            // of client and server state.
            return(documents[0]);
        }
 public TSqlFormatterServiceTests()
 {
     textDocument = new TextDocumentIdentifier
     {
         Uri = "script file"
     };
     docFormatParams = new DocumentFormattingParams()
     {
         TextDocument = textDocument,
         Options      = new FormattingOptions()
         {
             InsertSpaces = true, TabSize = 4
         }
     };
     rangeFormatParams = new DocumentRangeFormattingParams()
     {
         TextDocument = textDocument,
         Options      = new FormattingOptions()
         {
             InsertSpaces = true, TabSize = 4
         },
         Range = new ServiceLayer.Workspace.Contracts.Range()
         {
             // From first "(" to last ")"
             Start = new Position {
                 Line = 0, Character = 16
             },
             End = new Position {
                 Line = 0, Character = 56
             }
         }
     };
 }
Exemple #10
0
        public void DidChange(TextDocumentIdentifier textDocument,
                              ICollection <TextDocumentContentChangeEvent> contentChanges)
        {
            Program.logWriter.WriteLine("Documento changed");
            if (Session.Documents[textDocument.Uri] == null)
            {
                Program.logWriter.WriteLine("Unknown doc");
                var item = new TextDocumentItem();
                item.Uri = textDocument.Uri;
                var doc     = new SessionDocument(item);
                var session = Session;
                doc.DocumentChanged += async(sender, args) =>
                {
                    Program.logWriter.WriteLine("Document changed");
                    // Lint the document when it's changed.
                    var doc1  = ((SessionDocument)sender).Document;
                    var diag1 = session.DiagnosticProvider.LintDocument(doc1, session.Settings.MaxNumberOfProblems);
                    if (session.Documents.ContainsKey(doc1.Uri))
                    {
                        // In case the document has been closed when we were linting…
                        await session.Client.Document.PublishDiagnostics(doc1.Uri, diag1);
                    }
                };
                Session.Documents.TryAdd(textDocument.Uri, doc);
            }
            Program.logWriter.WriteLine("A");

            Session.Documents[textDocument.Uri].NotifyChanges(contentChanges);
            Program.logWriter.WriteLine("B");
        }
Exemple #11
0
#pragma warning restore 0067

        private async Task <VsProjectAnalyzer> FindAnalyzerAsync(TextDocumentIdentifier document)
        {
            if (document?.Uri == null)
            {
                return(null);
            }

            if (!_analyzerCache.TryGetValue(document.Uri, out var analyzer))
            {
                var filePath = document.Uri.LocalPath;
                if (string.IsNullOrEmpty(filePath))
                {
                    return(null);
                }

                if (_uiThread != null)
                {
                    // TODO: Use URI for more accurate lookup
                    analyzer = await _uiThread.InvokeTask(async() =>
                                                          (await _serviceProvider.FindAllAnalyzersForFile(filePath)).FirstOrDefault() as VsProjectAnalyzer
                                                          );
                }

                analyzer = _analyzerCache.GetOrAdd(document.Uri, analyzer);
            }

            return(analyzer);
        }
        /// <summary>
        /// Used to reload the file content when a file is saved.
        /// Does nothing if the given file is listed as to be ignored.
        /// Expects to get the entire content of the file at the time of saving as argument.
        /// Throws an ArgumentException if the uri of the given text document identifier is null or not an absolute file uri.
        /// Throws an ArgumentNullException if the given content is null.
        /// </summary>
        internal Task SaveFileAsync(TextDocumentIdentifier textDocument, string fileContent)
        {
            if (!ValidFileUri(textDocument?.Uri))
            {
                throw new ArgumentException("invalid text document identifier");
            }
            if (fileContent == null)
            {
                throw new ArgumentNullException(nameof(fileContent));
            }
            return(this.Projects.ManagerTaskAsync(textDocument.Uri, (manager, __) =>
            {
                if (IgnoreFile(textDocument.Uri))
                {
                    return;
                }

                // Currently it is not possible to handle both the behavior of VS and VS Code for changes on disk in a manner that will never fail.
                // To mitigate the impact of failures we choose to ignore them silently and do our best to recover.
                if (!this.OpenFiles.TryGetValue(textDocument.Uri, out var file))
                {
                    file = CompilationUnitManager.InitializeFileManager(textDocument.Uri, fileContent, this.Publish, manager.LogException);
                    this.OpenFiles.TryAdd(textDocument.Uri, file);
                    _ = manager.AddOrUpdateSourceFileAsync(file);
                }
                else
                {
                    _ = manager.AddOrUpdateSourceFileAsync(file, fileContent);  // let's reload the file content on saving
                }
            }));
        }
Exemple #13
0
        public static T FindDocumentInProjectContext <T>(
            this ImmutableArray <T> documents,
            TextDocumentIdentifier documentIdentifier
            ) where T : TextDocument
        {
            if (documents.Length > 1)
            {
                // We have more than one document; try to find the one that matches the right context
                if (documentIdentifier is VSTextDocumentIdentifier vsDocumentIdentifier)
                {
                    if (vsDocumentIdentifier.ProjectContext != null)
                    {
                        var projectId = ProtocolConversions.ProjectContextToProjectId(
                            vsDocumentIdentifier.ProjectContext
                            );
                        var matchingDocument = documents.FirstOrDefault(
                            d => d.Project.Id == projectId
                            );

                        if (matchingDocument != null)
                        {
                            return(matchingDocument);
                        }
                    }
                }
            }

            // We either have only one document or have multiple, but none of them  matched our context. In the
            // latter case, we'll just return the first one arbitrarily since this might just be some temporary mis-sync
            // of client and server state.
            return(documents[0]);
        }
        public override async Task <SemanticTokens?> GetSemanticTokensAsync(
            TextDocumentIdentifier textDocumentIdentifier,
            Range range,
            CancellationToken cancellationToken)
        {
            var documentPath = textDocumentIdentifier.Uri.GetAbsoluteOrUNCPath();

            if (documentPath is null)
            {
                return(null);
            }

            var documentInfo = await TryGetDocumentInfoAsync(documentPath, cancellationToken).ConfigureAwait(false);

            if (documentInfo is null)
            {
                return(null);
            }

            var(documentSnapshot, documentVersion) = documentInfo.Value;

            var tokens = await GetSemanticTokensAsync(
                textDocumentIdentifier, range, documentSnapshot, documentVersion, cancellationToken);

            return(tokens);
        }
        public static async Task AssertReferences(Server s, TextDocumentIdentifier document, SourceLocation position, IEnumerable <string> contains, IEnumerable <string> excludes, string expr = null, bool returnDefinition = false)
        {
            var refs = (await s.FindReferences(new ReferencesParams {
                textDocument = document,
                position = position,
                _expr = expr,
                context = new ReferenceContext {
                    includeDeclaration = true,
                    _includeDefinitionRanges = returnDefinition,
                    _includeValues = true
                }
            }));

            IEnumerable <string> set;

            if (returnDefinition)
            {
                set = refs.Select(r => $"{r._kind ?? ReferenceKind.Reference};{r._definitionRange}");
            }
            else
            {
                set = refs.Select(r => $"{r._kind ?? ReferenceKind.Reference};{r.range}");
            }

            AssertUtil.CheckCollection(
                set,
                contains,
                excludes
                );
        }
        private Document GetDocument(TextDocumentIdentifier documentIdentifier)
        {
            var filePath = ResolveFilePath(documentIdentifier.Uri);

            return(_workspace.CurrentDocuments
                   .GetDocumentsWithFilePath(filePath)
                   .FirstOrDefault());
        }
 public DafnyDocument? CloseDocument(TextDocumentIdentifier documentId) {
   DafnyDocument? document;
   if(!_documents.TryRemove(documentId.Uri, out document)) {
     _logger.LogTrace("the document {} was already closed", documentId);
     return null;
   }
   return document;
 }
 public async Task DidClose(TextDocumentIdentifier textDocument)
 {
     Session.RemoveDocument(textDocument.Uri);
     if (textDocument.Uri.IsUntitled())
     {
         await Session.Client.Document.PublishDiagnostics(textDocument.Uri, new Diagnostic[0]);
     }
 }
        public CompletionList Completion(TextDocumentIdentifier textDocument, Position position, CompletionContext context)
        {
            var doc = Session.DocumentStates[textDocument.Uri];

            doc.AnalyzeAsync();
            return
                (Session.Project.GetCompletionList(doc, position, context)); //position, Session.PageInfoStore));
        }
 public async Task DidClose(TextDocumentIdentifier textDocument)
 {
     if (textDocument.Uri.IsUntitled())
     {
         await Client.Document.PublishDiagnostics(textDocument.Uri, new Diagnostic[0]);
     }
     Session.Documents.TryRemove(textDocument.Uri, out _);
 }
 public SignatureHelp SignatureHelp(TextDocumentIdentifier textDocument, Position position)
 {
     return(new SignatureHelp(new List <SignatureInformation>
     {
         new SignatureInformation("**Function1**", "Documentation1"),
         new SignatureInformation("**Function2** <strong>test</strong>", "Documentation2"),
     }));
 }
        // Internal and virtual for testing only
        internal virtual async Task <SemanticRange[]?> GetCSharpSemanticRangesAsync(
            RazorCodeDocument codeDocument,
            TextDocumentIdentifier textDocumentIdentifier,
            Range razorRange,
            long documentVersion,
            CancellationToken cancellationToken,
            string?previousResultId = null)
        {
            // We'll try to call into the mapping service to map to the projected range for us. If that doesn't work,
            // we'll try to find the minimal range ourselves.
            if (!_documentMappingService.TryMapToProjectedDocumentRange(codeDocument, razorRange, out var csharpRange) &&
                !TryGetMinimalCSharpRange(codeDocument, razorRange, out csharpRange))
            {
                // There's no C# in the range.
                return(Array.Empty <SemanticRange>());
            }

            var csharpResponse = await GetMatchingCSharpResponseAsync(textDocumentIdentifier, documentVersion, csharpRange, cancellationToken);

            // Indicates an issue with retrieving the C# response (e.g. no response or C# is out of sync with us).
            // Unrecoverable, return default to indicate no change. We've already queued up a refresh request in
            // `GetMatchingCSharpResponseAsync` that will cause us to retry in a bit.
            if (csharpResponse is null)
            {
                _logger.LogWarning($"Issue with retrieving C# response for Razor range: {razorRange}");
                return(null);
            }

            var razorRanges = new List <SemanticRange>();

            SemanticRange?previousSemanticRange = null;

            for (var i = 0; i < csharpResponse.Length; i += TokenSize)
            {
                var lineDelta      = csharpResponse[i];
                var charDelta      = csharpResponse[i + 1];
                var length         = csharpResponse[i + 2];
                var tokenType      = csharpResponse[i + 3];
                var tokenModifiers = csharpResponse[i + 4];

                var semanticRange = DataToSemanticRange(
                    lineDelta, charDelta, length, tokenType, tokenModifiers, previousSemanticRange);
                if (_documentMappingService.TryMapFromProjectedDocumentRange(codeDocument, semanticRange.Range, out var originalRange))
                {
                    var razorSemanticRange = new SemanticRange(semanticRange.Kind, originalRange, tokenModifiers);
                    if (razorRange is null || razorRange.OverlapsWith(razorSemanticRange.Range))
                    {
                        razorRanges.Add(razorSemanticRange);
                    }
                }

                previousSemanticRange = semanticRange;
            }

            var result = razorRanges.ToArray();

            return(result);
        }
Exemple #23
0
 public Task <SignatureHelp> SignatureHelp(TextDocumentIdentifier textDocument, Position position)
 {
     using (new DebugMeasureTime("textDocument/signatureHelp")) {
         return(MainThreadPriority.SendAsync(async() => {
             var doc = Documents.GetDocument(textDocument.Uri);
             return doc != null ? await doc.GetSignatureHelpAsync(position) : new SignatureHelp();
         }, ThreadPostPriority.Background));
     }
 }
Exemple #24
0
        public async Task <CompletionList> Completion(TextDocumentIdentifier textDocument, Position position,
                                                      CancellationToken ct)
        {
            var doc = Session.DocumentStates[textDocument.Uri];
            await doc.AnalyzeAsync(ct);

            return
                (Session.Project.GetCompletionList(doc, position)); //position, Session.PageInfoStore));
        }
 private async Task CloseDocumentAndHideDiagnosticsAsync(TextDocumentIdentifier documentId)
 {
     try {
         await documents.CloseDocumentAsync(documentId);
     } catch (Exception e) {
         logger.LogError(e, "error while closing the document");
     }
     diagnosticPublisher.HideDiagnostics(documentId);
 }
        public async Task <Hover> Hover(TextDocumentIdentifier textDocument, Position position, CancellationToken ct)
        {
            // Note that Hover is cancellable.
            await Task.Delay(1000, ct);

            return(new Hover {
                Contents = "Test _hover_ @" + position + "\n\n" + textDocument
            });
        }
        public async Task <CompletionList> Completion(TextDocumentIdentifier textDocument, Position position,
                                                      CancellationToken ct)
        {
            var doc = Session.DocumentStates[textDocument.Uri];
            await doc.AnalyzeAsync(ct);

            var(items, isIncomplete) = doc.LintedDocument.GetCompletionItems(position, Session.PageInfoStore);
            return(new CompletionList(items, isIncomplete));
        }
 public async Task<DafnyDocument?> SaveDocumentAsync(TextDocumentIdentifier documentId, CancellationToken cancellationToken) {
   if(VerifyOnSave) {
     return await VerifyDocumentAsync(documentId, cancellationToken);
   }
   if(_documents.TryGetValue(documentId.Uri, out var document)) {
     return document;
   }
   return null;
 }
Exemple #29
0
 public Task <CompletionList> completion(TextDocumentIdentifier textDocument, Position position)
 {
     using (new DebugMeasureTime("textDocument/completion")) {
         return(MainThreadPriority.SendAsync(() => {
             var doc = Documents.GetDocument(textDocument.Uri);
             return Task.FromResult(doc != null ? doc.GetCompletions(position) : new CompletionList());
         }, ThreadPostPriority.Background));
     }
 }
Exemple #30
0
 protected override VSInternalWorkspaceDiagnosticReport CreateReport(TextDocumentIdentifier identifier, VisualStudio.LanguageServer.Protocol.Diagnostic[]?diagnostics, string?resultId)
 => new VSInternalWorkspaceDiagnosticReport
 {
     TextDocument = identifier,
     Diagnostics  = diagnostics,
     ResultId     = resultId,
     // Mark these diagnostics as having come from us.  They will be superseded by any diagnostics for the
     // same file produced by the DocumentPullDiagnosticHandler.
     Identifier = WorkspaceDiagnosticIdentifier,
 };