示例#1
0
文件: App.cs 项目: smx-smx/ValaSharp
        private void ValidateTextDocument(TextDocumentItem document)
        {
            if (!ValaDocumentValidator.IsHandled(document))
            {
                return;
            }

            List <Diagnostic> diagnostics = new List <Diagnostic>();

            try {
                List <Diagnostic> messages = _validator.Validate(document.GetDocumentPath());
                diagnostics.AddRange(messages);
            } catch (ParseException ex) {
                if (ex.error_type != ParseError.SYNTAX)
                {
                    throw ex;
                }

                diagnostics.Add(new Diagnostic {
                    severity = DiagnosticSeverity.Error,
                    message  = ex.Message,
                    source   = "syntax"
                });
            } finally {
                Proxy.TextDocument.PublishDiagnostics(new PublishDiagnosticsParams {
                    uri         = document.uri,
                    diagnostics = diagnostics.ToArray()
                });
            }
        }
 private Task CloseDocumentAndWaitAsync(TextDocumentItem documentItem)
 {
     _client.DidCloseTextDocument(new DidCloseTextDocumentParams {
         TextDocument = documentItem
     });
     return(_client.WaitForNotificationCompletionAsync(documentItem.Uri, CancellationToken));
 }
示例#3
0
        // routines related to tracking the editor state

        /// <summary>
        /// To be called whenever a file is opened in the editor.
        /// Does nothing if the given file is listed as to be ignored.
        /// Otherwise publishes suitable diagnostics for it.
        /// Invokes the given Action showError with a suitable message if the given file cannot be loaded.
        /// Invokes the given Action logError with a suitable message if the given file cannot be associated with a compilation unit,
        /// or if the given file is already 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.
        /// Throws an ArgumentNullException if the given content is null.
        /// </summary>
        internal Task OpenFileAsync(TextDocumentItem textDocument,
                                    Action <string, MessageType> showError = null, Action <string, MessageType> logError = null)
        {
            if (!ValidFileUri(textDocument?.Uri))
            {
                throw new ArgumentException("invalid text document identifier");
            }
            if (textDocument.Text == null)
            {
                throw new ArgumentNullException(nameof(textDocument.Text));
            }
            _ = this.Projects.ManagerTaskAsync(textDocument.Uri, (manager, associatedWithProject) =>
            {
                if (IgnoreFile(textDocument.Uri))
                {
                    return;
                }
                var newManager = CompilationUnitManager.InitializeFileManager(textDocument.Uri, textDocument.Text, this.Publish, ex =>
                {
                    showError?.Invoke($"Failed to load file '{textDocument.Uri.LocalPath}'", MessageType.Error);
                    manager.LogException(ex);
                });

                // 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 just log them as info.
                var file = this.OpenFiles.GetOrAdd(textDocument.Uri, newManager);
                if (file != newManager) // this may be the case (depending on the editor) e.g. when opening a version control diff ...
                {
                    showError?.Invoke($"Version control and opening multiple versions of the same file in the editor are currently not supported. \n" +
                                      $"Intellisense has been disable for the file '{textDocument.Uri.LocalPath}'. An editor restart is required to enable intellisense again.", MessageType.Error);
                    #if DEBUG
                    if (showError == null)
                    {
                        logError?.Invoke("Attempting to open a file that is already open in the editor.", MessageType.Error);
                    }
                    #endif

                    this.IgnoreEditorUpdatesFor(textDocument.Uri);
                    this.OpenFiles.TryRemove(textDocument.Uri, out FileContentManager _);
                    if (!associatedWithProject)
                    {
                        _ = manager.TryRemoveSourceFileAsync(textDocument.Uri);
                    }
                    this.Publish(new PublishDiagnosticParams {
                        Uri = textDocument.Uri, Diagnostics = new Diagnostic[0]
                    });
                    return;
                }

                if (!associatedWithProject)
                {
                    logError?.Invoke(
                        $"The file {textDocument.Uri.LocalPath} is not associated with a compilation unit. Only syntactic diagnostics are generated."
                        , MessageType.Info);
                }
                _ = manager.AddOrUpdateSourceFileAsync(file);
            });
            // reloading from disk in case we encountered a file already open error above
            return(this.Projects.SourceFileChangedOnDiskAsync(textDocument.Uri, GetOpenFile)); // NOTE: relies on that the manager task is indeed executed first!
        }
 Task <Unit> Parse(TextDocumentItem document)
 {
     return(Task.Run(() => {
         Update(document);
         return Unit.Value;
     }));
 }
