uqbar-project / wollok-lsp-ide

IDE for Wollok - LSP node-based
GNU General Public License v3.0
7 stars 3 forks source link

¿Cómo se ejecuta el LSP para otros editores? #163

Open tralph3 opened 7 months ago

tralph3 commented 7 months ago

Quisiera saber si hay algún ejecutable que me permita correr el servidor por separado de VSCode para uso en otros editores.

Compilé el proyecto con node, y probé ejecutar el archivo server.js con la flag --stdio. Eso parece funcionar, pero cuando intento usarlo con mi cliente de LSP (eglot) tira el siguiente error y falla instantáneamente:

[stderr]  /home/tralph3/Downloads/extension/server/out/server.js:27
[stderr]  config.forEach(config => environmentProvider.inferTypes = config.typeSystem.enabled);
[stderr]                                                                   ^
[stderr]  
[stderr]  TypeError: Cannot read properties of null (reading 'typeSystem')
[stderr]      at /home/tralph3/Downloads/extension/server/out/server.js:27:66
[stderr]      at Object.next (/home/tralph3/Downloads/extension/server/node_modules/rxjs/dist/cjs/internal/Observable.js:54:25)
[stderr]      at ConsumerObserver.next (/home/tralph3/Downloads/extension/server/node_modules/rxjs/dist/cjs/internal/Subscriber.js:113:33)
[stderr]      at Subscriber._next (/home/tralph3/Downloads/extension/server/node_modules/rxjs/dist/cjs/internal/Subscriber.js:80:26)
[stderr]      at Subscriber.next (/home/tralph3/Downloads/extension/server/node_modules/rxjs/dist/cjs/internal/Subscriber.js:51:18)
[stderr]      at /home/tralph3/Downloads/extension/server/node_modules/rxjs/dist/cjs/internal/Subject.js:69:34
[stderr]      at Object.errorContext (/home/tralph3/Downloads/extension/server/node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9)
[stderr]      at Subject.next (/home/tralph3/Downloads/extension/server/node_modules/rxjs/dist/cjs/internal/Subject.js:59:24)
[stderr]      at /home/tralph3/Downloads/extension/server/out/server.js:100:16
[stderr]  
[stderr]  Node.js v21.7.1

----------b---y---e---b---y---e----------
[stderr]  
[stderr]  
[stderr]  nil
[stderr]  nil
[stderr]  Process EGLOT (tralph3/nil) stderr finished

Eglot también se queja de lo siguiente:

[eglot] Connected! Server `EGLOT (tralph3/nil)' now managing `nil' buffers in project `tralph3'.
[eglot] (warning) Server tried to register unsupported capability `workspace/didChangeConfiguration'
[eglot] (warning) Server tried to register unsupported capability `workspace/didChangeWorkspaceFolders'
[jsonrpc] Server exited with status 1
[eglot] (warning) Not auto-reconnecting, last one didn't last long.

El comando que estoy utilizando para ejecutar el server es node /home/tralph3/Downloads/extension/server/out/server.js --stdio. Está tirado en mi directorio de descargas porque estoy haciendo pruebas.

¿Estoy haciendo algo mal? Gracias.

fdodino commented 6 months ago

Hola @tralph3 , lo que yo tomaría es el archivo client de este proyecto para ver cómo invocar al server. El problema puntual acá es el server no tiene un archivo de configuración y se rompe. Saluditos Fer

tralph3 commented 6 months ago

Hola, estuve leyendo el código y no llego a ver dónde se carga un archivo de configuración. Veo que detecta cambios en los archivos .clientrc. ¿Es eso? ¿Dónde espera encontrar el archivo?

Para ser claro, el LSP debería poder ejecutarse en una terminal independientemente del editor, y luego un cliente se conecta y comienza a comunicarse con él.

No he tenido problemas con otros LSP, y no estoy seguro si estoy haciendo algo mal, o si fue diseñado para uso exclusivo con VSCode.

fdodino commented 6 months ago

Hola, el archivo .clientrc supongo que lo genera en base al package.json: acá es donde hacemos una definición de los valores y eso se puede cambiar desde el VSC mediante Ctrl + , (Settings).

Yendo a tu pregunta puntual,

tralph3 commented 6 months ago

Perfecto, revisaré por mi cuenta entonces como hacerlo y si se necesita hacer alguna modificación al código hago una contribución. Saludos.

tomi2108 commented 5 months ago

@tralph3 Llegaste a algún lado con esto? Yo estuve haciendo unas pruebas para implementar un plugin de NeoVim pero el LSP me responde Error: Missing workspace folder! cuando en la request de init estas las veo bien.

tralph3 commented 5 months ago

Hice algunas pruebas. Parece que el server intenta registrar capacidades que el cliente no soporta. Conseguí establecer una conexión sin que se muera el server, pero no funciona, el cliente envía requests y el server no las responde.

El primer fallo que tiene es acá. Esa línea tira un error que es el que publiqué en el primer mensaje:

TypeError: Cannot read properties of null (reading 'typeSystem')

Si se comenta o se quita, el server sigue sin aparente problema. Luego el cliente se queja de que intenta registrar didChangeWorkspaceFolders.

Para hacer pruebas, establecí el valor de esta variable a false.

Con esto, el cliente se queja una vez más de que el server intenta registrar una capacidad no soportada que es didChangeConfigurationNotification. Se hace acá.

Nuevamente, borrando la línea, se continúa. Con esto, el cliente se puede conectar al server, y envía requests, pero como dije antes no responde. Se queda haciendo nada.

No estoy seguro de como solucionar esto. Si alguien tiene experiencia con el protocolo le agradecería una mano.

Para ejecutar el server primero hago npm compile en el root del proyecto, y luego ejecuto el server.js resultante en la carpeta out con node, especificando --stdio para que la comunicación se haga por los buffers de entrada/salida.

node server.js --stdio
tralph3 commented 5 months ago

Las issues están para esto.

tomi2108 commented 5 months ago

Logre hacer funcionar el LSP hardcodeando el workspace folder en el servidor :? imagen Estas son las capacidades que me devuelve el servidor

{ 
["capabilities"] = {
 ["referencesProvider"] = true,
 ["renameProvider"] = {
   ["prepareProvider"] = true,
 } ,
 ["textDocumentSync"] = { 
  ["save"] = {
    ["includeText"] = false,
  } ,
  ["willSave"] = false,
  ["change"] = 2,
  ["willSaveWaitUntil"] = false,
  ["openClose"] = true,
 } ,
 ["completionProvider"] = { 
  ["triggerCharacters"] = {
   [1] = .,
  } ,
  ["resolveProvider"] = true,
  ["completionItem"] = { 
   ["labelDetailsSupport"] = true,
  } ,
  } ,
 ["codeLensProvider"] = {
  ["resolveProvider"] = true,
 } ,
 ["workspace"] = {
  ["workspaceFolders"] = {
   ["supported"] = true,
  } ,
 } ,
 ["documentRangeFormattingProvider"] = true,
 ["documentFormattingProvider"] = true,
 ["documentSymbolProvider"] = true,
 ["definitionProvider"] = true,
 ["workspaceSymbolProvider"] = true,
 ["hoverProvider"] = true,
 } ,
}

No veo nada de notification que me decis, quizas me estoy perdiendo de algo

tralph3 commented 5 months ago

¿Podrías pasar tu configuración de NeoVim para el server?

tomi2108 commented 5 months ago

function()
  vim.lsp.start_client({
    name = "wollok-lsp",
    cmd = { "node", "path_al_server_js", "--stdio" },
    workspace_folders = {
      {
        uri = "file:path_al_dir_de_prueba", -- esto parece no estar funcionando por ahora... es lo que tuve que hardcodear en el server
        name = "cwd",
      },
    },
    -- before_init = function(params)
    --   local file = io.open("wollok_req.log", "w")
    --   io.output(file)
    --   io.write(dump(params))
    -- end,
    on_init = function(client, params)
      -- local file = io.open("wollok_res.log", "w")
      -- io.output(file)
      -- io.write(dump(params))
      vim.lsp.buf_attach_client(0, client.id) 
    end,
  })
end

Eso es todo para iniciar el server y conectarlo al buffer actual, después hay otras cosas para hacer el coloreado de sintaxis

Estos son los parametros que envia por detras

