Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add configurations and notes for Astro LS #43

Merged
merged 5 commits into from
Sep 12, 2024
Merged

Conversation

S0AndS0
Copy link
Contributor

@S0AndS0 S0AndS0 commented Sep 1, 2024

⚠️ The install.py script is untested as I've a non-standard way of organizing my .vim stuff, but am somewhat confident things should function as advertised as I'm now enjoying Astro LSP via shared YouCompleteMe integrations :-D


This change is Reviewable

@S0AndS0
Copy link
Contributor Author

S0AndS0 commented Sep 2, 2024

Additional thoughts;

It might be wise to explore setting a fallback to user scoped path for installed typescript.tsdk dependency within the .ycm_extra_conf.py file. But I'm not certain how best to clue Astro LS in on how to find the other dependencies (namely; prettier, prettier-plugin-astro, @astrojs/ts-plugin) in those sorts of situations.

Warnings

  • I'm yoinking configurations from @astro/ts-plugin into the ReadMe file about adding @astrojs/ts-plugin to a project's development dependencies and tsconfig.json file. If it fits in this PR, groovy, if not then I'm happy to submit a follow-up Pull Request.
  • I'm seeing some errors popping when YCM tries to get completions from the Astro LS, eg. when the cursor is after the period of some input such as myArray. within a Vim buffer... so this PR may not be a full-feature/stable change!
    2024-09-02 10:26:24,236 - ERROR - Exception from semantic completer (using general)
    Traceback (most recent call last):
      File "/home/USER/.vim/plugged/YouCompleteMe/third_party/ycmd/ycmd/handlers.py", line 116, in GetCompletions
        completions = filetype_completer.ComputeCandidates( request_data )
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/USER/.vim/plugged/YouCompleteMe/third_party/ycmd/ycmd/completers/completer.py", line 303, in ComputeCandidates
        candidates = self._GetCandidatesFromSubclass( request_data )
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/USER/.vim/plugged/YouCompleteMe/third_party/ycmd/ycmd/completers/language_server/language_server_completer.py", line 1336, in _GetCandidatesFromSubclass
        raw_completions, is_incomplete = self.ComputeCandidatesInner( request_data,
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/USER/.vim/plugged/YouCompleteMe/third_party/ycmd/ycmd/completers/language_server/language_server_completer.py", line 1321, in ComputeCandidatesInner
        return ( self._CandidatesFromCompletionItems(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/USER/.vim/plugged/YouCompleteMe/third_party/ycmd/ycmd/completers/language_server/language_server_completer.py", line 1458, in _CandidatesFromCompletionItems
        _InsertionTextForItem( request_data, item ) )
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/USER/.vim/plugged/YouCompleteMe/third_party/ycmd/ycmd/completers/language_server/language_server_completer.py", line 3178, in _InsertionTextForItem
        assert lsp.INSERT_TEXT_FORMAT[
               ^^^^^^^^^^^^^^^^^^^^^^^
    AssertionError
    

Copy link
Contributor

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, switching to Reviewable, for the "big guns" review!

First, thanks a lot for contributing.

AssertionError

Yikes... That means the server is being an asshole not respecting our client capabilities. Its completion texts are snippets (think UltiSnips) rather than plain text.
That's a bug in the server. We've seen so... so... so many servers that disrespect client capabilities.
You could turn on debug logging and then report the bug.
Sometimes the bug is solved immediately, as was the case with haskell.
Other times the bug just accumulates dust.

Usually this repo's README mentions this kind of problems.

I'm yoinking configurations from @astro/ts-plugin into the ReadMe file about adding @astrojs/ts-plugin to a project's development dependencies and tsconfig.json file. If it fits in this PR, groovy, if not then I'm happy to submit a follow-up Pull Request.

It's fine to keep it in this pull request.

 

Finally, the only reason I've not yet approved this pull request is because I don't yet want to close the conversations on Reviewable. Not that I see any actual blockers.

Reviewed 3 of 4 files at r1, 1 of 1 files at r2, all commit messages.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @S0AndS0)


README.md line 367 at r2 (raw file):

            'ls': {
                'typescript': {
                    'tsdk':  "{}/node_modules/typescript/lib".format(os.path.abspath(os.path.curdir)),

Is this correct? Did you really mean curdir, as in $PWD, or did you rather mean "dir of this script" and assumed that .ycm_extra_conf.py would be in project root?


astro/snippet.vim line 5 at r1 (raw file):

Previously, S0AndS0 wrote…

Short answer; I'm not sure, here's the output of ls -1 after a mostly fresh Astro project initialization;

astro.config.mjs
node_modules
package.json
package-lock.json
public
README.md
src
tsconfig.json

... But am thinking the astro.conf.mjs and tsconfig.json files may be important to the Astro Language Server.

Slightly longer answer;

  • Official documentation is a bit sparse as to what else it may want
  • ⚠️ I did spot the @astro/ts-plugin may be an additional recommended ritual to add to npm init tasks
  • Configurations for NeoVim's Mason LSP plugin seem to match requiring only the typescript.tsdk directory
  • Searching for Vim Issues and skimming results didn't expose any additional requirements or suggestions beyond requiring the typescript.tsdk directory
  • With the advertised configurations YcmToggleLogs logs don't show any complaints, warnings, or notifications related to searching-out additional files;
    2024-09-02 09:45:06,153 - INFO - Completion config: 50, detailing 0 candiates
    2024-09-02 09:45:06,153 - INFO - Completion config: 50, detailing 0 candiates
    2024-09-02 09:45:06,153 - INFO - Completion config: 50, detailing 0 candiates
    2024-09-02 09:45:06,153 - INFO - Completion config: 50, detailing 0 candiates
    127.0.0.1 - - [02/Sep/2024 09:45:06] "GET /ready HTTP/1.1" 200 4
    2024-09-02 09:45:06,164 - INFO - Initializing generic LSP completer with: {'name': 'astro', 'cmdline': ['/home/USER/git/hub/ycm-core/lsp-examples/astro/node_modules/@astrojs/language-server/bin/nodeServer.js', '--stdio'], 'filetypes': ['astro']}
    2024-09-02 09:45:06,164 - INFO - Completion config: 50, detailing 0 candiates
    127.0.0.1 - - [02/Sep/2024 09:45:06] "GET /signature_help_available?subserver=astro HTTP/1.1" 200 23
    127.0.0.1 - - [02/Sep/2024 09:45:06] "POST /event_notification HTTP/1.1" 200 2
    2024-09-02 09:45:06,383 - INFO - Adding buffer identifiers for file: /home/USER/git/hub/ORG/REPO/src/components/example.astro
    127.0.0.1 - - [02/Sep/2024 09:45:06] "POST /receive_messages HTTP/1.1" 200 5
    2024-09-02 09:45:06,389 - INFO - Starting astroCompleter: ['/home/USER/git/hub/ycm-core/lsp-examples/astro/node_modules/@astrojs/language-server/bin/nodeServer.js', '--stdio']
    2024-09-02 09:45:06,393 - INFO - astroCompleter started with PID 10008
    127.0.0.1 - - [02/Sep/2024 09:45:06] "POST /event_notification HTTP/1.1" 200 2
    127.0.0.1 - - [02/Sep/2024 09:45:06] "POST /semantic_completion_available HTTP/1.1" 200 4
    2024-09-02 09:45:10,393 - INFO - astro: Language server requires resolve request
    2024-09-02 09:45:10,393 - INFO - astro: Language server requires sync type of Incremental
    2024-09-02 09:45:10,393 - INFO - astro: Using trigger characters for semantic triggers: .,:,<,",=,/,-,>,+,^,*,(,),#,[,],$,@,{,},',`, 
    2024-09-02 09:45:10,394 - INFO - astro: Using characters for signature triggers: (,,,<
    127.0.0.1 - - [02/Sep/2024 09:45:10] "POST /receive_messages HTTP/1.1" 200 4
    2024-09-02 09:45:10,403 - WARNING - Server reported: Inlay hint refresh is not supported by the client.
    2024-09-02 09:45:10,403 - WARNING - Server reported: Semantic tokens refresh is not supported by the client.
    127.0.0.1 - - [02/Sep/2024 09:45:13] "POST /receive_messages HTTP/1.1" 200 117
    127.0.0.1 - - [02/Sep/2024 09:45:13] "POST /receive_messages HTTP/1.1" 200 117
    127.0.0.1 - - [02/Sep/2024 09:45:23] "POST /receive_messages HTTP/1.1" 200 4
    127.0.0.1 - - [02/Sep/2024 09:45:33] "POST /receive_messages HTTP/1.1" 200 4
    127.0.0.1 - - [02/Sep/2024 09:45:43] "POST /receive_messages HTTP/1.1" 200 4
    127.0.0.1 - - [02/Sep/2024 09:45:44] "POST /debug_info HTTP/1.1" 200 1121
    127.0.0.1 - - [02/Sep/2024 09:45:46] "POST /receive_messages HTTP/1.1" 200 5
    127.0.0.1 - - [02/Sep/2024 09:45:47] "POST /debug_info HTTP/1.1" 200 1121
    127.0.0.1 - - [02/Sep/2024 09:45:49] "POST /debug_info HTTP/1.1" 200 1121
    127.0.0.1 - - [02/Sep/2024 09:45:53] "POST /receive_messages HTTP/1.1" 200 4
    127.0.0.1 - - [02/Sep/2024 09:45:54] "POST /debug_info HTTP/1.1" 200 1121
    127.0.0.1 - - [02/Sep/2024 09:46:03] "POST /receive_messages HTTP/1.1" 200 4
    2024-09-02 09:47:19,276 - INFO - No support for ExecuteCommand command in server for astro
    2024-09-02 09:47:19,277 - INFO - Found codeActionProvider support for command FixIt in astro
    2024-09-02 09:47:19,277 - INFO - Found definitionProvider support for command GoToDefinition in astro
    2024-09-02 09:47:19,277 - INFO - Found definitionProvider support for command GoToDeclaration in astro
    2024-09-02 09:47:19,277 - INFO - Found definitionProvider support for command GoTo in astro
    2024-09-02 09:47:19,277 - INFO - Found typeDefinitionProvider support for command GoToType in astro
    2024-09-02 09:47:19,277 - INFO - Found implementationProvider support for command GoToImplementation in astro
    2024-09-02 09:47:19,277 - INFO - Found referencesProvider support for command GoToReferences in astro
    2024-09-02 09:47:19,277 - INFO - Found renameProvider support for command RefactorRename in astro
    2024-09-02 09:47:19,278 - INFO - Found documentFormattingProvider support for command Format in astro
    2024-09-02 09:47:19,278 - INFO - Found workspaceSymbolProvider support for command GoToSymbol in astro
    2024-09-02 09:47:19,278 - INFO - Found documentSymbolProvider support for command GoToDocumentOutline in astro
    2024-09-02 09:47:19,278 - INFO - Always supporting StopServer for astro
    2024-09-02 09:47:19,278 - INFO - Always supporting RestartServer for astro
    2024-09-02 09:47:19,278 - INFO - Always supporting GoToCallees for astro
    2024-09-02 09:47:19,278 - INFO - Always supporting GoToCallers for astro
    2024-09-02 09:47:19,278 - INFO - Always supporting CallHierarchy for astro
    2024-09-02 09:47:19,278 - INFO - Always supporting ResolveCallHierarchyItem for astro
    2024-09-02 09:47:19,278 - INFO - Always supporting GetHover for astro
    127.0.0.1 - - [02/Sep/2024 09:47:19] "POST /run_completer_command HTTP/1.1" 200 418
    127.0.0.1 - - [02/Sep/2024 09:47:19] "POST /receive_messages HTTP/1.1" 200 4
    

You are definitely in a better position to decide.
Maybe we can go with tsconfig.json for now and, if you realize that was wrong, you can come again with a new pull request.

@S0AndS0
Copy link
Contributor Author

S0AndS0 commented Sep 2, 2024

Okay, switching to Reviewable, for the "big guns" review!

First, thanks a lot for contributing.

Woot... And welcome for sure ya be, and thanks for maintaining the tools that make my dev experience better!

You could turn on debug logging and then report the bug.

🤦 oh good call, I've enabled the following in my .vimrc stuff;

let g:ycm_debug_info = 1
let g:ycm_verbose_logs = 1
let g:ycm_log_level = 'debug'

... and if there are any other toggles I should switch then please do let me know, as I'll soon be collecting additional data for the Astro LS team.

Sometimes the bug is solved immediately, as was the case with haskell.
Other times the bug just accumulates dust.

After turning-on the above log toggles, and trying to inspect the JSON Astro LS is shipping, it certainly looks to be a bug or maybe a small nest of 'em!

  • result.items[0]
{
  "label": "title.",
  "textEdit": {
    "range": {
      "start": {
        "line": 8,
        "character": 10
      },
      "end": {
        "line": 8,
        "character": 16
      }
    },
    "newText": "<title class=\\"${1}\\">${0}</title>"
    //> ------------------------^ error| Expected comma [514]
    //> -------------------------^ error| Colon expected [515]
    //> --------------------------^ ...
  },
  "documentation": "<title class=\\"|\\">|</title>",
    //> ----------------------------^ error| Expected comma [514]
    //> -----------------------------^ error| Colon expected [515]
    //> ------------------------------^ ...
  "insertTextFormat": 2,
  "detail": "Emmet Abbreviation"
}

... Near as I can tell, after some fiddling about, is the double backslashes may need to be replaced with singles. Because after doing that tools like Prettier were happy to parse the whole mess.


It's fine to keep it in this pull request.

Super, I think GH did that automatically, but feel free to holler at me if not.


Finally, the only reason I've not yet approved this pull request is because I don't yet want to close the conversations on Reviewable.
Not that I see any actual blockers.

No worries, I ain't in any hurries!... After all this is your sandbox I be playing in ;-D


README.md line 367 at r2 (raw file):

            'ls': {
                'typescript': {
                    'tsdk':  "{}/node_modules/typescript/lib".format(os.path.abspath(os.path.curdir)),

Here's the abiged payload sent during Astro LS initalization;

{
  "params": {
        "...": "...",
    "initializationOptions": {
      "typescript": {
        "tsdk": "/home/USER/git/hub/ORG/REPO/node_modules/typescript/lib"
      }
    },
    "...": "..."
}

... Seems, "{}/node_modules/typescript/lib".format(os.path.abspath(os.path.curdir)), so long as Vim is started in the root of a repo, should map to the abbsolute path for that project's Node modules directory.

It might be possible to just define node_modules/typescript/lib instead;

                 'typescript': {
-                    'tsdk':  "{}/node_modules/typescript/lib".format(os.path.abspath(os.path.curdir)),
+                    'tsdk':  "node_modules/typescript/lib",
                 },

... because latest tests show that didn't cause the server to barf any new errors 🎉


astro/snippet.vim line 5 at r1 (raw file):

...

You are definitely in a better position to decide.

Maybe we can go with tsconfig.json for now and, if you realize that was wrong, you can come again with a new pull request.

To be super safe I'll be adding 'em both when collecting and preparing data for the eventual bug report to the Astro LS team;

 let g:ycm_language_server += [
   \   {
   \     'name': 'astro',
   \     'filetypes': [ 'astro' ],
   \     'cmdline': [  expand( g:ycm_lsp_dir . '/astro/node_modules/@astrojs/language-server/bin/nodeServer.js' ), '--stdio' ],
+  \     'project_root_files': [ 'tsconfig.json', 'astro.config.mjs' ]
   \   },
   \ ]

... and so far I've not seen the language server throw any new errors because of the above additions.

Copy link
Contributor

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦 oh good call, I've enabled the following in my .vimrc stuff;

let g:ycm_debug_info = 1
let g:ycm_verbose_logs = 1
let g:ycm_log_level = 'debug'

... and if there are any other toggles I should switch then please do let me know, as I'll soon be collecting additional data for the Astro LS team.

Only the last one is actually recognized by YCM and it is all you need for debug logs.

As for reporting the bug, I don't think they'd care about vim config. Rather the messages exchanged between their server and our client - the ycmd stderr log, but just the TX and RX lines.
Also, their own stderr, if it contains anything.

Oh and the protocol specification is here: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/

After turning-on the above log toggles, and trying to inspect the JSON Astro LS is shipping, it certainly looks to be a bug or maybe a small nest of 'em!

Yeah... what you have pasted does not look like a valid json, but I think that's just an artifact of printing json. Else you'd have seen some JSONDecodeError somewhere. Possibly caught and shipped to YCM and then printed in the YCM stderr log.
Unlikely, though.
Still...

"insertTextFormat": 2

That means the type of insertion text is snippet - the thing YCM does not support.

@puremourning Had a branch in his fork for YCM/ycmd to support snippets. Neither of us were a fan of non-manually-triggered snippet completion.

"newText": "<title class=\\"${1}\\"\>${0}</title>"

Ignoring the extra backslashes, that newText is a snippet with two "stops".

Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @S0AndS0)


README.md line 367 at r2 (raw file):

so long as Vim is started in the root of a repo

That was exactly my point. It's wrong if vim is not started in the root of a repo.

On the other hand, .ycm_extra_conf.py is meant to go into the root of the repo. Then you can do something like this:

import pathlib
DIR_OF_THIS_SCRIPT=pathlib.Path(__file__).absolute().parent
TSDK_PATH=DIR_OF_THIS_SCRIPT / 'node_modules' / 'typescript' / 'lib'

...

'typescript': {
    'tsdk': str(TSDK_PATH)
}

The blessing (curse?) of having a turing complete language for config.

To be super safe I'll be adding 'em both when collecting and preparing data for the eventual bug report to the Astro LS team;

Fine with me. You can keep an eye on :YcmDebugInfo, where you can find what YCM thinks is the root of the project.

@S0AndS0
Copy link
Contributor Author

S0AndS0 commented Sep 2, 2024

As for reporting the bug, I don't think they'd care about vim config. Rather the messages exchanged between their server and our client - the ycmd stderr log, but just the TX and RX lines.
Also, their own stderr, if it contains anything.

Heh, standard error for the server be empty X-D ... And until they chime-in I'll likely not fiddle with any of the Astro LS code/configs

But I'll be sure to include a link to the Issue here and Pull Request there ;-D

Yeah... what you have pasted does not look like a valid json, but I think that's just an artifact of printing json. Else you'd have seen some JSONDecodeError somewhere. Possibly caught and shipped to YCM and then printed in the YCM stderr log.
Unlikely, though.
Still...

 "insertTextFormat": 2

That means the type of insertion text is snippet - the thing YCM does not support.

Turns out that was a bit of a red-herring caused by the Emmit plugin I had enabled 🤦

But disabling Emmit exposed what may be the real behavior causing the issue, near as I can tell there's something in the Astro LS stack that sees double-quotes and says, "oh I gotta escape that!", while totally disregarding that may escape a preexisting escape.

That was exactly my point. It's wrong if vim is not started in the root of a repo.

On the other hand, .ycm_extra_conf.py is meant to go into the root of the repo. Then you can do something like this:

...

The blessing (curse?) of having a turing complete language for config.

Uh-oh! I've been using a global-ish .ycm_extra_conf.py file, because I couldn't make the g:ycm_extra_conf_globlist configurations happy, eg.

let g:ycm_global_ycm_extra_conf = expand($HOME . '/git/hub/S0AndS0/configure-vim/dot-files/.ycm_extra_conf.py')

... Maybe a backwards walk of the current working directory that hunts for node_modules would allow for scenarios of starting a Vim session in a sub-directory and/or a repo level .ycm_extra_conf.py 🤔

Copy link
Contributor

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, standard error for the server be empty

Not unheard of. In LSP mode, the C# server uses client/logMessage requests to log to... wherever client decides.

snippets

Turns out that was a bit of a red-herring caused by the Emmit plugin I had enabled

Are you saying that disabling the Emmit plugin stops AstroLS from sending from sending snippets?
I still see a lot of snippets sent, in the ycmd stderr log that you have attached in the bug report.

I've been using a global-ish

You can certainly do that, but unless explicitly mentioned otherwise, our documentation is written with local extra confs in mind.
Users who use global (or "global-ish") extra confs should know enough to adapt.

Maybe a backwards walk of the current working directory that hunts for node_modules would allow for scenarios of starting a Vim session in a sub-directory and/or a repo level .ycm_extra_conf.py 🤔

I'd rather not. You'll find some unrelated node_modules and users might get angry if we do :cd behind their backs.

Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @S0AndS0)

Copy link
Contributor

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just checked a different server and see the "thing\\"" in completion items there as well.
It's definitely an artifact of ycmd logs.
Furthermore, they will only be interested in these lines from your log:

TX: Sending message: b'Content-Length: 1942\r\n\r\n{"id":1,"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"documentationFormat":["plaintext","markdown"],"resolveSupport":{"properties":["documentation","detail"]}},"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"documentSymbol":{"hierarchicalDocumentSymbolSupport":false,"labelSupport":false,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"hover":{"contentFormat":["plaintext","markdown"]},"inlay_hint":{},"semanticTokens":{"augmentSyntaxTokens":true,"formats":["relative"],"requests":{"full":{"delta":false},"range":true},"tokenModifiers":[],"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","method","member","macro","keyword","modifier","comment","string","number","regexp","operator"]},"signatureHelp":{"signatureInformation":{"documentationFormat":["plaintext","markdown"],"parameterInformation":{"labelOffsetSupport":true}}},"synchronization":{"didSave":true}},"workspace":{"applyEdit":true,"didChangeWatchedFiles":{"dynamicRegistration":true},"symbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"workspaceEdit":{"documentChanges":true},"workspaceFolders":true}},"initializationOptions":{"typescript":{"tsdk":"node_modules/typescript/lib"}},"processId":18517,"rootPath":"/home/NAME/git/hub/ORG/REPO","rootUri":"file:///home/NAME/git/hub/ORG/REPO","workspaceFolders":[{"name":"REPO","uri":"file:///home/NAME/git/hub/ORG/REPO"}]}}'
RX: Received message: b'{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":2,"message":"Inlay hint refresh is not supported by the client."}}'
RX: Received message: b'{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":2,"message":"Semantic tokens refresh is not supported by the client."}}'
RX: Received message: b'{"jsonrpc":"2.0","id":1,"result":{"capabilities":{"textDocumentSync":2,"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":true}},"selectionRangeProvider":true,"foldingRangeProvider":true,"linkedEditingRangeProvider":true,"colorProvider":true,"documentSymbolProvider":true,"documentFormattingProvider":true,"documentRangeFormattingProvider":true,"referencesProvider":true,"implementationProvider":true,"definitionProvider":true,"typeDefinitionProvider":true,"callHierarchyProvider":true,"hoverProvider":true,"documentHighlightProvider":true,"workspaceSymbolProvider":{},"renameProvider":{"prepareProvider":true},"documentLinkProvider":{},"codeLensProvider":{},"inlayHintProvider":{},"signatureHelpProvider":{"triggerCharacters":["(",",","<"],"retriggerCharacters":[")"]},"completionProvider":{"triggerCharacters":[".",":","<","\\"","=","/","-",">","+","^","*","(",")","#","[","]","$","@","{","}","\'","`"," "],"resolveProvider":true},"semanticTokensProvider":{"range":true,"full":false,"legend":{"tokenTypes":["namespace","class","enum","interface","typeParameter","type","parameter","variable","property","enumMember","function","method"],"tokenModifiers":["declaration","readonly","static","async","defaultLibrary","local"]}},"codeActionProvider":{"codeActionKinds":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.fixAll","source.organizeImports"],"resolveProvider":true},"documentOnTypeFormattingProvider":{"firstTriggerCharacter":";","moreTriggerCharacter":["}","\\n"]},"experimental":{"autoInsertionProvider":{"triggerCharacters":["=",">","/"],"configurationSections":[["html.autoCreateQuotes"],["html.autoClosingTags","javascript.autoClosingTags","typescript.autoClosingTags"],["html.autoClosingTags"]]},"fileRenameEditsProvider":true,"fileReferencesProvider":true}}}}'
TX: Sending notification: b'Content-Length: 52\r\n\r\n{"jsonrpc":"2.0","method":"initialized","params":{}}'
TX: Sending notification: b'Content-Length: 137\r\n\r\n{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"typescript":{"tsdk":"node_modules/typescript/lib"}}}}'
TX: Sending notification: b'Content-Length: 335\r\n\r\n{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"astro","text":"---\\ninterface Props {\\n\\ttitle: string;\\n}\\n\\nconst { title } = Astro.props;\\n---\\n\\n<strong>{ title }</strong>\\n\\n","uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","version":1}}}'
RX: Received message: b'{"jsonrpc":"2.0","id":0,"method":"client/registerCapability","params":{"registrations":[{"id":"7c6468e6-aebd-4597-af1c-353365c18f00","method":"workspace/didChangeWatchedFiles","registerOptions":{"watchers":[{"globPattern":"**/*.{js,cjs,mjs,ts,cts,mts,jsx,tsx,json,astro,vue,svelte}"}]}}]}}'
TX: Sending response: b'Content-Length: 38\r\n\r\n{"id":0,"jsonrpc":"2.0","result":null}'
RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","diagnostics":[],"version":1}}'
RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","diagnostics":[],"version":1}}'
TX: Sending notification: b'Content-Length: 345\r\n\r\n{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"---\\ninterface Props {\\n\\ttitle: string;\\n}\\n\\nconst { title } = Astro.props;\\ntitle.\\n---\\n\\n<strong>{ title }</strong>\\n\\n"}],"textDocument":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","version":2}}}'
TX: Sending message: b'Content-Length: 222\r\n\r\n{"id":2,"jsonrpc":"2.0","method":"textDocument/completion","params":{"position":{"character":6,"line":6},"textDocument":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro"}}}'
RX: Received message: b'{"jsonrpc":"2.0","id":2,"result":{"isIncomplete":false,"items":[{"label":"interface Props","kind":15,"labelDetails":{"description":"Create a new interface to type your props"},"documentation":{"kind":"markdown","value":"Create a new interface to type your props.\\n\\n\\n[Astro reference](https://docs.astro.build/en/guides/typescript/#component-props)"},"insertTextFormat":2,"filterText":"interface props","insertText":"interface Props {\\n\\t$1\\n}","data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{},"pluginIndex":8,"embeddedDocumentUri":"volar-embedded-content://html/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"getStaticPaths","kind":15,"labelDetails":{"description":"Create a new getStaticPaths function"},"documentation":{"kind":"markdown","value":"Create a new getStaticPaths function.\\n\\n\\n[Astro reference](https://docs.astro.build/en/reference/api-reference/#getstaticpaths)"},"insertText":"export const getStaticPaths = (() => {\\n\\t$1\\n\\treturn [];\\n}) satisfies GetStaticPaths;","additionalTextEdits":[{"range":{"start":{"line":8,"character":0},"end":{"line":8,"character":0}},"newText":"import type { GetStaticPaths } from \\"astro\\";\\n"}],"filterText":"getstaticpaths","insertTextFormat":2,"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"additionalTextEdits":[{"range":{"start":{"line":1,"character":0},"end":{"line":1,"character":0}},"newText":"import type { GetStaticPaths } from \\"astro\\";\\n"}]},"pluginIndex":8,"embeddedDocumentUri":"volar-embedded-content://html/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"prerender","kind":15,"labelDetails":{"description":"Add prerender export"},"documentation":{"kind":"markdown","value":"Add prerender export. When [using server-side rendering](https://docs.astro.build/en/guides/server-side-rendering/#enabling-ssr-in-your-project), this value will be used to determine whether to prerender the page or not.\\n\\n\\n[Astro reference](https://docs.astro.build/en/guides/server-side-rendering/#configuring-individual-routes)"},"insertText":"export const prerender = ${1|true,false,import.meta.env.|}","insertTextFormat":2,"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{},"pluginIndex":8,"embeddedDocumentUri":"volar-embedded-content://html/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"at","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".at","insertTextFormat":1,"filterText":".at","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".at"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".at"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"at"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"charAt","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".charAt","insertTextFormat":1,"filterText":".charAt","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".charAt"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".charAt"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"charAt"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"charCodeAt","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".charCodeAt","insertTextFormat":1,"filterText":".charCodeAt","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".charCodeAt"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".charCodeAt"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"charCodeAt"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"codePointAt","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".codePointAt","insertTextFormat":1,"filterText":".codePointAt","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".codePointAt"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".codePointAt"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"codePointAt"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"concat","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".concat","insertTextFormat":1,"filterText":".concat","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".concat"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".concat"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"concat"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"endsWith","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".endsWith","insertTextFormat":1,"filterText":".endsWith","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".endsWith"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".endsWith"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"endsWith"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"includes","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".includes","insertTextFormat":1,"filterText":".includes","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".includes"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".includes"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"includes"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"indexOf","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".indexOf","insertTextFormat":1,"filterText":".indexOf","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".indexOf"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".indexOf"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"indexOf"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"isWellFormed","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".isWellFormed","insertTextFormat":1,"filterText":".isWellFormed","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".isWellFormed"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".isWellFormed"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"isWellFormed"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"lastIndexOf","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".lastIndexOf","insertTextFormat":1,"filterText":".lastIndexOf","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".lastIndexOf"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".lastIndexOf"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"lastIndexOf"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"length","kind":5,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".length","insertTextFormat":1,"filterText":".length","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".length"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".length"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"length"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"localeCompare","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".localeCompare","insertTextFormat":1,"filterText":".localeCompare","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".localeCompare"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".localeCompare"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"localeCompare"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"match","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".match","insertTextFormat":1,"filterText":".match","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".match"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".match"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"match"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"matchAll","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".matchAll","insertTextFormat":1,"filterText":".matchAll","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".matchAll"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".matchAll"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"matchAll"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"normalize","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".normalize","insertTextFormat":1,"filterText":".normalize","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".normalize"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".normalize"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"normalize"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"padEnd","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".padEnd","insertTextFormat":1,"filterText":".padEnd","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".padEnd"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".padEnd"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"padEnd"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"padStart","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".padStart","insertTextFormat":1,"filterText":".padStart","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".padStart"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".padStart"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"padStart"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"repeat","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".repeat","insertTextFormat":1,"filterText":".repeat","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".repeat"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".repeat"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"repeat"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"replace","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".replace","insertTextFormat":1,"filterText":".replace","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".replace"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".replace"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"replace"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"replaceAll","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".replaceAll","insertTextFormat":1,"filterText":".replaceAll","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".replaceAll"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".replaceAll"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"replaceAll"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"search","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".search","insertTextFormat":1,"filterText":".search","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".search"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".search"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"search"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"slice","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".slice","insertTextFormat":1,"filterText":".slice","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".slice"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".slice"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"slice"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"split","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".split","insertTextFormat":1,"filterText":".split","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".split"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".split"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"split"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"startsWith","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".startsWith","insertTextFormat":1,"filterText":".startsWith","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".startsWith"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".startsWith"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"startsWith"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"substring","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".substring","insertTextFormat":1,"filterText":".substring","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".substring"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".substring"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"substring"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"Symbol","kind":6,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":"[Symbol]","insertTextFormat":1,"filterText":".[Symbol]","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":"[Symbol]"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"insert":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"replace":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":"[Symbol]"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"Symbol"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"toLocaleLowerCase","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".toLocaleLowerCase","insertTextFormat":1,"filterText":".toLocaleLowerCase","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".toLocaleLowerCase"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".toLocaleLowerCase"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"toLocaleLowerCase"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"toLocaleUpperCase","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".toLocaleUpperCase","insertTextFormat":1,"filterText":".toLocaleUpperCase","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".toLocaleUpperCase"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".toLocaleUpperCase"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"toLocaleUpperCase"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"toLowerCase","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".toLowerCase","insertTextFormat":1,"filterText":".toLowerCase","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".toLowerCase"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".toLowerCase"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"toLowerCase"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"toString","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".toString","insertTextFormat":1,"filterText":".toString","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".toString"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".toString"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"toString"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"toUpperCase","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".toUpperCase","insertTextFormat":1,"filterText":".toUpperCase","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".toUpperCase"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".toUpperCase"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"toUpperCase"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"toWellFormed","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".toWellFormed","insertTextFormat":1,"filterText":".toWellFormed","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".toWellFormed"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".toWellFormed"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"toWellFormed"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"trim","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".trim","insertTextFormat":1,"filterText":".trim","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".trim"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".trim"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"trim"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"trimEnd","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".trimEnd","insertTextFormat":1,"filterText":".trimEnd","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".trimEnd"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".trimEnd"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"trimEnd"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"trimStart","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".trimStart","insertTextFormat":1,"filterText":".trimStart","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".trimStart"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".trimStart"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"trimStart"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"valueOf","kind":2,"sortText":"11","commitCharacters":[".",",",";","("],"insertText":".valueOf","insertTextFormat":1,"filterText":".valueOf","textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".valueOf"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".valueOf"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"valueOf"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"anchor","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".anchor","insertTextFormat":1,"filterText":".anchor","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".anchor"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".anchor"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"anchor"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"big","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".big","insertTextFormat":1,"filterText":".big","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".big"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".big"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"big"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"blink","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".blink","insertTextFormat":1,"filterText":".blink","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".blink"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".blink"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"blink"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"bold","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".bold","insertTextFormat":1,"filterText":".bold","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".bold"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".bold"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"bold"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"fixed","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".fixed","insertTextFormat":1,"filterText":".fixed","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".fixed"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".fixed"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"fixed"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"fontcolor","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".fontcolor","insertTextFormat":1,"filterText":".fontcolor","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".fontcolor"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".fontcolor"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"fontcolor"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"fontsize","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".fontsize","insertTextFormat":1,"filterText":".fontsize","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".fontsize"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".fontsize"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"fontsize"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"italics","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".italics","insertTextFormat":1,"filterText":".italics","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".italics"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".italics"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"italics"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"link","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".link","insertTextFormat":1,"filterText":".link","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".link"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".link"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"link"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"small","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".small","insertTextFormat":1,"filterText":".small","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".small"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".small"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"small"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"strike","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".strike","insertTextFormat":1,"filterText":".strike","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".strike"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".strike"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"strike"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"sub","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".sub","insertTextFormat":1,"filterText":".sub","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".sub"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".sub"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"sub"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"substr","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".substr","insertTextFormat":1,"filterText":".substr","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".substr"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".substr"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"substr"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"sup","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".sup","insertTextFormat":1,"filterText":".sup","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".sup"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".sup"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"sup"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"trimLeft","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".trimLeft","insertTextFormat":1,"filterText":".trimLeft","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".trimLeft"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".trimLeft"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"trimLeft"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}},{"label":"trimRight","kind":2,"sortText":"z11","commitCharacters":[".",",",";","("],"insertText":".trimRight","insertTextFormat":1,"filterText":".trimRight","tags":[1],"textEdit":{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":6}},"newText":".trimRight"},"data":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","original":{"textEdit":{"range":{"start":{"line":8,"character":5},"end":{"line":8,"character":6}},"newText":".trimRight"},"data":{"uri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro","fileName":"/home/NAME/git/hub/ORG/REPO/src/components/example.astro","offset":105,"originalItem":{"name":"trimRight"}}},"pluginIndex":3,"embeddedDocumentUri":"volar-embedded-content://tsx/file%253A%252F%252F%252Fhome%252FNAME%252Fgit%252Fhub%252FORG%252FREPO%252Fsrc%252Fcomponents%252Fexample.astro"}}]}}'
RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","diagnostics":[],"version":2}}'
RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/NAME/git/hub/ORG/REPO/src/components/example.astro","diagnostics":[],"version":2}}'

What's interesting is:

  1. Snippets when we don't support them.
  2. No inlay hints when we do support them. Nope, this is correct. It's "inlay hint refresh" not just "inlay hint".
  3. No semantic tokens when we do support them. Correct as well. Same reason.

I would have focused on those three items instead of the backslashes, which are an artifact of...

https://github.com/ycm-core/ycmd/blob/master/ycmd/completers/language_server/language_server_completer.py#L520

...of using %r, which does additional escaping before logging.

Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @S0AndS0)

@S0AndS0
Copy link
Contributor Author

S0AndS0 commented Sep 4, 2024

Are you saying that disabling the Emmit plugin stops AstroLS from sending from sending snippets?
I still see a lot of snippets sent, in the ycmd stderr log that you have attached in the bug report.

Oh, I was only searching for Emmit related lines when I made that false assertion, whups!

You can certainly do that, but unless explicitly mentioned otherwise, our documentation is written with local extra confs in mind.
Users who use global (or "global-ish") extra confs should know enough to adapt.

That makes sense since such configs should likely be shared via Git if/when working with others on a code base.

I'd rather not. You'll find some unrelated node_modules and users might get angry if we do :cd behind their backs.

I wasn't thinking of changing the current directory, that would indeed be an unwelcome surprise. More I was considering the first file opened (kwargs'filename' fed to the Settings function in a .ycm_extra_conf.py) that starts a server could help us determine what npm workspace we'd be dealing with, eg.

def closest_node_modules_directory(path: str) -> str:
    """Walk through parent directories until `node_modules` is found or throw a `FileNotFoundError` if we recurs beyond current user's home directory

    Args:
        path (str): Directory to recursively search for `node_modules`

    Returns:
        str: Directory path to nearest `node_modules`

    TODO:
        Consider system call parsing to `npm root -g` if/when recursion reaches home directory
    """
    has_modules = 0 < len( [ x for x in os.listdir(path) if x == 'node_modules' and os.path.isdir(os.path.join(path, x)) ])
    if has_modules:
        return os.path.join(path, 'node_modules')
    elif path == os.path.dirname(os.path.expanduser('~')):
        if os.path.isfile(os.path.join(path, 'package.json')):
            print('You may want to: "pushd {} && npm install; popd"'.format(path), file=sys.stderr)
        else:
            raise FileNotFoundError('Did not find: "node_modules"')
    else:
        return closest_node_modules_directory(os.path.dirname(path))

... And though this seems to work for a non-monorepo, I am hesitant to put this sort of code into your ReadMe because it ain't well tested and feels a bit much for what should be a configuration file.

I've just checked a different server and see the "thing\"" in completion items there as well.
It's definitely an artifact of ycmd logs.

Ha here I was so ready to jump on the Astro LS team for doubling-up on backslashes 🤦 Thanks for correcting my confusion!

Furthermore, they will only be interested in these lines from your log:

...

What's interesting is:

  1. Snippets when we don't support them.

Ah so if I understand correctly the "method":"initialize" data provides params.capabilities which says what the LSP (YCM) client supports, which may be ignored (or defaulted/assumed true) by the time a response to "method":"textDocument/completion" is sent?

If that's the case, is there any way I can explicitly set things like params.capabilities.textDocument.completion.completionItem.snippetSupport to be false via a YCM config?

@S0AndS0
Copy link
Contributor Author

S0AndS0 commented Sep 9, 2024

Good news! I did a manual update/upgrade of dependencies, because tag v2.4.4 of the volar.js package published the snippet fix, and everything so far looks to be clean in the YouCompeteMe logs :-D

Only thing I can think of that may delay merging is that I pinned the @astrojs/language-server version to 2.14.1, so I'm not sure if a npm update will be required or not for those following proposed instructions on a fresh device.

Copy link
Contributor

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delayed response. I had a really busy couple of days.
Again, thank you for working on this!

Good news! I did a manual update/upgrade of dependencies, because tag v2.4.4 of the volar.js package published the snippet fix, and everything so far looks to be clean in the YouCompeteMe logs :-D

Great!

And though this seems to work for a non-monorepo, I am hesitant to put this sort of code into your ReadMe because it ain't well tested and feels a bit much for what should be a configuration file.

On top of that, what happens if we find an unrelated node_modules?
I'd just change

'tsdk': "{}/node_modules/typescript/lib".format(os.path.abspath(os.path.curdir))

to

lib_path = pathlib.Path(__file__).absolute().parent
...
'tsdk': f'{lib_path}/node_modues/typescript/lib'

Let's not over-engineer an example config.

Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @S0AndS0)

Copy link
Contributor

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for pinning the version, I've just checked other servers in lsp-examples. Vue does this:

{
  "description": "ycmd yaml-language-server runtime area",
  "dependencies": {
    "vls": "*"
  }
}

php does the same:

{
  "description": "ycmd css-language-server runtime area",
  "dependencies": {
    "vscode-langservers-extracted": "*"
  }
}

So let's just allow any version, to not worry about updating server versions in lsp-examples.

Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @S0AndS0)

@S0AndS0
Copy link
Contributor Author

S0AndS0 commented Sep 11, 2024

Sorry for the delayed response. I had a really busy couple of days.
Again, thank you for working on this!

No need for apologies, but forgiven and most welcome ya totally be ;-D

On top of that, what happens if we find an unrelated node_modules? I'd just change

'tsdk': "{}/node_modules/typescript/lib".format(os.path.abspath(os.path.curdir))

to

lib_path = pathlib.Path(__file__).absolute().parent
...
'tsdk': f'{lib_path}/node_modues/typescript/lib'

Let's not over-engineer an example config.

Tragically the Astro Docs -- Example Project Tree shows a file nesting of two, or greater, for any .astro files;

Snippet from Example Project Tree
- `src/`
  - `components/`
    - `Header.astro`
    - `Button.jsx`
  - `layouts/`
    - `PostLayout.astro`
  - `pages/`
    - `posts/`
      `post1.md`
      `post2.md`
      `post3.md`
    - `index.astro`

... Which leads me to believe; using the current working directory as the base when trying to find the node_modules/typescript/lib path is gonna be the least over-engineered avenue, but what I'll do for future readers is leverage a locally scoped variable and format string.

So let's just allow any version, to not worry about updating server versions in lsp-examples.

Consider it done!

Oh, and I added/committed the previously project_root_files requested changes too; totally spaced that last week 🤦

README.md Show resolved Hide resolved
@bstaletic bstaletic merged commit 4b1fde4 into ycm-core:master Sep 12, 2024
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants