tailwindlabs / tailwindcss-intellisense

Intelligent Tailwind CSS tooling for Visual Studio Code
2.86k stars 195 forks source link

LSP textDocument/completion returns no response for a proper formatted request #925

Closed artemkovalyov closed 7 months ago

artemkovalyov commented 7 months ago

What version of VS Code are you using?

Emacs with lsp-bridge, also tried with eglot

What version of Tailwind CSS IntelliSense are you using?

Latest lang server version

What version of Tailwind CSS are you using?

3.0

What package manager are you using?

For example: npm

What operating system are you using?

Linux

Tailwind config

// Paste the contents of your Tailwind config file here

Describe your issue

I've tried to configure tailwindcss LSP for lsp-bridge and it seems to be getting through the configuration flow but never replies to completion requests:

{
   "id": 62852,
   "method": "textDocument/completion",
   "params": {
      "position": {
         "line": 10,
         "character": 118
      },
      "context": {
         "triggerKind": 1
      },
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte"
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}

I never see a response.

The configuration sequence seems rather fine:

{
   "id": 59681,
   "method": "initialize",
   "params": {
      "processId": 56848,
      "rootPath": "/umetra/someoneinmyhead",
      "clientInfo": {
         "name": "emacs",
         "version": "lsp-bridge"
      },
      "rootUri": "file:///umetra/someoneinmyhead",
      "capabilities": {
         "workspace": {
            "configuration": true,
            "symbol": {
               "resolveSupport": {
                  "properties": []
               }
            }
         },
         "textDocument": {
            "completion": {
               "completionItem": {
                  "snippetSupport": true,
                  "deprecatedSupport": true,
                  "tagSupport": {
                     "valueSet": [
                        1
                     ]
                  },
                  "resolveSupport": {
                     "properties": [
                        "documentation",
                        "detail",
                        "additionalTextEdits"
                     ]
                  }
               }
            },
            "codeAction": {
               "dynamicRegistration": false,
               "codeActionLiteralSupport": {
                  "codeActionKind": {
                     "valueSet": [
                        "quickfix",
                        "refactor",
                        "refactor.extract",
                        "refactor.inline",
                        "refactor.rewrite",
                        "source",
                        "source.organizeImports"
                     ]
                  }
               },
               "isPreferredSupport": true
            },
            "inlayHint": {
               "dynamicRegistration": false
            },
            "publishDiagnostics": {
               "relatedInformation": true,
               "tagSupport": {
                  "valueSet": [
                     1,
                     2
                  ]
               },
               "versionSupport": true,
               "codeDescriptionSupport": true,
               "dataSupport": true
            }
         }
      },
      "initializationOptions": {
         "configuration": {
            "tailwindCSS": {
               "emmetCompletions": false,
               "showPixelEquivalents": true,
               "rootFontSize": 16,
               "validate": true,
               "hovers": true,
               "suggestions": true,
               "codeActions": true,
               "lint": {
                  "invalidScreen": "error",
                  "invalidVariant": "error",
                  "invalidTailwindDirective": "error",
                  "invalidApply": "error",
                  "invalidConfigPath": "error",
                  "cssConflict": "warning",
                  "recommendedVariantOrder": "warning"
               },
               "experimental": {
                  "classRegex": ""
               },
               "classAttributes": [
                  "class",
                  "className",
                  "ngClass"
               ]
            }
         }
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}
{
   "jsonrpc": "2.0",
   "id": 59681,
   "result": {
      "capabilities": {
         "textDocumentSync": 1,
         "hoverProvider": true,
         "colorProvider": true,
         "codeActionProvider": true,
         "documentLinkProvider": {},
         "completionProvider": {
            "resolveProvider": true,
            "triggerCharacters": [
               "\"",
               "'",
               "`",
               " ",
               ".",
               "(",
               "[",
               "]",
               "!",
               "/",
               "-",
               ":"
            ]
         }
      }
   }
}
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] Loaded tailwindcss v3.4.1: /umetra/someoneinmyhead/node_modules/tailwindcss"
   }
}
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] Loaded postcss v8.4.35: /umetra/someoneinmyhead/node_modules/postcss"
   }
}

I tried a mix of configuration options for initialization but completion never picked up. What could be the obvious culprit? Can you suggest the best way to test it or a minimal configuration for that to work?

Other servers like Svelte, JS, Rust, etc work pretty fine and I'm surprised to be unable to get any progress with a tailwind. I checked the code of the server and VSCode plugin to figure out the configuration but with little fruit so far. Sadly, there is not much documentation on the server itself and it's quirks.

Am I missing smth obvious? Can you point me in a better direction?

thecrypticace commented 7 months ago

I'll take a look at this soon — probably tomorrow. It does look like it's booted properly based on the fact that you're getting log messages though.

Would you mind providing these things:

artemkovalyov commented 7 months ago

@thecrypticace, thanks for getting back, I will provide all you ask. I activated logs for debugging reasons after failing simple attempts to integrate the tailwindcss language server. Having it for Emacs would be a blessing.