{ 
["rootUri"] = file:path_de_prueba,
["capabilities"] = { 
["window"] = { 
["workDoneProgress"] = true,
["showMessage"] = { 
["messageActionItem"] = { 
["additionalPropertiesSupport"] = false,
},
},
["showDocument"] = { 
["support"] = true,
},
},
["textDocument"] = { 
["implementation"] = { 
["linkSupport"] = true,
},
["typeDefinition"] = { 
["linkSupport"] = true,
},
["callHierarchy"] = { 
["dynamicRegistration"] = false,
},
["signatureHelp"] = { 
["dynamicRegistration"] = false,
["signatureInformation"] = { 
["documentationFormat"] = { 
[1] = markdown,
[2] = plaintext,
},
["activeParameterSupport"] = true,
["parameterInformation"] = { 
["labelOffsetSupport"] = true,
},
},
},
["documentSymbol"] = { 
["hierarchicalDocumentSymbolSupport"] = true,
["dynamicRegistration"] = false,
["symbolKind"] = { 
["valueSet"] = { 
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 4,
[5] = 5,
[6] = 6,
[7] = 7,
[8] = 8,
[9] = 9,
[10] = 10,
[11] = 11,
[12] = 12,
[13] = 13,
[14] = 14,
[15] = 15,
[16] = 16,
[17] = 17,
[18] = 18,
[19] = 19,
[20] = 20,
[21] = 21,
[22] = 22,
[23] = 23,
[24] = 24,
[25] = 25,
[26] = 26,
},
},
},
["semanticTokens"] = { 
["requests"] = { 
["full"] = { 
["delta"] = true,
},
["range"] = false,
},
["formats"] = { 
[1] = relative,
},
["dynamicRegistration"] = false,
["overlappingTokenSupport"] = true,
["multilineTokenSupport"] = false,
["tokenModifiers"] = { 
[1] = declaration,
[2] = definition,
[3] = readonly,
[4] = static,
[5] = deprecated,
[6] = abstract,
[7] = async,
[8] = modification,
[9] = documentation,
[10] = defaultLibrary,
},
["augmentsSyntaxTokens"] = true,
["tokenTypes"] = { 
[1] = namespace,
[2] = type,
[3] = class,
[4] = enum,
[5] = interface,
[6] = struct,
[7] = typeParameter,
[8] = parameter,
[9] = variable,
[10] = property,
[11] = enumMember,
[12] = event,
[13] = function,
[14] = method,
[15] = macro,
[16] = keyword,
[17] = modifier,
[18] = comment,
[19] = string,
[20] = number,
[21] = regexp,
[22] = operator,
[23] = decorator,
},
["serverCancelSupport"] = false,
},
["completion"] = { 
["contextSupport"] = false,
["completionItemKind"] = { 
["valueSet"] = { 
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 4,
[5] = 5,
[6] = 6,
[7] = 7,
[8] = 8,
[9] = 9,
[10] = 10,
[11] = 11,
[12] = 12,
[13] = 13,
[14] = 14,
[15] = 15,
[16] = 16,
[17] = 17,
[18] = 18,
[19] = 19,
[20] = 20,
[21] = 21,
[22] = 22,
[23] = 23,
[24] = 24,
[25] = 25,
},
},
["dynamicRegistration"] = false,
["completionItem"] = { 
["snippetSupport"] = false,
["commitCharactersSupport"] = false,
["preselectSupport"] = false,
["deprecatedSupport"] = false,
["documentationFormat"] = { 
[1] = markdown,
[2] = plaintext,
},
},
},
["rename"] = { 
["dynamicRegistration"] = false,
["prepareSupport"] = true,
},
["references"] = { 
["dynamicRegistration"] = false,
},
["documentHighlight"] = { 
["dynamicRegistration"] = false,
},
["declaration"] = { 
["linkSupport"] = true,
},
["synchronization"] = { 
["didSave"] = true,
["willSaveWaitUntil"] = true,
["dynamicRegistration"] = false,
["willSave"] = true,
},
["hover"] = { 
["dynamicRegistration"] = false,
["contentFormat"] = { 
[1] = markdown,
[2] = plaintext,
},
},
["codeAction"] = { 
["isPreferredSupport"] = true,
["dataSupport"] = true,
["resolveSupport"] = { 
["properties"] = { 
[1] = edit,
},
},
["codeActionLiteralSupport"] = { 
["codeActionKind"] = { 
["valueSet"] = { 
[1] = ,
[2] = quickfix,
[3] = refactor,
[4] = refactor.extract,
[5] = refactor.inline,
[6] = refactor.rewrite,
[7] = source,
[8] = source.organizeImports,
},
},
},
["dynamicRegistration"] = false,
},
["publishDiagnostics"] = { 
["tagSupport"] = { 
["valueSet"] = { 
[1] = 1,
[2] = 2,
},
},
["relatedInformation"] = true,
},
["definition"] = { 
["linkSupport"] = true,
},
},
["workspace"] = { 
["symbol"] = { 
["hierarchicalWorkspaceSymbolSupport"] = true,
["dynamicRegistration"] = false,
["symbolKind"] = { 
["valueSet"] = { 
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 4,
[5] = 5,
[6] = 6,
[7] = 7,
[8] = 8,
[9] = 9,
[10] = 10,
[11] = 11,
[12] = 12,
[13] = 13,
[14] = 14,
[15] = 15,
[16] = 16,
[17] = 17,
[18] = 18,
[19] = 19,
[20] = 20,
[21] = 21,
[22] = 22,
[23] = 23,
[24] = 24,
[25] = 25,
[26] = 26,
},
},
},
["didChangeWatchedFiles"] = { 
["dynamicRegistration"] = false,
["relativePatternSupport"] = true,
},
["semanticTokens"] = { 
["refreshSupport"] = true,
},
["configuration"] = true,
["applyEdit"] = true,
["workspaceFolders"] = true,
["workspaceEdit"] = { 
["resourceOperations"] = { 
[1] = rename,
[2] = create,
[3] = delete,
},
},
},
},
["trace"] = off,
["workspaceFolders"] = { 
[1] = { 
["uri"] = file:path_de_prueba,
["name"] = cwd,
},
},
["rootPath"] = path_de_prueba,
["processId"] = 15298,
["clientInfo"] = { 
["version"] = 0.9.5,
["name"] = Neovim,
},
}