From ffb79071b303fbde3e8a4c141858142f75c5b85d Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Tue, 10 Dec 2024 23:17:05 +0500 Subject: [PATCH] feat(lsp): fix bug when module found up to workspace and we see its problems --- .vscode/launch.json | 4 ++-- cmd/lsp/indexer/indexer.go | 36 ++++++++++++++++++++++++++---- cmd/lsp/server/general_messages.go | 1 + cmd/lsp/server/server.go | 21 ++++++++++++----- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c9612828..25109744 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,8 +7,8 @@ "request": "launch", "mode": "auto", "program": "${workspaceFolder}/cmd/neva", - "cwd": "${workspaceFolder}/examples", - "args": ["run", "--trace", "filter_list"] + "cwd": "${workspaceFolder}/e2e/filter_list", + "args": ["run", "--trace", "main"] }, { "name": "DEBUG CODEGEN", diff --git a/cmd/lsp/indexer/indexer.go b/cmd/lsp/indexer/indexer.go index c7bde73e..efccf141 100644 --- a/cmd/lsp/indexer/indexer.go +++ b/cmd/lsp/indexer/indexer.go @@ -2,6 +2,8 @@ package indexer import ( "context" + "path/filepath" + "strings" "github.com/nevalang/neva/internal/builder" "github.com/nevalang/neva/internal/compiler" @@ -15,12 +17,38 @@ type Indexer struct { analyzer analyzer.Analyzer } -func (i Indexer) FullIndex(ctx context.Context, path string) (src.Build, *compiler.Error) { - feResult, err := i.fe.Process(ctx, path) +func (i Indexer) FullScan( + ctx context.Context, + workspacePath string, +) (src.Build, bool, *compiler.Error) { + feResult, err := i.fe.Process(ctx, workspacePath) if err != nil { - return src.Build{}, err + return src.Build{}, false, err } - return i.analyzer.AnalyzeBuild(feResult.ParsedBuild) + + // if nevalang module is found, but it's not part of the workspace + if isParentPath(workspacePath, feResult.Path) { + return src.Build{}, false, nil + } + + aBuild, err := i.analyzer.AnalyzeBuild(feResult.ParsedBuild) + if err != nil { + return src.Build{}, false, err + } + + return aBuild, true, nil +} + +func isParentPath(parent, child string) bool { + parent = filepath.Clean(parent) + child = filepath.Clean(child) + + rel, err := filepath.Rel(parent, child) + if err != nil { + return false + } + + return !strings.HasPrefix(rel, "..") } func New( diff --git a/cmd/lsp/server/general_messages.go b/cmd/lsp/server/general_messages.go index f45795d0..35806002 100644 --- a/cmd/lsp/server/general_messages.go +++ b/cmd/lsp/server/general_messages.go @@ -7,6 +7,7 @@ import ( func (s *Server) Initialize(glspCtx *glsp.Context, params *protocol.InitializeParams) (any, error) { s.workspacePath = *params.RootPath + return protocol.InitializeResult{ Capabilities: s.handler.CreateServerCapabilities(), ServerInfo: &protocol.InitializeResultServerInfo{ diff --git a/cmd/lsp/server/server.go b/cmd/lsp/server/server.go index e949b3fe..d2352d17 100644 --- a/cmd/lsp/server/server.go +++ b/cmd/lsp/server/server.go @@ -27,20 +27,29 @@ type Server struct { index *src.Build problemsMutex *sync.Mutex - problemFiles map[string]struct{} + problemFiles map[string]struct{} // we only need to store file urls but not their problems activeFile string activeFileMutex *sync.Mutex } +// indexAndNotifyProblems does full scan of the workspace +// and sends diagnostics if there are any problems func (s *Server) indexAndNotifyProblems(notify glsp.NotifyFunc) error { - build, err := s.indexer.FullIndex(context.Background(), s.workspacePath) + build, found, proplems := s.indexer.FullScan( + context.Background(), + s.workspacePath, + ) + + if !found { + return nil + } s.indexMutex.Lock() s.index = &build s.indexMutex.Unlock() - if err == nil { + if proplems == nil { // clear problems s.problemsMutex.Lock() for uri := range s.problemFiles { @@ -60,13 +69,13 @@ func (s *Server) indexAndNotifyProblems(notify glsp.NotifyFunc) error { // remember problem and send diagnostic s.problemsMutex.Lock() - uri := filepath.Join(s.workspacePath, err.Meta.Location.String()) + uri := filepath.Join(s.workspacePath, proplems.Meta.Location.String()) s.problemFiles[uri] = struct{}{} notify( protocol.ServerTextDocumentPublishDiagnostics, - s.createDiagnostics(*err, uri), + s.createDiagnostics(*proplems, uri), ) - s.logger.Info("diagnostic sent:", "err", err) + s.logger.Info("diagnostic sent:", "err", proplems) s.problemsMutex.Unlock() return nil