artemkovalyov commented 7 months ago
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/**/*.{html,js,mjs,svelte,ts,md,svx}',
    './plugins/**/*.{html,js,mjs,svelte,ts,md,svx}'
  ],
  darkMode: 'class',
  theme: {
    extend: {
      typography: {
        DEFAULT: {
          css: {
            code: {
              'background-color': 'var(--md-sys-color-outline-variant)',
              padding: '0.2rem 0.5rem 0.1rem 0.5rem',
              fontWeight: 0
            },
            'code::before': {
              content: ''
            },
            'code::after': {
              content: ''
            }
          }
        }
      },
      colors: {
        // 'gray': {
        //   5: '#1e1e1e',
        //   7: '#222222',
        //   8: '#242424',
        //   9: '#272727',
        //   11: '#2c2c2c',
        //   12: '#2e2e2e',
        //   14: '#333333',
        //   15: '#363636',
        //   16: '#383838'
        // },
        // Material design colors scheme
        // The tokns automatically change for Light and Dark scheme
        // Check /src/lib/styles
        primary: 'var(--md-sys-color-primary)',
        'on-primary': 'var(--md-sys-color-on-primary)',
        'primary-container': 'var(--md-sys-color-primary-container)',
        'on-primary-container': 'var(--md-sys-color-on-primary-container)',
        'on-primary-container-high-contrast':
          'var(--md-sys-color-on-primary-container-high-contrast)',
        secondary: 'var(--md-sys-color-secondary)',
        'on-secondary': 'var(--md-sys-color-on-secondary)',
        'secondary-container': 'var(--md-sys-color-secondary-container)',
        'on-secondary-container': 'var(--md-sys-color-on-secondary-container)',
        tertiary: 'var(--md-sys-color-tertiary)',
        'on-tertiary': 'var(--md-sys-color-on-tertiary)',
        'tertiary-container': 'var(--md-sys-color-tertiary-container)',
        'on-tertiary-container': 'var(--md-sys-color-on-tertiary-container)',
        error: 'var(--md-sys-color-error)',
        'on-error': 'var(--md-sys-color-on-error)',
        'error-container': 'var(--md-sys-color-error-container)',
        'on-error-container': 'var(--md-sys-color-on-error-container)',
        background: 'var(--md-sys-color-background)',
        'on-background': 'var(--md-sys-color-on-background)',
        surface: 'var(--md-sys-color-surface)',
        'on-surface': 'var(--md-sys-color-on-surface)',
        'surface-variant': 'var(--md-sys-color-surface-variant)',
        'on-surface-variant': 'var(--md-sys-color-on-surface-variant)',
        outline: 'var(--md-sys-color-outline)',
        'outline-variant': 'var(--md-sys-color-outline-variant)',
        'inverse-surface': 'var(--md-sys-color-inverse-surface)',
        'on-inverse-surface': 'var(--md-sys-color-on-inverse-surface)',
        'inverse-primary': 'var(--md-sys-color-inverse-primary)',
        'on-inverse-primary': 'var(--md-sys-color-on-inverse-primary)',
        shadow: 'var(--md-sys-color-shadow)',
        'surface-tint': 'var(--md-sys-color-surface-tint)',
        'surface-tint-color': 'var(--md-sys-color-surface-tint-color)',
        elevation: {
          1: 'var(--md-sys-color-elevation1)',
          2: 'var(--md-sys-color-elevation2)',
          3: 'var(--md-sys-color-elevation3)',
          4: 'var(--md-sys-color-elevation4)',
          5: 'var(--md-sys-color-elevation5)',
          6: 'var(--md-sys-color-elevation6)',
          7: 'var(--md-sys-color-elevation7)'
        },

        // Tonal palette from the Material Design Theme
        'primary-palette': {
          /* primary */
          0: 'var(--md-ref-palette-primary0)', // --md-ref-palette-primary0: #000000;
          10: 'var(--md-ref-palette-primary10)', // --md-ref-palette-primary10: #301400;
          20: 'var(--md-ref-palette-primary20)', // --md-ref-palette-primary20: #502500;
          25: 'var(--md-ref-palette-primary25)', // --md-ref-palette-primary25: #602e00;
          30: 'var(--md-ref-palette-primary30)', // --md-ref-palette-primary30: #713700;
          35: 'var(--md-ref-palette-primary35)', // --md-ref-palette-primary35: #834000;
          40: 'var(--md-ref-palette-primary40)', // --md-ref-palette-primary40: #954a00;
          50: 'var(--md-ref-palette-primary50)', // --md-ref-palette-primary50: #ba5e00;
          60: 'var(--md-ref-palette-primary60)', // --md-ref-palette-primary60: #e17300;
          70: 'var(--md-ref-palette-primary70)', // --md-ref-palette-primary70: #ff8e2f;
          80: 'var(--md-ref-palette-primary80)', // --md-ref-palette-primary80: #ffb785;
          90: 'var(--md-ref-palette-primary90)', // --md-ref-palette-primary90: #ffdcc6;
          95: 'var(--md-ref-palette-primary95)', // --md-ref-palette-primary95: #ffede4;
          98: 'var(--md-ref-palette-primary98)', // --md-ref-palette-primary98: #fff8f5;
          99: 'var(--md-ref-palette-primary99)', // --md-ref-palette-primary99: #fffbff;
          100: 'var(--md-ref-palette-primary100)' // --md-ref-palette-primary100: #ffffff;
        },
        'secondary-palette': {
          /* secondary */
          0: 'var(--md-ref-palette-secondary0)', // --md-ref-palette-secondary0: #000000;
          10: 'var(--md-ref-palette-secondary10)', // --md-ref-palette-secondary10: #001e2f;
          20: 'var(--md-ref-palette-secondary20)', // --md-ref-palette-secondary20: #00344d;
          25: 'var(--md-ref-palette-secondary25)', // --md-ref-palette-secondary25: #00405d;
          30: 'var(--md-ref-palette-secondary30)', // --md-ref-palette-secondary30: #004c6e;
          35: 'var(--md-ref-palette-secondary35)', // --md-ref-palette-secondary35: #00587f;
          40: 'var(--md-ref-palette-secondary40)', // --md-ref-palette-secondary40: #006591;
          50: 'var(--md-ref-palette-secondary50)', // --md-ref-palette-secondary50: #007fb5;
          60: 'var(--md-ref-palette-secondary60)', // --md-ref-palette-secondary60: #009adb;
          70: 'var(--md-ref-palette-secondary70)', // --md-ref-palette-secondary70: #1db6ff;
          80: 'var(--md-ref-palette-secondary80)', // --md-ref-palette-secondary80: #89ceff;
          90: 'var(--md-ref-palette-secondary90)', // --md-ref-palette-secondary90: #c9e6ff;
          95: 'var(--md-ref-palette-secondary95)', // --md-ref-palette-secondary95: #e5f2ff;
          98: 'var(--md-ref-palette-secondary98)', // --md-ref-palette-secondary98: #f6faff;
          99: 'var(--md-ref-palette-secondary99)', // --md-ref-palette-secondary99: #fcfcff;
          100: 'var(--md-ref-palette-secondary100)' // --md-ref-palette-secondary100: #ffffff;
        },
        'tertiary-palette': {
          /* tertiary */
          0: 'var(--md-ref-palette-tertiary0)', // --md-ref-palette-tertiary0:  #000000;
          10: 'var(--md-ref-palette-tertiary10)', // --md-ref-palette-tertiary10: #002115;
          20: 'var(--md-ref-palette-tertiary20)', // --md-ref-palette-tertiary20: #003827;
          25: 'var(--md-ref-palette-tertiary25)', // --md-ref-palette-tertiary25: #004530;
          30: 'var(--md-ref-palette-tertiary30)', // --md-ref-palette-tertiary30: #005139;
          35: 'var(--md-ref-palette-tertiary35)', // --md-ref-palette-tertiary35: #005e43;
          40: 'var(--md-ref-palette-tertiary40)', // --md-ref-palette-tertiary40: #006c4d;
          50: 'var(--md-ref-palette-tertiary50)', // --md-ref-palette-tertiary50: #008862;
          60: 'var(--md-ref-palette-tertiary60)', // --md-ref-palette-tertiary60: #27a37a;
          70: 'var(--md-ref-palette-tertiary70)', // --md-ref-palette-tertiary70: #4bbf93;
          80: 'var(--md-ref-palette-tertiary80)', // --md-ref-palette-tertiary80: #69dbad;
          90: 'var(--md-ref-palette-tertiary90)', // --md-ref-palette-tertiary90: #86f8c8;
          95: 'var(--md-ref-palette-tertiary95)', // --md-ref-palette-tertiary95: #bdffdf;
          98: 'var(--md-ref-palette-tertiary98)', // --md-ref-palette-tertiary98: #e7fff1;
          99: 'var(--md-ref-palette-tertiary99)', // --md-ref-palette-tertiary99: #f4fff7;
          100: 'var(--md-ref-palette-tertiary100)' // --md-ref-palette-tertiary100: #ffffff;
        },
        'neutral-palette': {
          /* neutral */
          0: 'var(--md-ref-palette-neutral0)', // --md-ref-palette-neutral0 : #000000;
          10: 'var(--md-ref-palette-neutral10)', // --md-ref-palette-neutral10: #201a17;
          20: 'var(--md-ref-palette-neutral20)', // --md-ref-palette-neutral20: #362f2b;
          25: 'var(--md-ref-palette-neutral25)', // --md-ref-palette-neutral25: #413a36;
          30: 'var(--md-ref-palette-neutral30)', // --md-ref-palette-neutral30: #4d4541;
          35: 'var(--md-ref-palette-neutral35)', // --md-ref-palette-neutral35: #59514d;
          40: 'var(--md-ref-palette-neutral40)', // --md-ref-palette-neutral40: #655d58;
          50: 'var(--md-ref-palette-neutral50)', // --md-ref-palette-neutral50: #7e7570;
          60: 'var(--md-ref-palette-neutral60)', // --md-ref-palette-neutral60: #998f8a;
          70: 'var(--md-ref-palette-neutral70)', // --md-ref-palette-neutral70: #b4a9a4;
          80: 'var(--md-ref-palette-neutral80)', // --md-ref-palette-neutral80: #d0c4bf;
          90: 'var(--md-ref-palette-neutral90)', // --md-ref-palette-neutral90: #ece0da;
          95: 'var(--md-ref-palette-neutral95)', // --md-ref-palette-neutral95: #fbeee8;
          98: 'var(--md-ref-palette-neutral98)', // --md-ref-palette-neutral98: #fff8f5;
          99: 'var(--md-ref-palette-neutral99)', // --md-ref-palette-neutral99: #fffbff;
          100: 'var(--md-ref-palette-neutral100)' // --md-ref-palette-neutral100: #ffffff;
        },
        'neutral-variant-palette': {
          /* neutral-variant */
          0: 'var(--md-ref-palette-neutral-variant0)', // --md-ref-palette-neutral-variant0: #000000;
          10: 'var(--md-ref-palette-neutral-variant10)', // --md-ref-palette-neutral-variant10: #241912;
          20: 'var(--md-ref-palette-neutral-variant20)', // --md-ref-palette-neutral-variant20: #3a2e26;
          25: 'var(--md-ref-palette-neutral-variant25)', // --md-ref-palette-neutral-variant25: #463931;
          30: 'var(--md-ref-palette-neutral-variant30)', // --md-ref-palette-neutral-variant30: #52443b;
          35: 'var(--md-ref-palette-neutral-variant35)', // --md-ref-palette-neutral-variant35: #5e5047;
          40: 'var(--md-ref-palette-neutral-variant40)', // --md-ref-palette-neutral-variant40: #6a5b52;
          50: 'var(--md-ref-palette-neutral-variant50)', // --md-ref-palette-neutral-variant50: #84746a;
          60: 'var(--md-ref-palette-neutral-variant60)', // --md-ref-palette-neutral-variant60: #9f8d83;
          70: 'var(--md-ref-palette-neutral-variant70)', // --md-ref-palette-neutral-variant70: #baa89d;
          80: 'var(--md-ref-palette-neutral-variant80)', // --md-ref-palette-neutral-variant80: #d7c3b7;
          90: 'var(--md-ref-palette-neutral-variant90)', // --md-ref-palette-neutral-variant90: #f3ded3;
          95: 'var(--md-ref-palette-neutral-variant95)', // --md-ref-palette-neutral-variant95: #ffede4;
          98: 'var(--md-ref-palette-neutral-variant98)', // --md-ref-palette-neutral-variant98: #fff8f5;
          99: 'var(--md-ref-palette-neutral-variant99)', // --md-ref-palette-neutral-variant99: #fffbff;
          100: 'var(--md-ref-palette-neutral-variant100)' // --md-ref-palette-neutral-variant100: #ffffff;
        },
        'neutral-palette': {
          /* error */
          0: 'var(--md-ref-palette-error0)', // --md-ref-palette-error0: #000000;
          10: 'var(--md-ref-palette-error10)', // --md-ref-palette-error10: #410002;
          20: 'var(--md-ref-palette-error20)', // --md-ref-palette-error20: #690005;
          25: 'var(--md-ref-palette-error25)', // --md-ref-palette-error25: #7e0007;
          30: 'var(--md-ref-palette-error30)', // --md-ref-palette-error30: #93000a;
          35: 'var(--md-ref-palette-error35)', // --md-ref-palette-error35: #a80710;
          40: 'var(--md-ref-palette-error40)', // --md-ref-palette-error40: #ba1a1a;
          50: 'var(--md-ref-palette-error50)', // --md-ref-palette-error50: #de3730;
          60: 'var(--md-ref-palette-error60)', // --md-ref-palette-error60: #ff5449;
          70: 'var(--md-ref-palette-error70)', // --md-ref-palette-error70: #ff897d;
          80: 'var(--md-ref-palette-error80)', // --md-ref-palette-error80: #ffb4ab;
          90: 'var(--md-ref-palette-error90)', // --md-ref-palette-error90: #ffdad6;
          95: 'var(--md-ref-palette-error95)', // --md-ref-palette-error95: #ffedea;
          98: 'var(--md-ref-palette-error98)', // --md-ref-palette-error98: #fff8f7;
          99: 'var(--md-ref-palette-error99)', // --md-ref-palette-error99: #fffbff;
          100: 'var(--md-ref-palette-error100)' // --md-ref-palette-error100: #ffffff;
        }
      }
    }
  },
  plugins: [require('@tailwindcss/typography'), require('@tailwindcss/forms')]
};