示例#5
0
        private void RecomputeWorkspace(TextDocumentItem document)
        {
            var path = document.Uri.ToAbsolutePath(m_pathTable);

            // Need to check if parsedModule is prelude or configuration module.
            // If the parsed module is the configuration module, then full reanalysis is required.
            ParsedModule     parsedModule = m_workspace.TryGetModuleBySpecFileName(path);
            ModuleDefinition moduleDefinition;

            if (parsedModule != null)
            {
                moduleDefinition = parsedModule.Definition;
            }
            else
            {
                // This should never happen: all the new files trigger full workspace reconstruction.
                return;
            }

            try
            {
                var updatedWorkspace = GetUpdatedWorkspace(parsedModule, moduleDefinition, path);
                m_workspace = updatedWorkspace;
            }
            catch (Exception e)
            {
                // TODO: saqadri - log exception, but for now just swallow
                Debug.Fail($"Workspace recomputation threw an exception: {e}");
            }
        }
示例#6
0
        public Task OpenFileAsync(TextDocumentItem textDocument,
                                  Action <string, MessageType> showError,
                                  Action <string, MessageType> logError)
        {
            if (!ValidFileUri(textDocument.Uri))
            {
                throw new ArgumentException("invalid text document identifier");
            }
            _ = this.ManagerTaskAsync(textDocument.Uri, (associatedWithProject) =>
            {
                if (this.IgnoreFile(textDocument.Uri))
                {
                    return;
                }
                var file = this.openFiles.GetOrAdd(textDocument.Uri, textDocument.Uri);
                if (!associatedWithProject)
                {
                    logError?.Invoke(
                        $"The file {textDocument.Uri.LocalPath} is not associated with a compilation unit. Only syntactic diagnostics are generated.",
                        MessageType.Info);
                }

                // _ = manager.AddOrUpdateSourceFileAsync(file);
            });

            return(Task.CompletedTask);//this.projects.SourceFileChangedOnDiskAsync(textDocument.Uri, this.GetOpenFile); // NOTE: relies on that the manager task is indeed executed first!
        }
示例#7
0
        private bool TryGetOrAddDocument(AbsolutePath path, VersionedTextDocumentIdentifier documentIdentifier, TextDocumentContentChangeEvent[] changeEvents, out TextDocumentItem document)
        {
            if (!m_documents.TryGetValue(path, out document))
            {
                // The document is missing from the internal storage and the changeset is empty.
                // Can't do anything here.
                if (changeEvents.Length == 0)
                {
                    return(false);
                }

                lock (m_documents)
                {
                    if (!m_documents.TryGetValue(path, out document))
                    {
                        document = new TextDocumentItem()
                        {
                            Version = documentIdentifier.Version,
                            Uri     = documentIdentifier.Uri,
                            Text    = changeEvents.Last().Text,
                        };

                        document = m_documents.GetOrAdd(path, document);
                        return(true);
                    }
                }
            }

            return(true);
        }
示例#8
0
 public void Started(TextDocumentItem textDocument)
 {
     _languageServer.SendNotification(new VerificationStartedParams {
         Uri     = textDocument.Uri,
         Version = textDocument.Version,
     });
 }
示例#9
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");
        }
