From 72fea14300babe5ab615db6f4a55eb5a738bb806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20R=C3=A4tzel?= Date: Sun, 22 Dec 2024 18:01:37 +0000 Subject: [PATCH] Switch language service interface to use flat string as file URI --- .../elm-editor/src/Frontend/Main.elm | 11 +- .../elm-editor/src/LanguageService.elm | 165 ++++++------ .../src/LanguageServiceInterface.elm | 16 +- implement/pine/Elm/LanguageServer.cs | 243 +++++------------- .../LanguageServiceRequest.cs | 52 ++-- .../LanguageServiceResponse.cs | 43 +--- implement/pine/Elm/LanguageServiceState.cs | 8 +- .../Elm/elm-compiler/src/LanguageService.elm | 165 ++++++------ .../src/LanguageServiceInterface.elm | 16 +- .../context-app/src/LanguageService.elm | 165 ++++++------ .../src/LanguageServiceInterface.elm | 16 +- .../test-elm-time/ElmLanguageServiceTests.cs | 6 +- 12 files changed, 401 insertions(+), 505 deletions(-) diff --git a/implement/example-apps/elm-editor/src/Frontend/Main.elm b/implement/example-apps/elm-editor/src/Frontend/Main.elm index 7c5b1ffc..785c61db 100644 --- a/implement/example-apps/elm-editor/src/Frontend/Main.elm +++ b/implement/example-apps/elm-editor/src/Frontend/Main.elm @@ -1395,7 +1395,8 @@ updateToProvideHoverRequest request workspaceStateBefore = in updateForRequestToLanguageService (LanguageServiceInterface.ProvideHoverRequest - { filePathOpenedInEditor = directoryPath ++ [ fileName ] + { filePathOpenedInEditor = + String.join "/" (List.concat [ directoryPath, [ fileName ] ]) , positionLineNumber = request.positionLineNumber , positionColumn = request.positionColumn } @@ -1421,7 +1422,8 @@ updateToProvideDefinitionRequest request workspaceStateBefore = in updateForRequestToLanguageService (LanguageServiceInterface.ProvideDefinitionRequest - { filePathOpenedInEditor = directoryPath ++ [ fileName ] + { filePathOpenedInEditor = + String.join "/" (List.concat [ directoryPath, [ fileName ] ]) , positionLineNumber = request.positionLineNumber , positionColumn = request.positionColumn } @@ -1445,7 +1447,8 @@ updateToProvideCompletionItemsRequest request workspaceStateBefore = in updateForRequestToLanguageService (LanguageServiceInterface.ProvideCompletionItemsRequest - { filePathOpenedInEditor = directoryPath ++ [ fileName ] + { filePathOpenedInEditor = + String.join "/" (List.concat [ directoryPath, [ fileName ] ]) , cursorLineNumber = request.cursorLineNumber , cursorColumn = request.cursorColumn } @@ -4281,7 +4284,7 @@ provideDefinitionInMonacoEditorCmd locationsInFiles = monacoLocations = List.map (\locationInFile -> - { uri = monacoUriForFilePath locationInFile.filePath + { uri = monacoUriForFilePath [ locationInFile.filePath ] , range = locationInFile.range } ) diff --git a/implement/example-apps/elm-editor/src/LanguageService.elm b/implement/example-apps/elm-editor/src/LanguageService.elm index 59a1f095..7f377093 100644 --- a/implement/example-apps/elm-editor/src/LanguageService.elm +++ b/implement/example-apps/elm-editor/src/LanguageService.elm @@ -5,6 +5,7 @@ These functions enable features like completion suggestions and hover tips in th -} import Common +import Dict import Elm.Parser import Elm.Syntax.Comments import Elm.Syntax.Declaration @@ -26,14 +27,14 @@ import List.Extra type alias LanguageServiceState = - { fileTreeParseCache : FileTree.FileTreeNode LanguageServiceStateFileTreeNodeBlob + { documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob , coreModulesCache : List ElmCoreModule } type alias LanguageServiceStateFileTreeNodeBlob = { {- Avoid bug in Elm core library as reported at https://github.com/elm/bytes/issues/15 : - Convert to other representation before comparing. + Convert to other representation for equality check. -} sourceBase64 : String , textContent : Maybe FileTextContent @@ -48,14 +49,14 @@ type alias FileTextContent = type alias ParsedModuleCache = - { filePath : List String + { fileUri : String , text : String , syntax : Elm.Syntax.File.File } type alias ParsedCookedModuleCache = - { filePath : List String + { fileUri : String , text : String , syntax : Elm.Syntax.File.File , completionItems : ModuleCompletionItems @@ -96,7 +97,7 @@ type CookedDocumentation type LocationUnderFilePath range - = LocationUnderFilePath (List String) range + = LocationUnderFilePath String range type alias ModuleCompletionItems = @@ -152,12 +153,12 @@ initLanguageServiceState elmCoreModules = |> Maybe.map (\syntax -> { parseResult = - { filePath = [ "elm-core" ] + { fileUri = "elm-core" , text = coreModule.moduleText , syntax = syntax , completionItems = completionItemsFromModule - { filePath = [ "elm-core" ] + { fileUri = "elm-core" , text = coreModule.moduleText , syntax = syntax } @@ -167,7 +168,7 @@ initLanguageServiceState elmCoreModules = ) ) in - { fileTreeParseCache = FileTree.TreeNode [] + { documentCache = Dict.empty , coreModulesCache = elmCoreModulesParseResults } @@ -194,21 +195,19 @@ handleRequestInCurrentWorkspace request stateBefore = let ( serviceResponse, state ) = case request of - LanguageServiceInterface.AddFileRequest filePath content -> - addFile filePath content stateBefore + LanguageServiceInterface.AddFileRequest fileUri fileContent -> + addFile ( fileUri, fileContent ) stateBefore - LanguageServiceInterface.DeleteFileRequest filePath -> + LanguageServiceInterface.DeleteFileRequest fileUri -> let - newFileTree = - case FileTree.removeNodeAtPath filePath stateBefore.fileTreeParseCache of - Nothing -> - stateBefore.fileTreeParseCache - - Just afterRemove -> - afterRemove + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + Dict.remove fileUri stateBefore.documentCache in ( LanguageServiceInterface.WorkspaceSummaryResponse - , { stateBefore | fileTreeParseCache = newFileTree } + , { stateBefore + | documentCache = documentCache + } ) LanguageServiceInterface.ProvideHoverRequest provideHoverRequest -> @@ -271,19 +270,20 @@ handleRequestInCurrentWorkspace request stateBefore = addFile : - List String - -> LanguageServiceInterface.FileTreeBlobNode + ( String + , LanguageServiceInterface.FileTreeBlobNode + ) -> LanguageServiceState -> ( LanguageServiceInterface.Response, LanguageServiceState ) -addFile filePath content stateBefore = +addFile ( fileUri, fileContent ) stateBefore = let maybePreviousCached : Maybe LanguageServiceStateFileTreeNodeBlob maybePreviousCached = - FileTree.getBlobAtPathFromFileTree filePath stateBefore.fileTreeParseCache + Dict.get fileUri stateBefore.documentCache maybeTextContent : Maybe FileTextContent maybeTextContent = - case content.asText of + case fileContent.asText of Nothing -> Nothing @@ -296,12 +296,12 @@ addFile filePath content stateBefore = Ok syntax -> Just - { filePath = filePath + { fileUri = fileUri , text = asString , syntax = syntax , completionItems = completionItemsFromModule - { filePath = filePath + { fileUri = fileUri , text = asString , syntax = syntax } @@ -335,20 +335,20 @@ addFile filePath content stateBefore = Just parsedFile -> Just parsedFile - newFileTree : FileTree.FileTreeNode LanguageServiceStateFileTreeNodeBlob - newFileTree = - FileTree.setNodeAtPathInSortedFileTree - ( filePath - , FileTree.BlobNode - { sourceBase64 = content.asBase64 - , textContent = maybeTextContent - , parsedFileLastSuccess = parsedFileLastSuccess - } - ) - stateBefore.fileTreeParseCache + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + Dict.insert + fileUri + { sourceBase64 = fileContent.asBase64 + , textContent = maybeTextContent + , parsedFileLastSuccess = parsedFileLastSuccess + } + stateBefore.documentCache in ( LanguageServiceInterface.WorkspaceSummaryResponse - , { stateBefore | fileTreeParseCache = newFileTree } + , { stateBefore + | documentCache = documentCache + } ) @@ -359,7 +359,7 @@ provideHover : -> LanguageServiceState -> List String provideHover request languageServiceState = - case languageServiceState.fileTreeParseCache |> FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -389,7 +389,7 @@ provideHover request languageServiceState = type alias ImportedModule = - { filePath : List String + { fileUri : String , canonicalName : List String , importedName : Elm.Syntax.ModuleName.ModuleName , parsedModule : Maybe ParsedCookedModuleCache @@ -530,7 +530,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = ( completionItemLabel , ( maybeFilterRange , LocationUnderFilePath - parsedModule.filePath + parsedModule.fileUri completionItemRange , completionItem ) @@ -578,7 +578,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = if itemInsertText == nameInModule && item.isExposed then Just ( LocationUnderFilePath - referencedModule.filePath + referencedModule.fileUri item.range , itemDocumentation ) @@ -642,7 +642,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = in [ ( rangeModulePart , LocationUnderFilePath - referencedModule.filePath + referencedModule.fileUri (DeclarationRange rangeModulePart []) , documentation ) @@ -730,10 +730,7 @@ provideCompletionItems : -> LanguageServiceState -> List Frontend.MonacoEditor.MonacoCompletionItem provideCompletionItems request languageServiceState = - case - FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor - languageServiceState.fileTreeParseCache - of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -822,7 +819,7 @@ provideDefinitionInternal : -> LanguageServiceState -> List (LocationUnderFilePath DeclarationRange) provideDefinitionInternal request languageServiceState = - case FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor languageServiceState.fileTreeParseCache of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -852,11 +849,11 @@ provideDefinitionInternal request languageServiceState = textDocumentSymbol : - List String + String -> LanguageServiceState -> List LanguageServiceInterface.DocumentSymbol -textDocumentSymbol filePath languageServiceState = - case FileTree.getBlobAtPathFromFileTree filePath languageServiceState.fileTreeParseCache of +textDocumentSymbol fileUri languageServiceState = + case Dict.get fileUri languageServiceState.documentCache of Nothing -> [] @@ -948,7 +945,7 @@ textDocumentReferences referenceRequest languageServiceState = textDocumentReferencesGroupedByFilePath : LanguageServiceInterface.ProvideReferencesRequestStruct -> LanguageServiceState - -> Maybe ( ( List String, DeclarationRange ), List ( List String, List Range ) ) + -> Maybe ( ( String, DeclarationRange ), List ( String, List Range ) ) textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = let maybeDefinition : Maybe (LocationUnderFilePath DeclarationRange) @@ -967,7 +964,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = (DeclarationRange definitionLocationRangeWhole _) = definitionLocationRange - references : List ( List String, List Range ) + references : List ( String, List Range ) references = findReferences ( definitionLocationFilePath, definitionLocationRangeWhole ) languageServiceState in @@ -978,10 +975,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = Nothing -> -- Fallback: try to find a top-level declaration covering this position - case - FileTree.getBlobAtPathFromFileTree referenceRequest.filePathOpenedInEditor - languageServiceState.fileTreeParseCache - of + case Dict.get referenceRequest.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> Nothing @@ -996,7 +990,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = pos = ( referenceRequest.positionLineNumber, referenceRequest.positionColumn ) - maybeTopLevelDefinitionLocation : Maybe ( List String, DeclarationRange ) + maybeTopLevelDefinitionLocation : Maybe ( String, DeclarationRange ) maybeTopLevelDefinitionLocation = parsedFile.completionItems.fromTopLevel |> Common.listMapFind @@ -1013,7 +1007,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = declRangesName then Just - ( parsedFile.filePath + ( parsedFile.fileUri , decl.range ) @@ -1042,23 +1036,23 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = findReferences : - ( List String, Range ) + ( String, Range ) -> LanguageServiceState - -> List ( List String, List Range ) + -> List ( String, List Range ) findReferences ( targetDefinitionFilePath, targetDefinitionRange ) languageServiceState = let allParsedModules : List ParsedCookedModuleCache allParsedModules = List.concat - [ languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + [ languageServiceState.documentCache + |> Dict.toList |> List.filterMap (\( _, blob ) -> blob.parsedFileLastSuccess) , List.map .parseResult languageServiceState.coreModulesCache ] findReferencesInModule : ParsedCookedModuleCache - -> Maybe ( List String, List Range ) + -> Maybe ( String, List Range ) findReferencesInModule parsedModule = let { fromDeclarations } = @@ -1081,7 +1075,7 @@ findReferences ( targetDefinitionFilePath, targetDefinitionRange ) languageServi else Just - ( parsedModule.filePath + ( parsedModule.fileUri , ranges ) in @@ -1406,7 +1400,7 @@ importedModulesFromFile : -> LanguageServiceState -> List - { filePath : List String + { fileUri : String , canonicalName : List String , importedName : Elm.Syntax.ModuleName.ModuleName , parsedModule : Maybe ParsedCookedModuleCache @@ -1428,7 +1422,7 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = Elm.Syntax.Module.moduleName moduleDefinition in Just - { filePath = coreModule.parseResult.filePath + { fileUri = coreModule.parseResult.fileUri , canonicalName = canonicalName , importedName = canonicalName , parsedModule = Just coreModule.parseResult @@ -1477,7 +1471,7 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = Just parsedModule -> Just - { filePath = parsedModule.filePath + { fileUri = parsedModule.fileUri , canonicalName = canonicalName , importedName = importedName , parsedModule = Just parsedModule @@ -1491,8 +1485,8 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = modulesAvailableForImportFromState : LanguageServiceState -> List ParsedCookedModuleCache modulesAvailableForImportFromState languageServiceState = List.concat - [ languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + [ languageServiceState.documentCache + |> Dict.toList |> List.filterMap (\( _, fileCache ) -> fileCache.parsedFileLastSuccess @@ -1519,8 +1513,8 @@ importExposingsFromFile fileOpenedInEditor languageServiceState = importSyntax.moduleName in case - languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + languageServiceState.documentCache + |> Dict.toList |> Common.listMapFind (\( _, fileCache ) -> case fileCache.parsedFileLastSuccess of @@ -1962,10 +1956,12 @@ markdownElmCodeBlockFromCodeLines codeLines = updateLanguageServiceState : LanguageServiceInterface.FileTreeNode -> LanguageServiceState -> LanguageServiceState updateLanguageServiceState fileTree state = let + compileFileCacheEntry : ( String, LanguageServiceInterface.FileTreeBlobNode ) -> LanguageServiceStateFileTreeNodeBlob compileFileCacheEntry ( blobPath, fileTreeBlob ) = let + maybePreviousCached : Maybe LanguageServiceStateFileTreeNodeBlob maybePreviousCached = - state.fileTreeParseCache |> FileTree.getBlobAtPathFromFileTree blobPath + Dict.get blobPath state.documentCache buildNewEntry () = let @@ -1984,12 +1980,12 @@ updateLanguageServiceState fileTree state = Ok syntax -> Just - { filePath = blobPath + { fileUri = blobPath , text = asString , syntax = syntax , completionItems = completionItemsFromModule - { filePath = blobPath + { fileUri = blobPath , text = asString , syntax = syntax } @@ -2034,9 +2030,26 @@ updateLanguageServiceState fileTree state = else buildNewEntry () + + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + fileTree + |> FileTree.flatListOfBlobsFromFileTreeNode + |> List.map + (\( filePath, fileContent ) -> + let + filePathFlat : String + filePathFlat = + String.join "/" filePath + in + ( filePathFlat + , compileFileCacheEntry ( filePathFlat, fileContent ) + ) + ) + |> Dict.fromList in { state - | fileTreeParseCache = FileTree.mapBlobsWithPath compileFileCacheEntry fileTree + | documentCache = documentCache } diff --git a/implement/example-apps/elm-editor/src/LanguageServiceInterface.elm b/implement/example-apps/elm-editor/src/LanguageServiceInterface.elm index 49011db1..f2e7aae3 100644 --- a/implement/example-apps/elm-editor/src/LanguageServiceInterface.elm +++ b/implement/example-apps/elm-editor/src/LanguageServiceInterface.elm @@ -38,12 +38,12 @@ type alias RequestInWorkspace = type Request - = AddFileRequest (List String) FileTreeBlobNode - | DeleteFileRequest (List String) + = AddFileRequest String FileTreeBlobNode + | DeleteFileRequest String | ProvideHoverRequest ProvideHoverRequestStruct | ProvideCompletionItemsRequest ProvideCompletionItemsRequestStruct | ProvideDefinitionRequest ProvideDefinitionRequestStruct - | TextDocumentSymbolRequest (List String) + | TextDocumentSymbolRequest String | TextDocumentReferencesRequest ProvideReferencesRequestStruct | TextDocumentRenameRequest RenameParams @@ -59,14 +59,14 @@ type Response type alias ProvideHoverRequestStruct = - { filePathOpenedInEditor : List String + { filePathOpenedInEditor : String , positionLineNumber : Int , positionColumn : Int } type alias ProvideCompletionItemsRequestStruct = - { filePathOpenedInEditor : List String + { filePathOpenedInEditor : String , cursorLineNumber : Int , cursorColumn : Int } @@ -81,7 +81,7 @@ type alias ProvideReferencesRequestStruct = type alias RenameParams = - { filePath : List String + { filePath : String , positionLineNumber : Int , positionColumn : Int , newName : String @@ -89,7 +89,7 @@ type alias RenameParams = type alias LocationUnderFilePath = - { filePath : List String + { filePath : String , range : Frontend.MonacoEditor.MonacoRange } @@ -130,7 +130,7 @@ type alias WorkspaceEdit = type alias TextDocumentEdit = - { filePath : List String + { filePath : String , edits : List TextEdit } diff --git a/implement/pine/Elm/LanguageServer.cs b/implement/pine/Elm/LanguageServer.cs index f193aa43..9931f5cc 100644 --- a/implement/pine/Elm/LanguageServer.cs +++ b/implement/pine/Elm/LanguageServer.cs @@ -52,16 +52,16 @@ public static Result Init( } public Result AddFile( - IReadOnlyList filePath, + string fileUri, string fileContent) { - return languageServiceState.AddFile(filePath, fileContent); + return languageServiceState.AddFile(fileUri, fileContent); } public Result DeleteFile( - IReadOnlyList filePath) + string fileUri) { - return languageServiceState.DeleteFile(filePath); + return languageServiceState.DeleteFile(fileUri); } public Result HandleRequest( @@ -268,8 +268,14 @@ IEnumerable composeDirectories() fileClock.Restart(); + if (System.Uri.TryCreate(elmFile, System.UriKind.Absolute, out var uri) is false) + { + Log("Failed to create URI: " + elmFile); + continue; + } + languageServiceState.AddFile( - PathItemsFromFlatPath(elmFile), + uri.AbsoluteUri, fileContent); Log( @@ -315,7 +321,7 @@ public void Workspace_didChangeWorkspaceFolders(WorkspaceFoldersChangeEvent work public void TextDocument_didOpen(TextDocumentItem textDocument) { - var decodedUri = System.Uri.UnescapeDataString(textDocument.Uri); + var decodedUri = DocumentUriCleaned(textDocument.Uri); Log("TextDocument_didOpen: " + decodedUri); @@ -328,7 +334,7 @@ public void TextDocument_didChange( VersionedTextDocumentIdentifier textDocument, IReadOnlyList contentChanges) { - var textDocumentUri = System.Uri.UnescapeDataString(textDocument.Uri); + var textDocumentUri = DocumentUriCleaned(textDocument.Uri); allSeenDocumentUris[textDocumentUri] = textDocumentUri; @@ -365,7 +371,7 @@ public void TextDocument_didChange( public void TextDocument_didClose(TextDocumentIdentifier textDocument) { - var decodedUri = System.Uri.UnescapeDataString(textDocument.Uri); + var decodedUri = DocumentUriCleaned(textDocument.Uri); clientTextDocumentContents.TryRemove(decodedUri, out var _); @@ -381,7 +387,7 @@ public void Workspace_didChangeWatchedFiles(IReadOnlyList changesBefo change with { - Uri = System.Uri.UnescapeDataString(change.Uri) + Uri = DocumentUriCleaned(change.Uri) }) .ToList(); @@ -427,8 +433,7 @@ public void Workspace_didChangeWatchedFiles(IReadOnlyList changesBefo if (change.Type is FileChangeType.Deleted) { - languageServiceState.DeleteFile( - PathItemsFromFlatPath(localPath)); + languageServiceState.DeleteFile(change.Uri); } if (change.Type is not FileChangeType.Created && @@ -454,7 +459,7 @@ public void Workspace_didChangeWatchedFiles(IReadOnlyList changesBefo clock.Restart(); languageServiceState.AddFile( - PathItemsFromFlatPath(localPath), + change.Uri, fileContent); Log( @@ -473,12 +478,28 @@ public IReadOnlyList TextDocument_formatting( TextDocumentIdentifier textDocument, FormattingOptions options) { - var textDocumentUri = System.Uri.UnescapeDataString(textDocument.Uri); + var textDocumentUri = DocumentUriCleaned(textDocument.Uri); Log("TextDocument_formatting: " + textDocumentUri); clientTextDocumentContents.TryGetValue(textDocumentUri, out var textDocumentContentBefore); + var localPathResult = DocumentUriAsLocalPath(textDocumentUri); + + { + if (localPathResult.IsErrOrNull() is { } err) + { + Log("Ignoring URI: " + err + ": " + textDocumentUri); + return []; + } + } + + if (localPathResult.IsOkOrNull() is not { } localPath) + { + throw new System.NotImplementedException( + "Unexpected result type: " + localPathResult.GetType()); + } + if (textDocumentContentBefore is not null) { Log("Found document " + textDocumentUri + " in client-managed state"); @@ -487,7 +508,7 @@ public IReadOnlyList TextDocument_formatting( { try { - textDocumentContentBefore ??= System.IO.File.ReadAllText(textDocumentUri); + textDocumentContentBefore ??= System.IO.File.ReadAllText(localPath); } catch (System.Exception e) { @@ -570,35 +591,16 @@ static TextEdit replaceWholeDocument(string newContent) public Hover? TextDocument_hover( TextDocumentPositionParams positionParams) { - var textDocumentUri = System.Uri.UnescapeDataString(positionParams.TextDocument.Uri); + var textDocumentUri = DocumentUriCleaned(positionParams.TextDocument.Uri); var clock = System.Diagnostics.Stopwatch.StartNew(); Log("TextDocument_hover: " + textDocumentUri + " at " + positionParams.Position); - var localPathResult = DocumentUriAsLocalPath(textDocumentUri); - - { - if (localPathResult.IsErrOrNull() is { } err) - { - Log("Ignoring URI: " + err + ": " + textDocumentUri); - - return null; - } - } - - if (localPathResult.IsOkOrNull() is not { } localPath) - { - throw new System.NotImplementedException( - "Unexpected result type: " + localPathResult.GetType()); - } - - var filePathOpenedInEditor = PathItemsFromFlatPath(localPath); - var hoverStrings = ProvideHover( new Interface.ProvideHoverRequestStruct( - filePathOpenedInEditor, + textDocumentUri, /* * The language service currently uses the 1-based line and column numbers * inherited from the Monaco editor API. @@ -635,33 +637,16 @@ static TextEdit replaceWholeDocument(string newContent) public CompletionItem[] TextDocument_completion( TextDocumentPositionParams positionParams) { - var textDocumentUri = System.Uri.UnescapeDataString(positionParams.TextDocument.Uri); + var textDocumentUri = DocumentUriCleaned(positionParams.TextDocument.Uri); var clock = System.Diagnostics.Stopwatch.StartNew(); Log("TextDocument_completion: " + textDocumentUri + " at " + positionParams.Position); - var localPathResult = DocumentUriAsLocalPath(textDocumentUri); - { - if (localPathResult.IsErrOrNull() is { } err) - { - Log("Ignoring URI: " + err + ": " + textDocumentUri); - return []; - } - } - - if (localPathResult.IsOkOrNull() is not { } localPath) - { - throw new System.NotImplementedException( - "Unexpected result type: " + localPathResult.GetType()); - } - - var filePathOpenedInEditor = PathItemsFromFlatPath(localPath); - var completionItems = ProvideCompletionItems( new Interface.ProvideCompletionItemsRequestStruct( - filePathOpenedInEditor, + textDocumentUri, /* * The language service currently uses the 1-based line and column numbers * inherited from the Monaco editor API. @@ -710,33 +695,16 @@ public CompletionItem[] TextDocument_completion( public IReadOnlyList TextDocument_definition( TextDocumentPositionParams positionParams) { - var textDocumentUri = System.Uri.UnescapeDataString(positionParams.TextDocument.Uri); + var textDocumentUri = DocumentUriCleaned(positionParams.TextDocument.Uri); var clock = System.Diagnostics.Stopwatch.StartNew(); Log("TextDocument_definition: " + textDocumentUri + " at " + positionParams.Position); - var localPathResult = DocumentUriAsLocalPath(textDocumentUri); - { - if (localPathResult.IsErrOrNull() is { } err) - { - Log("Ignoring URI: " + err + ": " + textDocumentUri); - return []; - } - } - - if (localPathResult.IsOkOrNull() is not { } localPath) - { - throw new System.NotImplementedException( - "Unexpected result type: " + localPathResult.GetType()); - } - - var filePathOpenedInEditor = PathItemsFromFlatPath(localPath); - var provideDefinitionResult = ProvideDefinition( new Interface.ProvideHoverRequestStruct( - filePathOpenedInEditor, + textDocumentUri, PositionLineNumber: (int)positionParams.Position.Line + 1, PositionColumn: (int)positionParams.Position.Character + 1)); @@ -784,13 +752,14 @@ public IReadOnlyList TextDocument_definition( public IReadOnlyList TextDocument_documentSymbol( TextDocumentIdentifier textDocument) { - var textDocumentUri = System.Uri.UnescapeDataString(textDocument.Uri); + var textDocumentUri = DocumentUriCleaned(textDocument.Uri); var clock = System.Diagnostics.Stopwatch.StartNew(); Log("textDocument/documentSymbol: " + textDocumentUri); var localPathResult = DocumentUriAsLocalPath(textDocumentUri); + { if (localPathResult.IsErrOrNull() is { } err) { @@ -823,13 +792,11 @@ public IReadOnlyList TextDocument_documentSymbol( } languageServiceState.AddFile( - PathItemsFromFlatPath(localPath), + textDocumentUri, fileContent); - var filePathOpenedInEditor = PathItemsFromFlatPath(localPath); - var documentSymbols = - TextDocumentSymbolRequest(filePathOpenedInEditor); + TextDocumentSymbolRequest(textDocumentUri); { if (documentSymbols.IsErrOrNull() is { } err) @@ -908,34 +875,16 @@ static DocumentSymbol mapDocumentSymbol(Interface.DocumentSymbolStruct documentS public IReadOnlyList TextDocument_references( TextDocumentPositionParams positionParams) { - var textDocumentUri = - System.Uri.UnescapeDataString(positionParams.TextDocument.Uri); + var textDocumentUri = DocumentUriCleaned(positionParams.TextDocument.Uri); var clock = System.Diagnostics.Stopwatch.StartNew(); Log("TextDocument_references: " + textDocumentUri + " at " + positionParams.Position); - var localPathResult = DocumentUriAsLocalPath(textDocumentUri); - { - if (localPathResult.IsErrOrNull() is { } err) - { - Log("Ignoring URI: " + err + ": " + textDocumentUri); - return []; - } - } - - if (localPathResult.IsOkOrNull() is not { } localPath) - { - throw new System.NotImplementedException( - "Unexpected result type: " + localPathResult.GetType()); - } - - var filePathOpenedInEditor = PathItemsFromFlatPath(localPath); - var provideReferenceResult = TextDocumentReferencesRequest( new Interface.ProvideHoverRequestStruct( - filePathOpenedInEditor, + textDocumentUri, PositionLineNumber: (int)positionParams.Position.Line + 1, PositionColumn: (int)positionParams.Position.Character + 1)); { @@ -981,35 +930,16 @@ public IReadOnlyList TextDocument_references( public Result TextDocument_rename( RenameParams renameParams) { - var textDocumentUri = - System.Uri.UnescapeDataString(renameParams.TextDocument.Uri); + var textDocumentUri = DocumentUriCleaned(renameParams.TextDocument.Uri); var clock = System.Diagnostics.Stopwatch.StartNew(); Log("TextDocument_rename: " + textDocumentUri + " at " + renameParams.Position); - var localPathResult = DocumentUriAsLocalPath(textDocumentUri); - { - if (localPathResult.IsErrOrNull() is { } err) - { - Log("Ignoring URI: " + err + ": " + textDocumentUri); - - return "Ignoring URI: " + err + ": " + textDocumentUri; - } - } - - if (localPathResult.IsOkOrNull() is not { } localPath) - { - throw new System.NotImplementedException( - "Unexpected result type: " + localPathResult.GetType()); - } - - var filePathOpenedInEditor = PathItemsFromFlatPath(localPath); - var provideRenameResult = TextDocumentRenameRequest( new Interface.RenameParams( - filePathOpenedInEditor, + textDocumentUri, /* * The language service currently uses the 1-based line and column numbers * inherited from the Monaco editor API. @@ -1041,14 +971,8 @@ public IReadOnlyList TextDocument_references( var documentChanges = provideRenameOk.Edits - .SelectMany(documentEdit => + .Select(documentEdit => { - if (CorrespondingUri(documentEdit.FilePath) is not { } documentUri) - { - Log("No corresponding URI for " + documentEdit.FilePath); - return (IReadOnlyList)[]; - } - var editsInDocument = documentEdit.Edits .Select(edit => @@ -1062,9 +986,10 @@ public IReadOnlyList TextDocument_references( Character: (uint)edit.Range.EndColumn - 1)), NewText: edit.NewText)); - return [new TextDocumentEdit( - new OptionalVersionedTextDocumentIdentifier(documentUri, Version: null), - [.. editsInDocument])]; + return + new TextDocumentEdit( + new OptionalVersionedTextDocumentIdentifier(documentEdit.FilePath, Version: null), + [.. editsInDocument]); }) .ToImmutableArray(); @@ -1075,7 +1000,7 @@ public void TextDocument_didSave( DidSaveTextDocumentParams didSaveParams, System.Action> publishDiagnostics) { - var textDocumentUri = System.Uri.UnescapeDataString(didSaveParams.TextDocument.Uri); + var textDocumentUri = DocumentUriCleaned(didSaveParams.TextDocument.Uri); allSeenDocumentUris[textDocumentUri] = textDocumentUri; @@ -1185,15 +1110,6 @@ public void TextDocument_didSave( Log("Elm make errors for " + path + ": " + pathErrors.Length); - var correspondingUri = - allSeenDocumentUris - .FirstOrDefault(uri => DocumentUriAsLocalPath(uri.Value).WithDefault(null) == path).Key; - - if (correspondingUri is null) - { - Log("No corresponding URI for " + path); - } - IReadOnlyList diagnostics = [..pathErrors .Select(problem => @@ -1271,11 +1187,6 @@ public static Result ParseReportFromElmMake(string elmMak return null; } - static IReadOnlyList PathItemsFromFlatPath(string path) - { - return path.Split(['\\', '/']); - } - public static TreeNodeWithStringPath MergeIntoFileTree( TreeNodeWithStringPath seed, IReadOnlyDictionary, System.ReadOnlyMemory> dictionary) @@ -1381,11 +1292,11 @@ public Result> ProvideHover( } public Result> TextDocumentSymbolRequest( - IReadOnlyList filePath) + string fileUri) { var genericRequestResult = HandleRequest( - new Interface.Request.TextDocumentSymbolRequest(filePath)); + new Interface.Request.TextDocumentSymbolRequest(fileUri)); if (genericRequestResult.IsErrOrNull() is { } err) { @@ -1494,48 +1405,32 @@ public IEnumerable MapLocations( { return locations - .SelectMany(location => + .Select(location => { - if (CorrespondingUri(location.FilePath) is not { } uri) - { - return noMatchingUri(location.FilePath); - } - return - [new Location( - uri, + new Location( + location.FilePath, new Range( Start: new Position( Line: (uint)location.Range.StartLineNumber - 1, Character: (uint)location.Range.StartColumn - 1), End: new Position( Line: (uint)location.Range.EndLineNumber - 1, - Character: (uint)location.Range.EndColumn - 1))) - ]; + Character: (uint)location.Range.EndColumn - 1))); }); } - string? CorrespondingUri(IReadOnlyList path) + public static string DocumentUriCleaned(string documentUri) { - var flatPathForward = string.Join('/', path); - var flatPathBackward = string.Join('\\', path); - - var fromSeenUris = - allSeenDocumentUris - .FirstOrDefault(uri => - DocumentUriAsLocalPath(uri.Value).IsOkOrNull() is { } asLocalOk && - (asLocalOk == flatPathBackward || - asLocalOk == flatPathBackward)).Key; + /* + * The client in VSCode appears to send document URIs like this: + * file:///k%3A/Source/Repos/ + * Therefore we need to decode before handing to System.Uri + * */ - if (fromSeenUris is not null) - return fromSeenUris; + var unescaped = System.Uri.UnescapeDataString(documentUri); - return - System.Uri.TryCreate(flatPathForward, System.UriKind.Absolute, out var uri) - ? - uri.AbsoluteUri - : - null; + return unescaped.Replace("\\", "/"); } public static Result DocumentUriAsLocalPath(string documentUri) diff --git a/implement/pine/Elm/LanguageServiceInterface/LanguageServiceRequest.cs b/implement/pine/Elm/LanguageServiceInterface/LanguageServiceRequest.cs index d09be94d..2bc4bdf6 100644 --- a/implement/pine/Elm/LanguageServiceInterface/LanguageServiceRequest.cs +++ b/implement/pine/Elm/LanguageServiceInterface/LanguageServiceRequest.cs @@ -18,12 +18,12 @@ public record FileTreeBlobNode( /* type Request - = AddFileRequest (List String) FileTreeBlobNode - | DeleteFileRequest (List String) + = AddFileRequest String FileTreeBlobNode + | DeleteFileRequest String | ProvideHoverRequest ProvideHoverRequestStruct | ProvideCompletionItemsRequest ProvideCompletionItemsRequestStruct | ProvideDefinitionRequest ProvideDefinitionRequestStruct - | TextDocumentSymbolRequest (List String) + | TextDocumentSymbolRequest String | TextDocumentReferencesRequest ProvideReferencesRequestStruct | TextDocumentRenameRequest RenameParams @@ -31,11 +31,11 @@ type Request public abstract record Request { public record AddFileRequest( - IReadOnlyList FilePath, + string FilePath, FileTreeBlobNode Blob) : Request; - public record DeleteFileRequest(IReadOnlyList FilePath) + public record DeleteFileRequest(string FilePath) : Request; public record ProvideHoverRequest(ProvideHoverRequestStruct Request) @@ -47,7 +47,7 @@ public record ProvideCompletionItemsRequest(ProvideCompletionItemsRequestStruct public record ProvideDefinitionRequest(ProvideHoverRequestStruct Request) : Request; - public record TextDocumentSymbolRequest(IReadOnlyList FilePath) + public record TextDocumentSymbolRequest(string FilePath) : Request; public record TextDocumentReferencesRequest(ProvideHoverRequestStruct Request) @@ -58,14 +58,14 @@ public record TextDocumentRenameRequest(RenameParams Request) } public record ProvideHoverRequestStruct( - IReadOnlyList FilePathOpenedInEditor, + string FilePathOpenedInEditor, int PositionLineNumber, int PositionColumn); /* type alias ProvideCompletionItemsRequestStruct = - { filePathOpenedInEditor : List String + { filePathOpenedInEditor : String , cursorLineNumber : Int , cursorColumn : Int } @@ -73,13 +73,13 @@ public record ProvideHoverRequestStruct( * */ public record ProvideCompletionItemsRequestStruct( - IReadOnlyList FilePathOpenedInEditor, + string FilePathOpenedInEditor, int CursorLineNumber, int CursorColumn); /* type alias RenameParams = - { filePath : List String + { filePath : String , positionLineNumber : Int , positionColumn : Int , newName : String @@ -88,7 +88,7 @@ public record ProvideCompletionItemsRequestStruct( */ public record RenameParams( - IReadOnlyList FilePath, + string FilePath, int PositionLineNumber, int PositionColumn, string NewName); @@ -103,10 +103,7 @@ public static PineValue Encode(Request request) ElmValueEncoding.TagAsPineValue( "AddFileRequest", [ - PineValue.List( - [..addFileRequest.FilePath - .Select(ElmValueEncoding.StringAsPineValue) - ]), + ElmValueEncoding.StringAsPineValue(addFileRequest.FilePath), ElmValueEncoding.ElmValueAsPineValue( new ElmValue.ElmRecord( [ @@ -127,10 +124,7 @@ addFileRequest.Blob.AsText is { } asText ElmValueEncoding.TagAsPineValue( "DeleteFileRequest", [ - PineValue.List( - [..deleteFileRequest.FilePath - .Select(ElmValueEncoding.StringAsPineValue) - ]) + ElmValueEncoding.StringAsPineValue(deleteFileRequest.FilePath), ]), Request.ProvideHoverRequest provideHoverRequest => @@ -158,10 +152,7 @@ addFileRequest.Blob.AsText is { } asText ElmValueEncoding.TagAsPineValue( "TextDocumentSymbolRequest", [ - PineValue.List( - [..textDocumentSymbolRequest.FilePath - .Select(ElmValueEncoding.StringAsPineValue) - ]) + ElmValueEncoding.StringAsPineValue(textDocumentSymbolRequest.FilePath) ]), Request.TextDocumentReferencesRequest textDocumentReferenceRequest => @@ -190,10 +181,7 @@ public static PineValue Encode(ProvideHoverRequestStruct provideHoverRequest) ElmValueEncoding.ElmRecordAsPineValue( [ ("filePathOpenedInEditor", - PineValue.List( - [..provideHoverRequest.FilePathOpenedInEditor - .Select(ElmValueEncoding.StringAsPineValue) - ])), + ElmValueEncoding.StringAsPineValue(provideHoverRequest.FilePathOpenedInEditor)), ("positionLineNumber", PineValueAsInteger.ValueFromSignedInteger(provideHoverRequest.PositionLineNumber)), ("positionColumn", @@ -207,10 +195,7 @@ public static PineValue Encode(ProvideCompletionItemsRequestStruct provideComple ElmValueEncoding.ElmRecordAsPineValue( [ ("filePathOpenedInEditor", - PineValue.List( - [..provideCompletionItemsRequest.FilePathOpenedInEditor - .Select(ElmValueEncoding.StringAsPineValue) - ])), + ElmValueEncoding.StringAsPineValue(provideCompletionItemsRequest.FilePathOpenedInEditor)), ("cursorLineNumber", PineValueAsInteger.ValueFromSignedInteger(provideCompletionItemsRequest.CursorLineNumber)), ("cursorColumn", @@ -224,10 +209,7 @@ public static PineValue Encode(RenameParams renameParams) ElmValueEncoding.ElmRecordAsPineValue( [ ("filePath", - PineValue.List( - [..renameParams.FilePath - .Select(ElmValueEncoding.StringAsPineValue) - ])), + ElmValueEncoding.StringAsPineValue(renameParams.FilePath)), ("positionLineNumber", PineValueAsInteger.ValueFromSignedInteger(renameParams.PositionLineNumber)), ("positionColumn", diff --git a/implement/pine/Elm/LanguageServiceInterface/LanguageServiceResponse.cs b/implement/pine/Elm/LanguageServiceInterface/LanguageServiceResponse.cs index 100be62c..bc609d06 100644 --- a/implement/pine/Elm/LanguageServiceInterface/LanguageServiceResponse.cs +++ b/implement/pine/Elm/LanguageServiceInterface/LanguageServiceResponse.cs @@ -52,13 +52,13 @@ public record TextDocumentRenameResponse( /* type alias LocationUnderFilePath = - { filePath : List String + { filePath : String , range : Frontend.MonacoEditor.MonacoRange } * */ public record LocationUnderFilePath( - IReadOnlyList FilePath, + string FilePath, MonacoEditor.MonacoRange Range); @@ -132,7 +132,7 @@ List TextDocumentEdit type alias TextDocumentEdit = - { filePath : List String + { filePath : String , edits : List TextEdit } @@ -148,7 +148,7 @@ public record WorkspaceEdit( IReadOnlyList Edits); public record TextDocumentEdit( - IReadOnlyList FilePath, + string FilePath, IReadOnlyList Edits); public record TextEdit( @@ -470,20 +470,9 @@ public static Result Decode(ElmValue elmValue) string.Join(", ", record.Fields.Select(f => f.FieldName)); } - if (filePathValue is not ElmValue.ElmList filePathListValue) + if (filePathValue is not ElmValue.ElmString filePathString) { - return "Expected field 'filePath' to be a list, got: " + filePathValue.GetType(); - } - - // Decode filePath as a list of strings - var filePathArray = new string[filePathListValue.Elements.Count]; - for (var i = 0; i < filePathListValue.Elements.Count; i++) - { - if (filePathListValue.Elements[i] is not ElmValue.ElmString strVal) - { - return "Expected element of 'filePath' to be a string, got: " + filePathListValue.Elements[i].GetType(); - } - filePathArray[i] = strVal.Value; + return "Expected field 'filePath' to be a string, got: " + filePathValue.GetType(); } if (record["range"] is not { } rangeValue) @@ -507,7 +496,7 @@ public static Result Decode(ElmValue elmValue) ("Unexpected result type: " + rangeDecodeResult.GetType()); } - return new LocationUnderFilePath(filePathArray, range); + return new LocationUnderFilePath(filePathString.Value, range); } } @@ -900,21 +889,9 @@ public static Result Decode(ElmValue elmValue) string.Join(", ", record.Fields.Select(f => f.FieldName)); } - if (filePathValue is not ElmValue.ElmList filePathListValue) - { - return "Expected field 'filePath' to be a list, got: " + filePathValue.GetType(); - } - - var filePathArray = new string[filePathListValue.Elements.Count]; - - for (var i = 0; i < filePathListValue.Elements.Count; i++) + if (filePathValue is not ElmValue.ElmString filePathString) { - if (filePathListValue.Elements[i] is not ElmValue.ElmString strVal) - { - return "Expected element of 'filePath' to be a string, got: " + filePathListValue.Elements[i].GetType(); - } - - filePathArray[i] = strVal.Value; + return "Expected field 'filePath' to be a string, got: " + filePathValue.GetType(); } if (record["edits"] is not { } editsValue) @@ -949,7 +926,7 @@ public static Result Decode(ElmValue elmValue) textEdits[i] = textEdit; } - return new TextDocumentEdit(filePathArray, textEdits); + return new TextDocumentEdit(filePathString.Value, textEdits); } } diff --git a/implement/pine/Elm/LanguageServiceState.cs b/implement/pine/Elm/LanguageServiceState.cs index 2d92530a..b04931c7 100644 --- a/implement/pine/Elm/LanguageServiceState.cs +++ b/implement/pine/Elm/LanguageServiceState.cs @@ -92,10 +92,10 @@ public static Result InitLanguageServiceState( public Result DeleteFile( - IReadOnlyList filePath) + string fileUri) { var genericRequestResult = - HandleRequest(new Interface.Request.DeleteFileRequest(filePath)); + HandleRequest(new Interface.Request.DeleteFileRequest(fileUri)); if (genericRequestResult.IsErrOrNull() is { } err) { @@ -119,7 +119,7 @@ public static Result InitLanguageServiceState( public Result AddFile( - IReadOnlyList filePath, + string fileUri, string fileContentAsText) { var asBase64 = @@ -129,7 +129,7 @@ public static Result InitLanguageServiceState( var genericRequestResult = HandleRequest( new Interface.Request.AddFileRequest( - filePath, + fileUri, new Interface.FileTreeBlobNode(AsBase64: asBase64, AsText: fileContentAsText))); if (genericRequestResult.IsErrOrNull() is { } err) diff --git a/implement/pine/Elm/elm-compiler/src/LanguageService.elm b/implement/pine/Elm/elm-compiler/src/LanguageService.elm index 59a1f095..7f377093 100644 --- a/implement/pine/Elm/elm-compiler/src/LanguageService.elm +++ b/implement/pine/Elm/elm-compiler/src/LanguageService.elm @@ -5,6 +5,7 @@ These functions enable features like completion suggestions and hover tips in th -} import Common +import Dict import Elm.Parser import Elm.Syntax.Comments import Elm.Syntax.Declaration @@ -26,14 +27,14 @@ import List.Extra type alias LanguageServiceState = - { fileTreeParseCache : FileTree.FileTreeNode LanguageServiceStateFileTreeNodeBlob + { documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob , coreModulesCache : List ElmCoreModule } type alias LanguageServiceStateFileTreeNodeBlob = { {- Avoid bug in Elm core library as reported at https://github.com/elm/bytes/issues/15 : - Convert to other representation before comparing. + Convert to other representation for equality check. -} sourceBase64 : String , textContent : Maybe FileTextContent @@ -48,14 +49,14 @@ type alias FileTextContent = type alias ParsedModuleCache = - { filePath : List String + { fileUri : String , text : String , syntax : Elm.Syntax.File.File } type alias ParsedCookedModuleCache = - { filePath : List String + { fileUri : String , text : String , syntax : Elm.Syntax.File.File , completionItems : ModuleCompletionItems @@ -96,7 +97,7 @@ type CookedDocumentation type LocationUnderFilePath range - = LocationUnderFilePath (List String) range + = LocationUnderFilePath String range type alias ModuleCompletionItems = @@ -152,12 +153,12 @@ initLanguageServiceState elmCoreModules = |> Maybe.map (\syntax -> { parseResult = - { filePath = [ "elm-core" ] + { fileUri = "elm-core" , text = coreModule.moduleText , syntax = syntax , completionItems = completionItemsFromModule - { filePath = [ "elm-core" ] + { fileUri = "elm-core" , text = coreModule.moduleText , syntax = syntax } @@ -167,7 +168,7 @@ initLanguageServiceState elmCoreModules = ) ) in - { fileTreeParseCache = FileTree.TreeNode [] + { documentCache = Dict.empty , coreModulesCache = elmCoreModulesParseResults } @@ -194,21 +195,19 @@ handleRequestInCurrentWorkspace request stateBefore = let ( serviceResponse, state ) = case request of - LanguageServiceInterface.AddFileRequest filePath content -> - addFile filePath content stateBefore + LanguageServiceInterface.AddFileRequest fileUri fileContent -> + addFile ( fileUri, fileContent ) stateBefore - LanguageServiceInterface.DeleteFileRequest filePath -> + LanguageServiceInterface.DeleteFileRequest fileUri -> let - newFileTree = - case FileTree.removeNodeAtPath filePath stateBefore.fileTreeParseCache of - Nothing -> - stateBefore.fileTreeParseCache - - Just afterRemove -> - afterRemove + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + Dict.remove fileUri stateBefore.documentCache in ( LanguageServiceInterface.WorkspaceSummaryResponse - , { stateBefore | fileTreeParseCache = newFileTree } + , { stateBefore + | documentCache = documentCache + } ) LanguageServiceInterface.ProvideHoverRequest provideHoverRequest -> @@ -271,19 +270,20 @@ handleRequestInCurrentWorkspace request stateBefore = addFile : - List String - -> LanguageServiceInterface.FileTreeBlobNode + ( String + , LanguageServiceInterface.FileTreeBlobNode + ) -> LanguageServiceState -> ( LanguageServiceInterface.Response, LanguageServiceState ) -addFile filePath content stateBefore = +addFile ( fileUri, fileContent ) stateBefore = let maybePreviousCached : Maybe LanguageServiceStateFileTreeNodeBlob maybePreviousCached = - FileTree.getBlobAtPathFromFileTree filePath stateBefore.fileTreeParseCache + Dict.get fileUri stateBefore.documentCache maybeTextContent : Maybe FileTextContent maybeTextContent = - case content.asText of + case fileContent.asText of Nothing -> Nothing @@ -296,12 +296,12 @@ addFile filePath content stateBefore = Ok syntax -> Just - { filePath = filePath + { fileUri = fileUri , text = asString , syntax = syntax , completionItems = completionItemsFromModule - { filePath = filePath + { fileUri = fileUri , text = asString , syntax = syntax } @@ -335,20 +335,20 @@ addFile filePath content stateBefore = Just parsedFile -> Just parsedFile - newFileTree : FileTree.FileTreeNode LanguageServiceStateFileTreeNodeBlob - newFileTree = - FileTree.setNodeAtPathInSortedFileTree - ( filePath - , FileTree.BlobNode - { sourceBase64 = content.asBase64 - , textContent = maybeTextContent - , parsedFileLastSuccess = parsedFileLastSuccess - } - ) - stateBefore.fileTreeParseCache + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + Dict.insert + fileUri + { sourceBase64 = fileContent.asBase64 + , textContent = maybeTextContent + , parsedFileLastSuccess = parsedFileLastSuccess + } + stateBefore.documentCache in ( LanguageServiceInterface.WorkspaceSummaryResponse - , { stateBefore | fileTreeParseCache = newFileTree } + , { stateBefore + | documentCache = documentCache + } ) @@ -359,7 +359,7 @@ provideHover : -> LanguageServiceState -> List String provideHover request languageServiceState = - case languageServiceState.fileTreeParseCache |> FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -389,7 +389,7 @@ provideHover request languageServiceState = type alias ImportedModule = - { filePath : List String + { fileUri : String , canonicalName : List String , importedName : Elm.Syntax.ModuleName.ModuleName , parsedModule : Maybe ParsedCookedModuleCache @@ -530,7 +530,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = ( completionItemLabel , ( maybeFilterRange , LocationUnderFilePath - parsedModule.filePath + parsedModule.fileUri completionItemRange , completionItem ) @@ -578,7 +578,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = if itemInsertText == nameInModule && item.isExposed then Just ( LocationUnderFilePath - referencedModule.filePath + referencedModule.fileUri item.range , itemDocumentation ) @@ -642,7 +642,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = in [ ( rangeModulePart , LocationUnderFilePath - referencedModule.filePath + referencedModule.fileUri (DeclarationRange rangeModulePart []) , documentation ) @@ -730,10 +730,7 @@ provideCompletionItems : -> LanguageServiceState -> List Frontend.MonacoEditor.MonacoCompletionItem provideCompletionItems request languageServiceState = - case - FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor - languageServiceState.fileTreeParseCache - of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -822,7 +819,7 @@ provideDefinitionInternal : -> LanguageServiceState -> List (LocationUnderFilePath DeclarationRange) provideDefinitionInternal request languageServiceState = - case FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor languageServiceState.fileTreeParseCache of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -852,11 +849,11 @@ provideDefinitionInternal request languageServiceState = textDocumentSymbol : - List String + String -> LanguageServiceState -> List LanguageServiceInterface.DocumentSymbol -textDocumentSymbol filePath languageServiceState = - case FileTree.getBlobAtPathFromFileTree filePath languageServiceState.fileTreeParseCache of +textDocumentSymbol fileUri languageServiceState = + case Dict.get fileUri languageServiceState.documentCache of Nothing -> [] @@ -948,7 +945,7 @@ textDocumentReferences referenceRequest languageServiceState = textDocumentReferencesGroupedByFilePath : LanguageServiceInterface.ProvideReferencesRequestStruct -> LanguageServiceState - -> Maybe ( ( List String, DeclarationRange ), List ( List String, List Range ) ) + -> Maybe ( ( String, DeclarationRange ), List ( String, List Range ) ) textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = let maybeDefinition : Maybe (LocationUnderFilePath DeclarationRange) @@ -967,7 +964,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = (DeclarationRange definitionLocationRangeWhole _) = definitionLocationRange - references : List ( List String, List Range ) + references : List ( String, List Range ) references = findReferences ( definitionLocationFilePath, definitionLocationRangeWhole ) languageServiceState in @@ -978,10 +975,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = Nothing -> -- Fallback: try to find a top-level declaration covering this position - case - FileTree.getBlobAtPathFromFileTree referenceRequest.filePathOpenedInEditor - languageServiceState.fileTreeParseCache - of + case Dict.get referenceRequest.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> Nothing @@ -996,7 +990,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = pos = ( referenceRequest.positionLineNumber, referenceRequest.positionColumn ) - maybeTopLevelDefinitionLocation : Maybe ( List String, DeclarationRange ) + maybeTopLevelDefinitionLocation : Maybe ( String, DeclarationRange ) maybeTopLevelDefinitionLocation = parsedFile.completionItems.fromTopLevel |> Common.listMapFind @@ -1013,7 +1007,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = declRangesName then Just - ( parsedFile.filePath + ( parsedFile.fileUri , decl.range ) @@ -1042,23 +1036,23 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = findReferences : - ( List String, Range ) + ( String, Range ) -> LanguageServiceState - -> List ( List String, List Range ) + -> List ( String, List Range ) findReferences ( targetDefinitionFilePath, targetDefinitionRange ) languageServiceState = let allParsedModules : List ParsedCookedModuleCache allParsedModules = List.concat - [ languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + [ languageServiceState.documentCache + |> Dict.toList |> List.filterMap (\( _, blob ) -> blob.parsedFileLastSuccess) , List.map .parseResult languageServiceState.coreModulesCache ] findReferencesInModule : ParsedCookedModuleCache - -> Maybe ( List String, List Range ) + -> Maybe ( String, List Range ) findReferencesInModule parsedModule = let { fromDeclarations } = @@ -1081,7 +1075,7 @@ findReferences ( targetDefinitionFilePath, targetDefinitionRange ) languageServi else Just - ( parsedModule.filePath + ( parsedModule.fileUri , ranges ) in @@ -1406,7 +1400,7 @@ importedModulesFromFile : -> LanguageServiceState -> List - { filePath : List String + { fileUri : String , canonicalName : List String , importedName : Elm.Syntax.ModuleName.ModuleName , parsedModule : Maybe ParsedCookedModuleCache @@ -1428,7 +1422,7 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = Elm.Syntax.Module.moduleName moduleDefinition in Just - { filePath = coreModule.parseResult.filePath + { fileUri = coreModule.parseResult.fileUri , canonicalName = canonicalName , importedName = canonicalName , parsedModule = Just coreModule.parseResult @@ -1477,7 +1471,7 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = Just parsedModule -> Just - { filePath = parsedModule.filePath + { fileUri = parsedModule.fileUri , canonicalName = canonicalName , importedName = importedName , parsedModule = Just parsedModule @@ -1491,8 +1485,8 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = modulesAvailableForImportFromState : LanguageServiceState -> List ParsedCookedModuleCache modulesAvailableForImportFromState languageServiceState = List.concat - [ languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + [ languageServiceState.documentCache + |> Dict.toList |> List.filterMap (\( _, fileCache ) -> fileCache.parsedFileLastSuccess @@ -1519,8 +1513,8 @@ importExposingsFromFile fileOpenedInEditor languageServiceState = importSyntax.moduleName in case - languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + languageServiceState.documentCache + |> Dict.toList |> Common.listMapFind (\( _, fileCache ) -> case fileCache.parsedFileLastSuccess of @@ -1962,10 +1956,12 @@ markdownElmCodeBlockFromCodeLines codeLines = updateLanguageServiceState : LanguageServiceInterface.FileTreeNode -> LanguageServiceState -> LanguageServiceState updateLanguageServiceState fileTree state = let + compileFileCacheEntry : ( String, LanguageServiceInterface.FileTreeBlobNode ) -> LanguageServiceStateFileTreeNodeBlob compileFileCacheEntry ( blobPath, fileTreeBlob ) = let + maybePreviousCached : Maybe LanguageServiceStateFileTreeNodeBlob maybePreviousCached = - state.fileTreeParseCache |> FileTree.getBlobAtPathFromFileTree blobPath + Dict.get blobPath state.documentCache buildNewEntry () = let @@ -1984,12 +1980,12 @@ updateLanguageServiceState fileTree state = Ok syntax -> Just - { filePath = blobPath + { fileUri = blobPath , text = asString , syntax = syntax , completionItems = completionItemsFromModule - { filePath = blobPath + { fileUri = blobPath , text = asString , syntax = syntax } @@ -2034,9 +2030,26 @@ updateLanguageServiceState fileTree state = else buildNewEntry () + + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + fileTree + |> FileTree.flatListOfBlobsFromFileTreeNode + |> List.map + (\( filePath, fileContent ) -> + let + filePathFlat : String + filePathFlat = + String.join "/" filePath + in + ( filePathFlat + , compileFileCacheEntry ( filePathFlat, fileContent ) + ) + ) + |> Dict.fromList in { state - | fileTreeParseCache = FileTree.mapBlobsWithPath compileFileCacheEntry fileTree + | documentCache = documentCache } diff --git a/implement/pine/Elm/elm-compiler/src/LanguageServiceInterface.elm b/implement/pine/Elm/elm-compiler/src/LanguageServiceInterface.elm index 49011db1..f2e7aae3 100644 --- a/implement/pine/Elm/elm-compiler/src/LanguageServiceInterface.elm +++ b/implement/pine/Elm/elm-compiler/src/LanguageServiceInterface.elm @@ -38,12 +38,12 @@ type alias RequestInWorkspace = type Request - = AddFileRequest (List String) FileTreeBlobNode - | DeleteFileRequest (List String) + = AddFileRequest String FileTreeBlobNode + | DeleteFileRequest String | ProvideHoverRequest ProvideHoverRequestStruct | ProvideCompletionItemsRequest ProvideCompletionItemsRequestStruct | ProvideDefinitionRequest ProvideDefinitionRequestStruct - | TextDocumentSymbolRequest (List String) + | TextDocumentSymbolRequest String | TextDocumentReferencesRequest ProvideReferencesRequestStruct | TextDocumentRenameRequest RenameParams @@ -59,14 +59,14 @@ type Response type alias ProvideHoverRequestStruct = - { filePathOpenedInEditor : List String + { filePathOpenedInEditor : String , positionLineNumber : Int , positionColumn : Int } type alias ProvideCompletionItemsRequestStruct = - { filePathOpenedInEditor : List String + { filePathOpenedInEditor : String , cursorLineNumber : Int , cursorColumn : Int } @@ -81,7 +81,7 @@ type alias ProvideReferencesRequestStruct = type alias RenameParams = - { filePath : List String + { filePath : String , positionLineNumber : Int , positionColumn : Int , newName : String @@ -89,7 +89,7 @@ type alias RenameParams = type alias LocationUnderFilePath = - { filePath : List String + { filePath : String , range : Frontend.MonacoEditor.MonacoRange } @@ -130,7 +130,7 @@ type alias WorkspaceEdit = type alias TextDocumentEdit = - { filePath : List String + { filePath : String , edits : List TextEdit } diff --git a/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageService.elm b/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageService.elm index 59a1f095..7f377093 100644 --- a/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageService.elm +++ b/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageService.elm @@ -5,6 +5,7 @@ These functions enable features like completion suggestions and hover tips in th -} import Common +import Dict import Elm.Parser import Elm.Syntax.Comments import Elm.Syntax.Declaration @@ -26,14 +27,14 @@ import List.Extra type alias LanguageServiceState = - { fileTreeParseCache : FileTree.FileTreeNode LanguageServiceStateFileTreeNodeBlob + { documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob , coreModulesCache : List ElmCoreModule } type alias LanguageServiceStateFileTreeNodeBlob = { {- Avoid bug in Elm core library as reported at https://github.com/elm/bytes/issues/15 : - Convert to other representation before comparing. + Convert to other representation for equality check. -} sourceBase64 : String , textContent : Maybe FileTextContent @@ -48,14 +49,14 @@ type alias FileTextContent = type alias ParsedModuleCache = - { filePath : List String + { fileUri : String , text : String , syntax : Elm.Syntax.File.File } type alias ParsedCookedModuleCache = - { filePath : List String + { fileUri : String , text : String , syntax : Elm.Syntax.File.File , completionItems : ModuleCompletionItems @@ -96,7 +97,7 @@ type CookedDocumentation type LocationUnderFilePath range - = LocationUnderFilePath (List String) range + = LocationUnderFilePath String range type alias ModuleCompletionItems = @@ -152,12 +153,12 @@ initLanguageServiceState elmCoreModules = |> Maybe.map (\syntax -> { parseResult = - { filePath = [ "elm-core" ] + { fileUri = "elm-core" , text = coreModule.moduleText , syntax = syntax , completionItems = completionItemsFromModule - { filePath = [ "elm-core" ] + { fileUri = "elm-core" , text = coreModule.moduleText , syntax = syntax } @@ -167,7 +168,7 @@ initLanguageServiceState elmCoreModules = ) ) in - { fileTreeParseCache = FileTree.TreeNode [] + { documentCache = Dict.empty , coreModulesCache = elmCoreModulesParseResults } @@ -194,21 +195,19 @@ handleRequestInCurrentWorkspace request stateBefore = let ( serviceResponse, state ) = case request of - LanguageServiceInterface.AddFileRequest filePath content -> - addFile filePath content stateBefore + LanguageServiceInterface.AddFileRequest fileUri fileContent -> + addFile ( fileUri, fileContent ) stateBefore - LanguageServiceInterface.DeleteFileRequest filePath -> + LanguageServiceInterface.DeleteFileRequest fileUri -> let - newFileTree = - case FileTree.removeNodeAtPath filePath stateBefore.fileTreeParseCache of - Nothing -> - stateBefore.fileTreeParseCache - - Just afterRemove -> - afterRemove + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + Dict.remove fileUri stateBefore.documentCache in ( LanguageServiceInterface.WorkspaceSummaryResponse - , { stateBefore | fileTreeParseCache = newFileTree } + , { stateBefore + | documentCache = documentCache + } ) LanguageServiceInterface.ProvideHoverRequest provideHoverRequest -> @@ -271,19 +270,20 @@ handleRequestInCurrentWorkspace request stateBefore = addFile : - List String - -> LanguageServiceInterface.FileTreeBlobNode + ( String + , LanguageServiceInterface.FileTreeBlobNode + ) -> LanguageServiceState -> ( LanguageServiceInterface.Response, LanguageServiceState ) -addFile filePath content stateBefore = +addFile ( fileUri, fileContent ) stateBefore = let maybePreviousCached : Maybe LanguageServiceStateFileTreeNodeBlob maybePreviousCached = - FileTree.getBlobAtPathFromFileTree filePath stateBefore.fileTreeParseCache + Dict.get fileUri stateBefore.documentCache maybeTextContent : Maybe FileTextContent maybeTextContent = - case content.asText of + case fileContent.asText of Nothing -> Nothing @@ -296,12 +296,12 @@ addFile filePath content stateBefore = Ok syntax -> Just - { filePath = filePath + { fileUri = fileUri , text = asString , syntax = syntax , completionItems = completionItemsFromModule - { filePath = filePath + { fileUri = fileUri , text = asString , syntax = syntax } @@ -335,20 +335,20 @@ addFile filePath content stateBefore = Just parsedFile -> Just parsedFile - newFileTree : FileTree.FileTreeNode LanguageServiceStateFileTreeNodeBlob - newFileTree = - FileTree.setNodeAtPathInSortedFileTree - ( filePath - , FileTree.BlobNode - { sourceBase64 = content.asBase64 - , textContent = maybeTextContent - , parsedFileLastSuccess = parsedFileLastSuccess - } - ) - stateBefore.fileTreeParseCache + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + Dict.insert + fileUri + { sourceBase64 = fileContent.asBase64 + , textContent = maybeTextContent + , parsedFileLastSuccess = parsedFileLastSuccess + } + stateBefore.documentCache in ( LanguageServiceInterface.WorkspaceSummaryResponse - , { stateBefore | fileTreeParseCache = newFileTree } + , { stateBefore + | documentCache = documentCache + } ) @@ -359,7 +359,7 @@ provideHover : -> LanguageServiceState -> List String provideHover request languageServiceState = - case languageServiceState.fileTreeParseCache |> FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -389,7 +389,7 @@ provideHover request languageServiceState = type alias ImportedModule = - { filePath : List String + { fileUri : String , canonicalName : List String , importedName : Elm.Syntax.ModuleName.ModuleName , parsedModule : Maybe ParsedCookedModuleCache @@ -530,7 +530,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = ( completionItemLabel , ( maybeFilterRange , LocationUnderFilePath - parsedModule.filePath + parsedModule.fileUri completionItemRange , completionItem ) @@ -578,7 +578,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = if itemInsertText == nameInModule && item.isExposed then Just ( LocationUnderFilePath - referencedModule.filePath + referencedModule.fileUri item.range , itemDocumentation ) @@ -642,7 +642,7 @@ hoverItemsFromParsedModule parsedModule languageServiceState = in [ ( rangeModulePart , LocationUnderFilePath - referencedModule.filePath + referencedModule.fileUri (DeclarationRange rangeModulePart []) , documentation ) @@ -730,10 +730,7 @@ provideCompletionItems : -> LanguageServiceState -> List Frontend.MonacoEditor.MonacoCompletionItem provideCompletionItems request languageServiceState = - case - FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor - languageServiceState.fileTreeParseCache - of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -822,7 +819,7 @@ provideDefinitionInternal : -> LanguageServiceState -> List (LocationUnderFilePath DeclarationRange) provideDefinitionInternal request languageServiceState = - case FileTree.getBlobAtPathFromFileTree request.filePathOpenedInEditor languageServiceState.fileTreeParseCache of + case Dict.get request.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> [] @@ -852,11 +849,11 @@ provideDefinitionInternal request languageServiceState = textDocumentSymbol : - List String + String -> LanguageServiceState -> List LanguageServiceInterface.DocumentSymbol -textDocumentSymbol filePath languageServiceState = - case FileTree.getBlobAtPathFromFileTree filePath languageServiceState.fileTreeParseCache of +textDocumentSymbol fileUri languageServiceState = + case Dict.get fileUri languageServiceState.documentCache of Nothing -> [] @@ -948,7 +945,7 @@ textDocumentReferences referenceRequest languageServiceState = textDocumentReferencesGroupedByFilePath : LanguageServiceInterface.ProvideReferencesRequestStruct -> LanguageServiceState - -> Maybe ( ( List String, DeclarationRange ), List ( List String, List Range ) ) + -> Maybe ( ( String, DeclarationRange ), List ( String, List Range ) ) textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = let maybeDefinition : Maybe (LocationUnderFilePath DeclarationRange) @@ -967,7 +964,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = (DeclarationRange definitionLocationRangeWhole _) = definitionLocationRange - references : List ( List String, List Range ) + references : List ( String, List Range ) references = findReferences ( definitionLocationFilePath, definitionLocationRangeWhole ) languageServiceState in @@ -978,10 +975,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = Nothing -> -- Fallback: try to find a top-level declaration covering this position - case - FileTree.getBlobAtPathFromFileTree referenceRequest.filePathOpenedInEditor - languageServiceState.fileTreeParseCache - of + case Dict.get referenceRequest.filePathOpenedInEditor languageServiceState.documentCache of Nothing -> Nothing @@ -996,7 +990,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = pos = ( referenceRequest.positionLineNumber, referenceRequest.positionColumn ) - maybeTopLevelDefinitionLocation : Maybe ( List String, DeclarationRange ) + maybeTopLevelDefinitionLocation : Maybe ( String, DeclarationRange ) maybeTopLevelDefinitionLocation = parsedFile.completionItems.fromTopLevel |> Common.listMapFind @@ -1013,7 +1007,7 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = declRangesName then Just - ( parsedFile.filePath + ( parsedFile.fileUri , decl.range ) @@ -1042,23 +1036,23 @@ textDocumentReferencesGroupedByFilePath referenceRequest languageServiceState = findReferences : - ( List String, Range ) + ( String, Range ) -> LanguageServiceState - -> List ( List String, List Range ) + -> List ( String, List Range ) findReferences ( targetDefinitionFilePath, targetDefinitionRange ) languageServiceState = let allParsedModules : List ParsedCookedModuleCache allParsedModules = List.concat - [ languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + [ languageServiceState.documentCache + |> Dict.toList |> List.filterMap (\( _, blob ) -> blob.parsedFileLastSuccess) , List.map .parseResult languageServiceState.coreModulesCache ] findReferencesInModule : ParsedCookedModuleCache - -> Maybe ( List String, List Range ) + -> Maybe ( String, List Range ) findReferencesInModule parsedModule = let { fromDeclarations } = @@ -1081,7 +1075,7 @@ findReferences ( targetDefinitionFilePath, targetDefinitionRange ) languageServi else Just - ( parsedModule.filePath + ( parsedModule.fileUri , ranges ) in @@ -1406,7 +1400,7 @@ importedModulesFromFile : -> LanguageServiceState -> List - { filePath : List String + { fileUri : String , canonicalName : List String , importedName : Elm.Syntax.ModuleName.ModuleName , parsedModule : Maybe ParsedCookedModuleCache @@ -1428,7 +1422,7 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = Elm.Syntax.Module.moduleName moduleDefinition in Just - { filePath = coreModule.parseResult.filePath + { fileUri = coreModule.parseResult.fileUri , canonicalName = canonicalName , importedName = canonicalName , parsedModule = Just coreModule.parseResult @@ -1477,7 +1471,7 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = Just parsedModule -> Just - { filePath = parsedModule.filePath + { fileUri = parsedModule.fileUri , canonicalName = canonicalName , importedName = importedName , parsedModule = Just parsedModule @@ -1491,8 +1485,8 @@ importedModulesFromFile fileOpenedInEditor languageServiceState = modulesAvailableForImportFromState : LanguageServiceState -> List ParsedCookedModuleCache modulesAvailableForImportFromState languageServiceState = List.concat - [ languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + [ languageServiceState.documentCache + |> Dict.toList |> List.filterMap (\( _, fileCache ) -> fileCache.parsedFileLastSuccess @@ -1519,8 +1513,8 @@ importExposingsFromFile fileOpenedInEditor languageServiceState = importSyntax.moduleName in case - languageServiceState.fileTreeParseCache - |> FileTree.flatListOfBlobsFromFileTreeNode + languageServiceState.documentCache + |> Dict.toList |> Common.listMapFind (\( _, fileCache ) -> case fileCache.parsedFileLastSuccess of @@ -1962,10 +1956,12 @@ markdownElmCodeBlockFromCodeLines codeLines = updateLanguageServiceState : LanguageServiceInterface.FileTreeNode -> LanguageServiceState -> LanguageServiceState updateLanguageServiceState fileTree state = let + compileFileCacheEntry : ( String, LanguageServiceInterface.FileTreeBlobNode ) -> LanguageServiceStateFileTreeNodeBlob compileFileCacheEntry ( blobPath, fileTreeBlob ) = let + maybePreviousCached : Maybe LanguageServiceStateFileTreeNodeBlob maybePreviousCached = - state.fileTreeParseCache |> FileTree.getBlobAtPathFromFileTree blobPath + Dict.get blobPath state.documentCache buildNewEntry () = let @@ -1984,12 +1980,12 @@ updateLanguageServiceState fileTree state = Ok syntax -> Just - { filePath = blobPath + { fileUri = blobPath , text = asString , syntax = syntax , completionItems = completionItemsFromModule - { filePath = blobPath + { fileUri = blobPath , text = asString , syntax = syntax } @@ -2034,9 +2030,26 @@ updateLanguageServiceState fileTree state = else buildNewEntry () + + documentCache : Dict.Dict String LanguageServiceStateFileTreeNodeBlob + documentCache = + fileTree + |> FileTree.flatListOfBlobsFromFileTreeNode + |> List.map + (\( filePath, fileContent ) -> + let + filePathFlat : String + filePathFlat = + String.join "/" filePath + in + ( filePathFlat + , compileFileCacheEntry ( filePathFlat, fileContent ) + ) + ) + |> Dict.fromList in { state - | fileTreeParseCache = FileTree.mapBlobsWithPath compileFileCacheEntry fileTree + | documentCache = documentCache } diff --git a/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageServiceInterface.elm b/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageServiceInterface.elm index 49011db1..f2e7aae3 100644 --- a/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageServiceInterface.elm +++ b/implement/test-and-train/elm-interactive-scenarios-train/elm-compiler-dependencies/context-app/src/LanguageServiceInterface.elm @@ -38,12 +38,12 @@ type alias RequestInWorkspace = type Request - = AddFileRequest (List String) FileTreeBlobNode - | DeleteFileRequest (List String) + = AddFileRequest String FileTreeBlobNode + | DeleteFileRequest String | ProvideHoverRequest ProvideHoverRequestStruct | ProvideCompletionItemsRequest ProvideCompletionItemsRequestStruct | ProvideDefinitionRequest ProvideDefinitionRequestStruct - | TextDocumentSymbolRequest (List String) + | TextDocumentSymbolRequest String | TextDocumentReferencesRequest ProvideReferencesRequestStruct | TextDocumentRenameRequest RenameParams @@ -59,14 +59,14 @@ type Response type alias ProvideHoverRequestStruct = - { filePathOpenedInEditor : List String + { filePathOpenedInEditor : String , positionLineNumber : Int , positionColumn : Int } type alias ProvideCompletionItemsRequestStruct = - { filePathOpenedInEditor : List String + { filePathOpenedInEditor : String , cursorLineNumber : Int , cursorColumn : Int } @@ -81,7 +81,7 @@ type alias ProvideReferencesRequestStruct = type alias RenameParams = - { filePath : List String + { filePath : String , positionLineNumber : Int , positionColumn : Int , newName : String @@ -89,7 +89,7 @@ type alias RenameParams = type alias LocationUnderFilePath = - { filePath : List String + { filePath : String , range : Frontend.MonacoEditor.MonacoRange } @@ -130,7 +130,7 @@ type alias WorkspaceEdit = type alias TextDocumentEdit = - { filePath : List String + { filePath : String , edits : List TextEdit } diff --git a/implement/test-elm-time/ElmLanguageServiceTests.cs b/implement/test-elm-time/ElmLanguageServiceTests.cs index 8b489ff7..9d53faca 100644 --- a/implement/test-elm-time/ElmLanguageServiceTests.cs +++ b/implement/test-elm-time/ElmLanguageServiceTests.cs @@ -192,7 +192,7 @@ private static void AssertHover( var hoverRequest = new Pine.Elm.LanguageServiceInterface.ProvideHoverRequestStruct( - FilePathOpenedInEditor: filePathOpenedInEditor, + FilePathOpenedInEditor: string.Join("/", filePathOpenedInEditor), PositionLineNumber: beforeCursorLines.Length, PositionColumn: beforeCursorLines.Last().Length); @@ -221,7 +221,7 @@ private static void MutateServiceAddingFiles( var addFileResult = languageServiceState.HandleRequest( new Pine.Elm.LanguageServiceInterface.Request.AddFileRequest( - FilePath: file.path, + FilePath: string.Join("/", file.path), Blob: new Pine.Elm.LanguageServiceInterface.FileTreeBlobNode( AsBase64: asBase64, AsText: asText))); @@ -285,7 +285,7 @@ private static void AssertCompletionItems( var completionItemsRequest = new Pine.Elm.LanguageServiceInterface.ProvideCompletionItemsRequestStruct( - FilePathOpenedInEditor: filePathOpenedInEditor, + FilePathOpenedInEditor: string.Join("/", filePathOpenedInEditor), CursorLineNumber: beforeCursorLines.Length, CursorColumn: beforeCursorLines.Last().Length + 1);