The NavBar is very simple:

<script lang="ts">
  import HamburgerMenu from './HamburgerMenu.svelte';
  import Logo from './Logo.svelte';
  import ThemeToggle from './ThemeToggle.svelte';
  import TopMenuLinks from './TopMenuLinks.svelte';
  export let open: boolean;
  export let path: string;
</script>

<nav
  class="flex flex-nowrap bg-elevation-1 px-3 py-3 w-full sm:px-7 justify-between border-b-2 border-outline-variant"
>
  <Logo />
  <TopMenuLinks bind:path />
  <div class="flex gap-x-5 justify-end">
    <ThemeToggle />
    <HamburgerMenu bind:open />
  </div>
</nav>

tailwind

artemkovalyov commented 7 months ago

Here's the LSP Log I get, the response is always None I use the latest LSP Server from the latest VSCode plugin.

Eval in Emacs: (lsp-bridge--first-start '47137)
Eval in Emacs: (message '"[LSP-Bridge] found language server: /home/artem/.nvm/versions/node/v20.10.0/bin/node")
Start lsp server (tailwindcss) for /umetra/someoneinmyhead
Eval in Emacs: (message '"[LSP-Bridge] Active project 'someoneinmyhead', enjoy hacking!")
Handlers: [<class 'core.handler.completion.Completion'>,
 <class 'core.handler.completion_item.CompletionItem'>,
 <class 'core.handler.find_define.FindDefine'>,
 <class 'core.handler.find_type_define.FindTypeDefine'>,
 <class 'core.handler.find_implementation.FindImplementation'>,
 <class 'core.handler.find_references.FindReferences'>,
 <class 'core.handler.peek.PeekFindDefine'>,
 <class 'core.handler.peek.PeekFindReferences'>,
 <class 'core.handler.hover.Hover'>,
 <class 'core.handler.signature_help.SignatureHelp'>,
 <class 'core.handler.prepare_rename.PrepareRename'>,
 <class 'core.handler.rename.Rename'>,
 <class 'core.handler.jdt_uri_resolver.JDTUriResolver'>,
 <class 'core.handler.deno_uri_resolver.DenoUriResolver'>,
 <class 'core.handler.code_action.CodeAction'>,
 <class 'core.handler.formatting.Formatting'>,
 <class 'core.handler.execute_command.ExecuteCommand'>,
 <class 'core.handler.workspace_symbol.WorkspaceSymbol'>,
 <class 'core.handler.call_hierarchy.PrepareCallHierarchy'>,
 <class 'core.handler.call_hierarchy.CallHierarchy'>,
 <class 'core.handler.call_hierarchy.PrepareCallHierarchyIncomingCalls'>,
 <class 'core.handler.call_hierarchy.PrepareCallHierarchyOutgoingCalls'>,
 <class 'core.handler.call_hierarchy.CallHierarchyIncomingCalls'>,
 <class 'core.handler.call_hierarchy.CallHierarchyOutgoingCalls'>,
 <class 'core.handler.document_symbol.DocumentSymbol'>,
 <class 'core.handler.jdtls.jdtls_list_overridable_methods.JdtlsListOverridableMethods'>,
 <class 'core.handler.jdtls.jdtls_add_overridable_methods.JdtlsAddOverridableMethods'>,
 <class 'core.handler.inlay_hint.InlayHint'>,
 <class 'core.handler.semantic_tokens.SemanticTokens'>]

--- [11:06:27.587832] Send initialize request (28453) to 'tailwindcss' for project someoneinmyhead
{
   "id": 28453,
   "method": "initialize",
   "params": {
      "processId": 22240,
      "rootPath": "/umetra/someoneinmyhead",
      "clientInfo": {
         "name": "emacs",
         "version": "lsp-bridge"
      },
      "rootUri": "file:///umetra/someoneinmyhead",
      "capabilities": {
         "workspace": {
            "configuration": true,
            "symbol": {
               "resolveSupport": {
                  "properties": []
               }
            }
         },
         "textDocument": {
            "completion": {
               "completionItem": {
                  "snippetSupport": true,
                  "deprecatedSupport": true,
                  "tagSupport": {
                     "valueSet": [
                        1
                     ]
                  },
                  "resolveSupport": {
                     "properties": [
                        "documentation",
                        "detail",
                        "additionalTextEdits"
                     ]
                  }
               }
            },
            "codeAction": {
               "dynamicRegistration": false,
               "codeActionLiteralSupport": {
                  "codeActionKind": {
                     "valueSet": [
                        "quickfix",
                        "refactor",
                        "refactor.extract",
                        "refactor.inline",
                        "refactor.rewrite",
                        "source",
                        "source.organizeImports"
                     ]
                  }
               },
               "isPreferredSupport": true
            },
            "inlayHint": {
               "dynamicRegistration": false
            },
            "publishDiagnostics": {
               "relatedInformation": true,
               "tagSupport": {
                  "valueSet": [
                     1,
                     2
                  ]
               },
               "versionSupport": true,
               "codeDescriptionSupport": true,
               "dataSupport": true
            }
         }
      },
      "initializationOptions": {
         "configuration": {
            "tailwindCSS": {
               "emmetCompletions": false,
               "showPixelEquivalents": true,
               "rootFontSize": 16,
               "validate": true,
               "hovers": true,
               "suggestions": true,
               "codeActions": true,
               "lint": {
                  "invalidScreen": "error",
                  "invalidVariant": "error",
                  "invalidTailwindDirective": "error",
                  "invalidApply": "error",
                  "invalidConfigPath": "error",
                  "cssConflict": "warning",
                  "recommendedVariantOrder": "warning"
               },
               "experimental": {
                  "classRegex": ""
               },
               "classAttributes": [
                  "class",
                  "className",
                  "ngClass"
               ]
            }
         }
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}
Eval in Emacs: (lsp-bridge-set-prefix-style '"ascii")
Eval in Emacs: (lsp-bridge-set-server-names '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '("tailwindcss"))

--- [11:06:27.767428] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "Setting up server\u2026"
   }
}

--- [11:06:27.767862] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "Listening for messages\u2026"
   }
}

--- [11:06:27.769997] Recv response (28453) from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "id": 28453,
   "result": {
      "capabilities": {
         "textDocumentSync": 1,
         "hoverProvider": true,
         "colorProvider": true,
         "codeActionProvider": true,
         "documentLinkProvider": {},
         "completionProvider": {
            "resolveProvider": true,
            "triggerCharacters": [
               "\"",
               "'",
               "`",
               " ",
               ".",
               "(",
               "[",
               "]",
               "!",
               "/",
               "-",
               ":"
            ]
         }
      }
   }
}

--- [11:06:27.770218] Send initialized notification to 'tailwindcss' for project someoneinmyhead
{
   "method": "initialized",
   "params": {},
   "message_type": "notification",
   "jsonrpc": "2.0"
}

--- [11:06:27.770317] Send workspace/didChangeConfiguration notification to 'tailwindcss' for project someoneinmyhead
{
   "method": "workspace/didChangeConfiguration",
   "params": {
      "settings": {}
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}

--- [11:06:27.770424] Send textDocument/didOpen notification to 'tailwindcss' for project someoneinmyhead
{
   "method": "textDocument/didOpen",
   "params": {
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
         "languageId": "tailwindcss",
         "version": 0,
         "text": "<script lang=\"ts\">\n  import HamburgerMenu from './HamburgerMenu.svelte';\n  import Logo from './Logo.svelte';\n  import ThemeToggle from './ThemeToggle.svelte';\n  import TopMenuLinks from './TopMenuLinks.svelte';\n  export let open: boolean;\n  export let path: string;\n</script>\n\n<nav\n  class=\"flex flex-nowrap bg-elevation-1 px-3 py-3 w-full sm:px-7 justify-between border-b-2 border-outline-variant\"\n>\n  <Logo />\n  <TopMenuLinks bind:path />\n  <div class=\"flex gap-x-5 justify-end\">\n    <ThemeToggle />\n    <HamburgerMenu bind:open />\n  </div>\n</nav>\n"
      }
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}

--- [11:06:27.773198] Recv workspace/configuration request (0) from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "id": 0,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "editor"
         }
      ]
   }
}