示例#10
0
        public async Task <Dafny.Program> ParseAsync(TextDocumentItem document, ErrorReporter errorReporter, CancellationToken cancellationToken)
        {
            await _mutex.WaitAsync(cancellationToken);

            try {
                // Ensure that the statically kept scopes are empty when parsing a new document.
                Type.ResetScopes();
                var module      = new LiteralModuleDecl(new DefaultModuleDecl(), null);
                var builtIns    = new BuiltIns();
                var parseErrors = Parser.Parse(
                    document.Text,
                    document.Uri.GetFileSystemPath(),
                    // We use the full path as filename so we can better re-construct the DocumentUri for the definition lookup.
                    document.Uri.GetFileSystemPath(),
                    module,
                    builtIns,
                    errorReporter
                    );
                if (parseErrors != 0)
                {
                    _logger.LogDebug("encountered {} errors while parsing {}", parseErrors, document.Uri);
                }
                if (!TryParseIncludesOfModule(module, builtIns, errorReporter))
                {
                    _logger.LogDebug("encountered error while parsing the includes of {}", document.Uri);
                }
                // TODO Remove PoC workaround: the file system path is used as a program name to
                return(new Dafny.Program(document.Uri.GetFileSystemPath(), module, builtIns, errorReporter));
            } finally {
                _mutex.Release();
            }
        }
示例#11
0
        private static void DoReportDiagnostics(Workspace workspace, TextDocumentItem document, PathTable pathTable, ProviderContext providerContext)
        {
            // We report diagnostics for the document
            var documentUri = document.Uri;

            var semanticModel = workspace.GetSemanticModel();

            Contract.Assert(semanticModel != null, "We should always get a semantic model since we don't cancel on first failure");

            // These are all the syntactic diagnostics that come from the workspace, across all files
            var allDiagnostics = workspace.GetAllParsingAndBindingErrors();

            // If the file is part of the workspace, we add the type checking errors for that file only
            var path = documentUri.ToAbsolutePath(pathTable);

            if (workspace.TryGetSourceFile(path, out var spec))
            {
                allDiagnostics = allDiagnostics.Union(semanticModel.GetTypeCheckingDiagnosticsForFile(spec));
            }

            var publishDiagnostics = FilterDiagnosticsForSpec(documentUri, allDiagnostics, pathTable);

            // Need to report even if publishedDiagnostics is empty to clear the diagnostics list in IDE.
            Analysis.IgnoreResult(providerContext.PublishDiagnosticsAsync(publishDiagnostics), "Fire and forget");
        }
示例#12
0
 public TextDocumentItem ApplyChange(TextDocumentItem originalTextDocument, DidChangeTextDocumentParams documentChange, CancellationToken cancellationToken)
 {
     return(originalTextDocument with {
         Version = documentChange.TextDocument.Version,
         Text = ApplyTextChanges(originalTextDocument.Text, documentChange.ContentChanges, cancellationToken)
     });
 }
示例#13
0
        public async Task <CompilationUnit> ResolveSymbolsAsync(TextDocumentItem textDocument, Dafny.Program program, CancellationToken cancellationToken)
        {
            int parserErrors = GetErrorCount(program);

            if (parserErrors > 0)
            {
                _logger.LogTrace("document {} had {} parser errors, skipping symbol resolution", textDocument.Uri, parserErrors);
                return(new CompilationUnit(program));
            }

            // TODO The resolution requires mutual exclusion since it sets static variables of classes like Microsoft.Dafny.Type.
            //      Although, the variables are marked "ThreadStatic" - thus it might not be necessary. But there might be
            //      other classes as well.
            await _resolverMutex.WaitAsync(cancellationToken);

            try {
                if (!RunDafnyResolver(textDocument, program))
                {
                    // We cannot proceeed without a successful resolution. Due to the contracts in dafny-lang, we cannot
                    // access a property without potential contract violations. For example, a variable may have an
                    // unresolved type represented by null. However, the contract prohibits the use of the type property
                    // because it must not be null.
                    return(new CompilationUnit(program));
                }
            } finally {
                _resolverMutex.Release();
            }
            return(new SymbolDeclarationResolver(_logger, cancellationToken).ProcessProgram(program));
        }
示例#14
0
        public void OnTextDocumentOpened(DidOpenTextDocumentParams messageParams)
        {
            this.textDocument = messageParams.TextDocument;


            SendDiagnostics();
        }