--- [11:06:27.773572] Send response to server request 0 to 'tailwindcss' for project someoneinmyhead
{
   "id": 0,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}

--- [11:06:27.773812] Recv workspace/configuration request (1) from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "id": 1,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "tailwindCSS"
         }
      ]
   }
}

--- [11:06:27.774098] Send response to server request 1 to 'tailwindcss' for project someoneinmyhead
{
   "id": 1,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}

--- [11:06:27.785307] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "Searching for Tailwind CSS projects in the workspace's folders."
   }
}

--- [11:06:27.864740] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "{\"tailwind\":{\"version\":\"3.4.1\",\"features\":[\"layer:base\",\"separator:root\",\"content-list\",\"jit\",\"css-at-config\",\"relative-content-paths\",\"transpiled-configs\"],\"isDefaultVersion\":false}}"
   }
}

--- [11:06:27.865026] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "{\"tailwind\":{\"version\":\"3.4.1\",\"features\":[\"layer:base\",\"separator:root\",\"content-list\",\"jit\",\"css-at-config\",\"relative-content-paths\",\"transpiled-configs\"],\"isDefaultVersion\":false}}"
   }
}

--- [11:06:27.923074] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[Global] Creating projects: [{\"folder\":\"/umetra/someoneinmyhead\",\"config\":\"/umetra/someoneinmyhead/tailwind.config.cjs\",\"selectors\":[{\"pattern\":\"/umetra/someoneinmyhead/tailwind.config.cjs\",\"priority\":0},{\"pattern\":\"/umetra/someoneinmyhead/src/**/*.{html,js,mjs,svelte,ts,md,svx}\",\"priority\":1},{\"pattern\":\"/umetra/someoneinmyhead/plugins/**/*.{html,js,mjs,svelte,ts,md,svx}\",\"priority\":1},{\"pattern\":\"/umetra/someoneinmyhead/**\",\"priority\":2},{\"pattern\":\"/umetra/someoneinmyhead/**\",\"priority\":5}],\"user\":false,\"tailwind\":{\"version\":\"3.4.1\",\"features\":[\"layer:base\",\"separator:root\",\"content-list\",\"jit\",\"css-at-config\",\"relative-content-paths\",\"transpiled-configs\"],\"isDefaultVersion\":false}}]"
   }
}

--- [11:06:28.117069] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[Global] Adding watch patterns: /umetra/someoneinmyhead/tailwind.config.cjs, /umetra/someoneinmyhead"
   }
}

--- [11:06:28.117438] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] Initializing..."
   }
}

--- [11:06:28.117647] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] supported features: [\"layer:base\",\"separator:root\",\"content-list\",\"jit\",\"css-at-config\",\"relative-content-paths\",\"transpiled-configs\"]"
   }
}

--- [11:06:30.477525] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] Loaded tailwindcss v3.4.1: /umetra/someoneinmyhead/node_modules/tailwindcss"
   }
}

--- [11:06:30.477681] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] Loaded Tailwind CSS config file: /umetra/someoneinmyhead/tailwind.config.cjs"
   }
}

--- [11:06:30.477860] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] Loaded postcss v8.4.36: /umetra/someoneinmyhead/node_modules/postcss"
   }
}

--- [11:06:30.477964] Recv window/logMessage notification from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[tailwind.config.cjs] Building..."
   }
}

--- [11:06:30.478174] Recv workspace/configuration request (2) from 'tailwindcss' for project someoneinmyhead
{
   "jsonrpc": "2.0",
   "id": 2,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "editor",
            "scopeUri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte"
         }
      ]
   }
}

--- [11:06:30.478332] Send response to server request 2 to 'tailwindcss' for project someoneinmyhead

--- [11:06:30.478400] Recv workspace/configuration request (3) from 'tailwindcss' for project someoneinmyhead
{
   "id": 2,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}
{
   "jsonrpc": "2.0",
   "id": 3,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "tailwindCSS",
            "scopeUri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte"
         }
      ]
   }
}

--- [11:06:30.478684] Send response to server request 3 to 'tailwindcss' for project someoneinmyhead

--- [11:06:30.478747] Recv @/tailwindCSS/projectInitialized notification from 'tailwindcss' for project someoneinmyhead
{
   "id": 3,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}
{
   "jsonrpc": "2.0",
   "method": "@/tailwindCSS/projectInitialized",
   "params": [
      null
   ]
}

--- [11:06:30.481534] Recv textDocument/publishDiagnostics notification from 'tailwindcss' for project someoneinmyhead

--- [11:06:30.481632] Record diagnostics from 'tailwindcss' for file NavBar.svelte
{
   "jsonrpc": "2.0",
   "method": "textDocument/publishDiagnostics",
   "params": {
      "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
      "diagnostics": []
   }
}
Eval in Emacs: (lsp-bridge-diagnostic--render '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '0)

--- [11:06:31.917309] Send textDocument/didChange notification to 'tailwindcss' for project someoneinmyhead
{
   "method": "textDocument/didChange",
   "params": {
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
         "version": 1
      },
      "contentChanges": [
         {
            "text": "<script lang=\"ts\">\n  import HamburgerMenu from './HamburgerMenu.svelte';\n  import Logo from './Logo.svelte';\n  import ThemeToggle from './ThemeToggle.svelte';\n  import TopMenuLinks from './TopMenuLinks.svelte';\n  export let open: boolean;\n  export let path: string;\n</script>\n\n<nav\n  class=\"flex flex-nowrap bg-elevation-1 px-3 py-3 w-full sm:px-7 justify-between border-b-2 border-outline-variant \"\n>\n  <Logo />\n  <TopMenuLinks bind:path />\n  <div class=\"flex gap-x-5 justify-end\">\n    <ThemeToggle />\n    <HamburgerMenu bind:open />\n  </div>\n</nav>\n"
         }
      ]
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}