示例#15
0
        public async Task DidOpen(TextDocumentItem textDocument)
        {
            try
            {
                var doc     = new SessionDocument(textDocument);
                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);
                    var colors = session.ColorProvider.ColorDocument(doc1);
                    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);

                        await session.Client.Document.ColorProvider(doc1.Uri, colors);
                    }
                };
                if (Session == null)
                {
                    Program.logWriter.WriteLine("Session is null");
                }
                if (Session.Documents == null)
                {
                    Program.logWriter.WriteLine("Session.Documents is null");
                }

                Session.Documents.TryAdd(textDocument.Uri, doc);

                if (Session.DiagnosticProvider == null)
                {
                    Program.logWriter.WriteLine("Session.DiagnosticProvider is null");
                }

                if (Session.Settings == null)
                {
                    Program.logWriter.WriteLine("Session.Settings is null");
                }

                if (doc.Document == null)
                {
                    Program.logWriter.WriteLine("doc.Document is null");
                }


                var diag = Session.DiagnosticProvider.LintDocument(doc.Document, Session.Settings.MaxNumberOfProblems);
                await Client.Document.PublishDiagnostics(textDocument.Uri, diag);

                var color = Session.ColorProvider.ColorDocument(doc.Document);
                await Client.Document.ColorProvider(textDocument.Uri, color);
            }
            catch (Exception exc)
            {
                Program.logWriter.WriteLine(exc.Message + "\r\n" + exc.StackTrace);
            }
        }
 public async Task<DafnyDocument> LoadDocumentAsync(TextDocumentItem textDocument, CancellationToken cancellationToken) {
   var dafnyDocument = await _documentLoader.LoadAsync(textDocument, VerifyOnLoad, cancellationToken);
   var databaseDocument = _documents.AddOrUpdate(textDocument.Uri, dafnyDocument, (uri, old) => dafnyDocument.Version > old.Version ? dafnyDocument : old);
   if (databaseDocument != dafnyDocument) {
     _logger.LogDebug("a newer version of {} was already loaded", textDocument.Uri);
   }
   return databaseDocument;
 }
示例#17
0
 public void Completed(TextDocumentItem textDocument, bool verified)
 {
     _languageServer.SendNotification(new VerificationCompletedParams {
         Uri      = textDocument.Uri,
         Version  = textDocument.Version,
         Verified = verified
     });
 }
        public DocumentState AddOrUpdateDocument(TextDocumentItem doc)
        {
            var ds = new DocumentState(TextDocument.Load <FullTextDocument>(doc), WiktextParser, loggerFactory);

            DocumentStates[doc.Uri] = ds;
            Attach(ds);
            return(ds);
        }
 public void SendStatusNotification(TextDocumentItem textDocument, CompilationStatus status)
 {
     languageServer.SendNotification(new CompilationStatusParams {
         Uri     = textDocument.Uri,
         Version = textDocument.Version,
         Status  = status
     });
 }
示例#20
0
        public override async Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken)
        {
            return(await Task.Run(() =>
            {
                var link = RenameInfo.GetLink(_languageServer, request.TextDocument.Uri.ToUri(), request.Position);
                if (link == null)
                {
                    return new WorkspaceEdit();
                }

                var grouped = link.Group();
                var documentChanges = new List <WorkspaceEditDocumentChange>();
                foreach (var group in grouped)
                {
                    List <TextEdit> edits = new List <TextEdit>();

                    foreach (var renameRange in group.Links)
                    {
                        edits.Add(new TextEdit()
                        {
                            NewText = request.NewName,
                            Range = renameRange
                        });
                    }

                    var document = _languageServer.DocumentHandler.TextDocumentFromUri(group.Uri)?.AsItem();

                    // document will be null if the editor doesn't have the document of the group opened.
                    if (document == null)
                    {
                        ImportedScript importedScript = _languageServer.FileGetter.GetImportedFile(group.Uri);
                        document = new TextDocumentItem()
                        {
                            Uri = group.Uri,
                            Text = importedScript.Content,
                            LanguageId = "ostw"
                        };
                    }

                    WorkspaceEditDocumentChange edit = new WorkspaceEditDocumentChange(new TextDocumentEdit()
                    {
                        Edits = edits.ToArray(),
                        TextDocument = new VersionedTextDocumentIdentifier()
                        {
                            Version = document.Version,
                            Uri = document.Uri
                        }
                    });
                    documentChanges.Add(edit);
                }

                return new WorkspaceEdit()
                {
                    DocumentChanges = documentChanges
                };
            }));
        }