--- [11:06:32.017987] Send textDocument/completion request (14878) to 'tailwindcss' for project someoneinmyhead
{
   "id": 14878,
   "method": "textDocument/completion",
   "params": {
      "position": {
         "line": 10,
         "character": 116
      },
      "context": {
         "triggerCharacter": " ",
         "triggerKind": 2
      },
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte"
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}

--- [11:06:32.029117] Recv textDocument/completion response (14878) from 'tailwindcss' for project someoneinmyhead

--- [11:06:32.029461] Got completion candidates (0) from 'tailwindcss' for file NavBar.svelte

--- [11:06:32.029608] Record completion candidates (0) from 'tailwindcss' for file NavBar.svelte
Eval in Emacs: (lsp-bridge-completion--record-items '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '(:line 10 :character 116) '"tailwindcss" '("\"" "'" "`" " " "." "(" "[" "]" "!" "/" "-" ":") '("tailwindcss"))
{
   "jsonrpc": "2.0",
   "id": 14878,
   "result": null
}

--- [11:06:32.421822] Recv textDocument/publishDiagnostics notification from 'tailwindcss' for project someoneinmyhead

--- [11:06:32.422132] Record diagnostics from 'tailwindcss' for file NavBar.svelte
{
   "jsonrpc": "2.0",
   "method": "textDocument/publishDiagnostics",
   "params": {
      "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
      "diagnostics": []
   }
}
Eval in Emacs: (lsp-bridge-diagnostic--render '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '0)
Eval in Emacs: (lsp-bridge-search-backend--record-items '"search-file-words" '())

--- [11:06:33.236628] Send textDocument/didChange notification to 'tailwindcss' for project someoneinmyhead
{
   "method": "textDocument/didChange",
   "params": {
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
         "version": 2
      },
      "contentChanges": [
         {
            "text": "<script lang=\"ts\">\n  import HamburgerMenu from './HamburgerMenu.svelte';\n  import Logo from './Logo.svelte';\n  import ThemeToggle from './ThemeToggle.svelte';\n  import TopMenuLinks from './TopMenuLinks.svelte';\n  export let open: boolean;\n  export let path: string;\n</script>\n\n<nav\n  class=\"flex flex-nowrap bg-elevation-1 px-3 py-3 w-full sm:px-7 justify-between border-b-2 border-outline-variant m\"\n>\n  <Logo />\n  <TopMenuLinks bind:path />\n  <div class=\"flex gap-x-5 justify-end\">\n    <ThemeToggle />\n    <HamburgerMenu bind:open />\n  </div>\n</nav>\n"
         }
      ]
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}
Eval in Emacs: (lsp-bridge-search-backend--record-items '"search-file-words" '())

--- [11:06:33.337778] Send textDocument/completion request (58489) to 'tailwindcss' for project someoneinmyhead
{
   "id": 58489,
   "method": "textDocument/completion",
   "params": {
      "position": {
         "line": 10,
         "character": 117
      },
      "context": {
         "triggerKind": 1
      },
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte"
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}

--- [11:06:33.343845] Recv textDocument/completion response (58489) from 'tailwindcss' for project someoneinmyhead

--- [11:06:33.344075] Got completion candidates (0) from 'tailwindcss' for file NavBar.svelte

--- [11:06:33.344196] Record completion candidates (0) from 'tailwindcss' for file NavBar.svelte
Eval in Emacs: (lsp-bridge-completion--record-items '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '(:line 10 :character 117) '"tailwindcss" '("\"" "'" "`" " " "." "(" "[" "]" "!" "/" "-" ":") '("tailwindcss"))
{
   "jsonrpc": "2.0",
   "id": 58489,
   "result": null
}

--- [11:06:33.378129] Send textDocument/didChange notification to 'tailwindcss' for project someoneinmyhead
{
   "method": "textDocument/didChange",
   "params": {
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
         "version": 3
      },
      "contentChanges": [
         {
            "text": "<script lang=\"ts\">\n  import HamburgerMenu from './HamburgerMenu.svelte';\n  import Logo from './Logo.svelte';\n  import ThemeToggle from './ThemeToggle.svelte';\n  import TopMenuLinks from './TopMenuLinks.svelte';\n  export let open: boolean;\n  export let path: string;\n</script>\n\n<nav\n  class=\"flex flex-nowrap bg-elevation-1 px-3 py-3 w-full sm:px-7 justify-between border-b-2 border-outline-variant mx\"\n>\n  <Logo />\n  <TopMenuLinks bind:path />\n  <div class=\"flex gap-x-5 justify-end\">\n    <ThemeToggle />\n    <HamburgerMenu bind:open />\n  </div>\n</nav>\n"
         }
      ]
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}

--- [11:06:33.478859] Send textDocument/completion request (10712) to 'tailwindcss' for project someoneinmyhead
{
   "id": 10712,
   "method": "textDocument/completion",
   "params": {
      "position": {
         "line": 10,
         "character": 118
      },
      "context": {
         "triggerKind": 1
      },
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte"
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}

--- [11:06:33.482399] Recv textDocument/completion response (10712) from 'tailwindcss' for project someoneinmyhead

--- [11:06:33.482733] Got completion candidates (0) from 'tailwindcss' for file NavBar.svelte

--- [11:06:33.482919] Record completion candidates (0) from 'tailwindcss' for file NavBar.svelte
Eval in Emacs: (lsp-bridge-completion--record-items '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '(:line 10 :character 118) '"tailwindcss" '("\"" "'" "`" " " "." "(" "[" "]" "!" "/" "-" ":") '("tailwindcss"))
{
   "jsonrpc": "2.0",
   "id": 10712,
   "result": null
}

--- [11:06:33.881824] Recv textDocument/publishDiagnostics notification from 'tailwindcss' for project someoneinmyhead

--- [11:06:33.882326] Record diagnostics from 'tailwindcss' for file NavBar.svelte
{
   "jsonrpc": "2.0",
   "method": "textDocument/publishDiagnostics",
   "params": {
      "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
      "diagnostics": []
   }
}
Eval in Emacs: (lsp-bridge-diagnostic--render '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '0)
Eval in Emacs: (lsp-bridge-search-backend--record-items '"search-file-words" '())

--- [11:06:36.295431] Send textDocument/didChange notification to 'tailwindcss' for project someoneinmyhead
{
   "method": "textDocument/didChange",
   "params": {
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
         "version": 4
      },
      "contentChanges": [
         {
            "text": "<script lang=\"ts\">\n  import HamburgerMenu from './HamburgerMenu.svelte';\n  import Logo from './Logo.svelte';\n  import ThemeToggle from './ThemeToggle.svelte';\n  import TopMenuLinks from './TopMenuLinks.svelte';\n  export let open: boolean;\n  export let path: string;\n</script>\n\n<nav\n  class=\"flex flex-nowrap bg-elevation-1 px-3 py-3 w-full sm:px-7 justify-between border-b-2 border-outline-variant mx-\"\n>\n  <Logo />\n  <TopMenuLinks bind:path />\n  <div class=\"flex gap-x-5 justify-end\">\n    <ThemeToggle />\n    <HamburgerMenu bind:open />\n  </div>\n</nav>\n"
         }
      ]
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}

--- [11:06:36.396368] Send textDocument/completion request (53914) to 'tailwindcss' for project someoneinmyhead
{
   "id": 53914,
   "method": "textDocument/completion",
   "params": {
      "position": {
         "line": 10,
         "character": 119
      },
      "context": {
         "triggerCharacter": "-",
         "triggerKind": 2
      },
      "textDocument": {
         "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte"
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}

--- [11:06:36.399611] Recv textDocument/completion response (53914) from 'tailwindcss' for project someoneinmyhead

--- [11:06:36.399894] Got completion candidates (0) from 'tailwindcss' for file NavBar.svelte

--- [11:06:36.400081] Record completion candidates (0) from 'tailwindcss' for file NavBar.svelte
Eval in Emacs: (lsp-bridge-completion--record-items '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '(:line 10 :character 119) '"tailwindcss" '("\"" "'" "`" " " "." "(" "[" "]" "!" "/" "-" ":") '("tailwindcss"))
{
   "jsonrpc": "2.0",
   "id": 53914,
   "result": null
}

--- [11:06:36.798330] Recv textDocument/publishDiagnostics notification from 'tailwindcss' for project someoneinmyhead

--- [11:06:36.798751] Record diagnostics from 'tailwindcss' for file NavBar.svelte
{
   "jsonrpc": "2.0",
   "method": "textDocument/publishDiagnostics",
   "params": {
      "uri": "file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte",
      "diagnostics": []
   }
}
Eval in Emacs: (lsp-bridge-diagnostic--render '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '0)

*** lsp-bridge-try-completion execute predicate 'lsp-bridge-not-only-blank-before-cursor' failed with result: 'nil'

*** lsp-bridge-try-completion execute predicate 'lsp-bridge-not-only-blank-before-cursor' failed with result: 'nil'
artemkovalyov commented 7 months ago

Here's my config for the server:

{
  "name": "tailwindcss",
  "languageId": "tailwindcss",
  "command": [
    "node",
    "/home/artem/.emacs.d/.cache/lsp/tailwindcss/extension/dist/tailwindServer.js",
    "--stdio"
  ],
  "initializationOptions": {
    "configuration": {
      "tailwindCSS": {
        "emmetCompletions": false,
        "showPixelEquivalents": true,
        "rootFontSize": 16,
        "validate": true,
        "hovers": true,
        "suggestions": true,
        "codeActions": true,
        "lint": {
          "invalidScreen": "error",
          "invalidVariant": "error",
          "invalidTailwindDirective": "error",
          "invalidApply": "error",
          "invalidConfigPath": "error",
          "cssConflict": "warning",
          "recommendedVariantOrder": "warning"
        },
        "experimental": {
          "classRegex": ""
        },
        "classAttributes": ["class", "className", "ngClass"]
      }
    }
  }
}
artemkovalyov commented 7 months ago

lsp-bridge-log.json

artemkovalyov commented 7 months ago

Linking the issue I've created in the LSP bridge repo some time ago: https://github.com/manateelazycat/lsp-bridge/issues/882 The maintainer compiled a list of classes and created a completion backend out of them because of failing to make the Tailwind server work. I was blaming everything on configs but didn't find any clue after tons of trial, error, and debugging attempts.

thecrypticace commented 7 months ago

Hey — I just took a look and, you're definitely getting completion messages back from the LSP based on those messages, for example:

--- [11:06:33.482919] Record completion candidates (0) from 'tailwindcss' for file > NavBar.svelte
Eval in Emacs: (lsp-bridge-completion--record-items > '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '(:line 10 :character > 118) '"tailwindcss" '("\"" "'" "`" " " "." "(" "[" "]" "!" "/" "-" ":") '("tailwindcss"))
{
   "jsonrpc": "2.0",
   "id": 10712,
   "result": null
}

This is a "successful" response to a completion request — it's just that the result is null. This is because the languageId being sent when you open the document is incorrect. The tailwindcss language ID is a custom language implemented for CSS files. Because of this it is trying to parse the file as CSS which it is not. The result is that it can't find any applicable completions for it and thus returns null.


You should use svelte for a Svelte file. For example, in the textDocument/didOpen request, I would change it like so:

{
  method: 'textDocument/didOpen',
  params: {
    textDocument: {
      uri: 'file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte',

      // BEGIN: I changed this line
      languageId: 'svelte',
      // END: I changed this line

      version: 0,
      text: "… clipped to make the snippet shorter …",
    },
  },
  message_type: 'notification',
  jsonrpc: '2.0',
},

If you do that, in response to the completion request, you'll get a response with actual data (clipped because it's a LOT of data):

{
  "jsonrpc": "2.0",
  "id": 10712,
  "result": {
    "isIncomplete": false,
    "items": [
      {
        "kind": 9,
        "data": { "_projectKey": "0", "_type": "variant" },
        "command": { "title": "", "command": "editor.action.triggerSuggest" },
        "sortText": "-00000000",
        "label": "*:",
        "detail": "& > *",
        "additionalTextEdits": [],
        "textEdit": {
          "newText": "*:",
          "range": {
            "start": { "line": 10, "character": 116 },
            "end": { "line": 10, "character": 116 }
          }
        }
      }
    ],
    // … omitted …
  }
}

Now I realize that you're using a plugin of some sort that actually communicates with the LSP — I'm not certain what settings you'll need to adjust to make sure it sends the correct language ID across the wire but that's the problem here.

Hope that helps! ✨

artemkovalyov commented 7 months ago

@thecrypticace, thank you, this helps. I'll try to amend what tooling sends and test it as you proposed. I'll get back with results when I have some:)

artemkovalyov commented 7 months ago

@thecrypticace, thanks again for the investigation. I tested and you were right about the language id. I see suggestions now and will try to fix the client implementation to respect it. You helped a lot to crack this puzzle.

manateelazycat commented 7 months ago

@artemkovalyov

Hi, thank you very much for contacting the author of Tailwindcss. I have fixed it in https://github.com/manateelazycat/lsp-bridge/commit/63e8d721d29c66d83ba1e62ccef113b16012a2bd

When the languageId field of tailwindcss.json is empty, lsp-bridge will be based on the file. The extension is dynamically sent to tailwindcss language server.

Thank you for your enthusiastic help

curtainp commented 2 weeks ago

Hey — I just took a look and, you're definitely getting completion messages back from the LSP based on those messages, for example:

--- [11:06:33.482919] Record completion candidates (0) from 'tailwindcss' for file > NavBar.svelte
Eval in Emacs: (lsp-bridge-completion--record-items > '"/umetra/someoneinmyhead/src/lib/components/NavBar.svelte" '"" '() '(:line 10 :character > 118) '"tailwindcss" '("\"" "'" "`" " " "." "(" "[" "]" "!" "/" "-" ":") '("tailwindcss"))
{
   "jsonrpc": "2.0",
   "id": 10712,
   "result": null
}

This is a "successful" response to a completion request — it's just that the result is null. This is because the languageId being sent when you open the document is incorrect. The tailwindcss language ID is a custom language implemented for CSS files. Because of this it is trying to parse the file as CSS which it is not. The result is that it can't find any applicable completions for it and thus returns null.

You should use svelte for a Svelte file. For example, in the textDocument/didOpen request, I would change it like so:

{
  method: 'textDocument/didOpen',
  params: {
    textDocument: {
      uri: 'file:///umetra/someoneinmyhead/src/lib/components/NavBar.svelte',

      // BEGIN: I changed this line
      languageId: 'svelte',
      // END: I changed this line

      version: 0,
      text: "… clipped to make the snippet shorter …",
    },
  },
  message_type: 'notification',
  jsonrpc: '2.0',
},

If you do that, in response to the completion request, you'll get a response with actual data (clipped because it's a LOT of data):

{
  "jsonrpc": "2.0",
  "id": 10712,
  "result": {
    "isIncomplete": false,
    "items": [
      {
        "kind": 9,
        "data": { "_projectKey": "0", "_type": "variant" },
        "command": { "title": "", "command": "editor.action.triggerSuggest" },
        "sortText": "-00000000",
        "label": "*:",
        "detail": "& > *",
        "additionalTextEdits": [],
        "textEdit": {
          "newText": "*:",
          "range": {
            "start": { "line": 10, "character": 116 },
            "end": { "line": 10, "character": 116 }
          }
        }
      }
    ],
    // … omitted …
  }
}

Now I realize that you're using a plugin of some sort that actually communicates with the LSP — I'm not certain what settings you'll need to adjust to make sure it sends the correct language ID across the wire but that's the problem here.

Hope that helps! ✨

Excuse me. @thecrypticace. I'd like to ask what correct languageId should I provide to tailwindcss server. btw, I have a project which create from tauri tutorials, with Nextjs as fronted framework, I have tried nextjs javascript javascriptreact typescript typescriptreact as languageId, but it's not working for me.

my project create with pnpm create next-app --use-pnpm, and follow is project structure:

image

These are the lsp logs:

--- [01:48:35.272262] Send textDocument/didOpen notification to 'tailwindcss' for project retropulse
{
   "method": "textDocument/didOpen",
   "params": {
      "textDocument": {
         "uri": "file:///Users/curtainw/workspace/coding/retropulse/app/page.tsx",
         "languageId": "typescript",
         "version": 0,
         "text": "\"use client\";\nimport { invoke } from \"@tauri-apps/api/core\";\nimport { open } from \"@tauri-apps/plugin-dialog\";\nimport { useRef } from \"react\";\n\nexport default function Home() {\n  const buttonRef = useRef<HTMLButtonElement>(null);\n\n  const handleClick = async () => {\n    if (buttonRef.current!.disabled) {\n      return;\n    }\n    buttonRef.current!.disabled = true;\n    const filepath = await open({\n      multiple: false,\n      directory: false,\n    });\n    if (filepath !== null) {\n      await invoke(\"greet\", { name: filepath });\n    }\n    buttonRef.current!.disabled = false;\n  };\n\n  return (\n    <div className=\"grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]\">\n      <main className=\"flex flex-col gap-8 row-start-2 items-center sm:items-start\">\n        <button\n          className=\"bg-blue-500 font-bold py-2 px-4 rounded\"\n          ref={buttonRef}\n          onClick={() => handleClick()}\n        >\n          Action!\n        </button>\n      </main>\n    </div>\n  );\n}\n"
      }
   },
   "message_type": "notification",
   "jsonrpc": "2.0"
}

--- [01:48:35.324655] Send response to server request 0 to 'tailwindcss' for project retropulse
{
   "id": 0,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}

--- [01:48:35.324756] Send response to server request 1 to 'tailwindcss' for project retropulse
{
   "id": 1,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}
{
   "jsonrpc": "2.0",
   "id": 0,
   "method": "window/workDoneProgress/create",
   "params": {
      "token": "0ad9d2a8-c648-4622-8fc0-591621667821"
   }
}

--- [01:48:35.210561] Send textDocument/signatureHelp request (57827) to 'typescriptreact' for project retropulse

--- [01:48:35.326149] Recv workspace/configuration request (2) from 'tailwindcss' for project retropulse

--- [01:48:35.381859] Recv textDocument/signatureHelp response (57827) from 'typescriptreact' for project retropulse
{
   "id": 57827,
   "method": "textDocument/signatureHelp",
   "params": {
      "position": {
         "line": 0,
         "character": 0
      },
      "textDocument": {
         "uri": "file:///Users/curtainw/workspace/coding/retropulse/app/page.tsx"
      }
   },
   "message_type": "request",
   "jsonrpc": "2.0"
}
{
   "jsonrpc": "2.0",
   "id": 2,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "editor",
            "scopeUri": "file:///Users/curtainw/workspace/coding/retropulse"
         }
      ]
   }
}
{
   "jsonrpc": "2.0",
   "id": 57827,
   "result": null
}

--- [01:48:35.382181] Send response to server request 0 to 'typescriptreact' for project retropulse
{
   "id": 0,
   "result": null,
   "message_type": "response",
   "jsonrpc": "2.0"
}

--- [01:48:35.382209] Send response to server request 2 to 'tailwindcss' for project retropulse

--- [01:48:35.439859] Recv workspace/configuration request (3) from 'tailwindcss' for project retropulse
{
   "id": 2,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}

--- [01:48:35.440117] Send response to server request 3 to 'tailwindcss' for project retropulse

--- [01:48:35.439931] Recv $/progress notification from 'typescriptreact' for project retropulse
{
   "jsonrpc": "2.0",
   "id": 3,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "tailwindCSS",
            "scopeUri": "file:///Users/curtainw/workspace/coding/retropulse"
         }
      ]
   }
}
{
   "id": 3,
   "result": [
      null
   ],
   "message_type": "response",
   "jsonrpc": "2.0"
}
Eval in Emacs: (lsp-bridge--record-work-done-progress '"[LSP-Bridge] Initializing JS/TS language features…")

--- [01:48:35.497928] Recv window/logMessage notification from 'tailwindcss' for project retropulse
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "Searching for Tailwind CSS projects in the workspace's folders."
   }
}

--- [01:48:35.498192] Recv window/logMessage notification from 'tailwindcss' for project retropulse
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "{\"tailwind\":{\"version\":\"3.4.14\",\"features\":[\"layer:base\",\"separator:root\",\"content-list\",\"jit\",\"css-at-config-as-project\",\"relative-content-paths\",\"transpiled-configs\"],\"isDefaultVersion\":false}}"
   }
}