示例#21
0
 public void Add(TextDocumentItem document)
 {
     if (_all.Any(x => x.uri == document.uri))
     {
         return;
     }
     _all.Add(document);
     OnChanged(document);
 }
示例#22
0
 /// <nodoc />
 protected IdeProviderBase(ProviderContext providerContext)
 {
     ProviderContext = providerContext;
     JsonRpc         = providerContext.JsonRpc;
     PathTable       = providerContext.PathTable;
     m_incrementalWorkspaceProvider = providerContext.IncrementalWorkspaceProvider;
     m_incrementalWorkspaceProvider.WorkspaceRecomputed += OnWorkspaceRecomputed;
     ChangedTextDocumentItems = new TextDocumentItem[0];
 }
示例#23
0
        public void Add(TextDocumentItem document)
        {
            if (_documents.ContainsKey(document.uri))
            {
                return;
            }

            _documents.Add(document.uri, document);
            OnChanged(document);
        }
示例#24
0
 private void ApplyChanges(TextDocumentItem documentItem, params TextDocumentContentChangeEvent[] changes)
 {
     client.DidChangeTextDocument(new DidChangeTextDocumentParams {
         TextDocument = new OptionalVersionedTextDocumentIdentifier {
             Uri     = documentItem.Uri,
             Version = documentItem.Version + 1
         },
         ContentChanges = changes
     });
 }
 private Task <Hover> RequestHover(TextDocumentItem documentItem, Position position)
 {
     return(_client.RequestHover(
                new HoverParams {
         TextDocument = documentItem.Uri,
         Position = position
     },
                CancellationToken
                ));
 }
示例#26
0
 /// <inheritdoc />
 protected override void OnLoad(TextDocumentItem doc)
 {
     base.OnLoad(doc);
     if (string.IsNullOrEmpty(Content))
     {
         _LineStarts = emptyLineStarts;
         return;
     }
     _LineStarts = GetLineStarts(Content).ToArray();
 }
        public void OnTextDocumentOpened(DidOpenTextDocumentParams messageParams)
        {
            this.textDocument = messageParams.TextDocument;

            lock (textDocuments) {
                textDocuments.Add(messageParams.TextDocument);
            }

            SendDiagnostics();
        }
 protected Task ApplyChangeAndWaitCompletionAsync(TextDocumentItem documentItem, Range range, string newText)
 {
     return(ApplyChangesAndWaitCompletionAsync(
                documentItem,
                new TextDocumentContentChangeEvent {
         Text = newText,
         Range = range
     }
                ));
 }
示例#29
0
 private Task <SignatureHelp> RequestSignatureHelpAsync(TextDocumentItem documentItem, Position position)
 {
     // TODO at this time we do not set the context since it appears that's also the case when used within VSCode.
     return(client.RequestSignatureHelp(
                new SignatureHelpParams {
         TextDocument = documentItem.Uri,
         Position = position
     },
                CancellationToken
                ));
 }
 protected Task ApplyChangesAndWaitCompletionAsync(TextDocumentItem documentItem, params TextDocumentContentChangeEvent[] changes)
 {
     Client.DidChangeTextDocument(new DidChangeTextDocumentParams {
         TextDocument = new VersionedTextDocumentIdentifier {
             Uri     = documentItem.Uri,
             Version = documentItem.Version + 1
         },
         ContentChanges = changes
     });
     return(Client.WaitForNotificationCompletionAsync(documentItem.Uri, CancellationToken));
 }