--- [01:48:35.498231] Recv window/logMessage notification from 'tailwindcss' for project retropulse
{
   "jsonrpc": "2.0",
   "method": "$/progress",
   "params": {
      "token": "0ad9d2a8-c648-4622-8fc0-591621667821",
      "value": {
         "kind": "begin",
         "title": "Initializing JS/TS language features\u2026"
      }
   }
}
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "{\"tailwind\":{\"version\":\"3.4.14\",\"features\":[\"layer:base\",\"separator:root\",\"content-list\",\"jit\",\"css-at-config-as-project\",\"relative-content-paths\",\"transpiled-configs\"],\"isDefaultVersion\":false}}"
   }
}

--- [01:48:35.504840] Recv window/logMessage notification from 'tailwindcss' for project retropulse
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 4,
      "message": "[Global] Creating projects: [{\"folder\":\"/Users/curtainw/workspace/coding/retropulse\",\"config\":\"/Users/curtainw/workspace/coding/retropulse/tailwind.config.ts\",\"selectors\":[{\"pattern\":\"/Users/curtainw/workspace/coding/retropulse/tailwind.config.ts\",\"priority\":0},{\"pattern\":\"/Users/curtainw/workspace/coding/retropulse/**\",\"priority\":3},{\"pattern\":\"/Users/curtainw/workspace/coding/retropulse/**\",\"priority\":5}],\"user\":false,\"tailwind\":{\"version\":\"3.4.14\",\"features\":[\"layer:base\",\"separator:root\",\"content-list\",\"jit\",\"css-at-config-as-project\",\"relative-content-paths\",\"transpiled-configs\"],\"isDefaultVersion\":false}}]"
   }
}

--- [01:48:35.562290] Recv client/registerCapability request (4) from 'tailwindcss' for project retropulse
{
   "jsonrpc": "2.0",
   "id": 4,
   "method": "client/registerCapability",
   "params": {
      "registrations": [
         {
            "id": "a10aa59c-d4f5-4db1-8998-e298fb2a1458",
            "method": "workspace/didChangeWatchedFiles",
            "registerOptions": {
               "watchers": [
                  {
                     "globPattern": "**/{tailwind,tailwind.config,tailwind.*.config,tailwind.config.*}.{js,cjs,ts,mjs,mts,cts}"
                  },
                  {
                     "globPattern": "**/{package-lock.json,yarn.lock,pnpm-lock.yaml}"
                  },
                  {
                     "globPattern": "**/*.{css,scss,sass,less,pcss}"
                  }
               ]
            }
         }
      ]
   }
}

--- [01:48:35.562463] Send response to server request 4 to 'tailwindcss' for project retropulse