From aa1efa440867b49f03c137081ed1a64a03bfef60 Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 20:13:57 -0300 Subject: [PATCH 01/12] Fix #128 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 8c87b34..1991fd5 100644 --- a/package.json +++ b/package.json @@ -189,6 +189,7 @@ "scope": "resource", "type": "string", "description": "Path to Wollok-CLI.", + "default": "wollok", "order": 10 }, "wollokLSP.language": { From aac99cb3bf180d2913dda814e2323fe12a39d958 Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 20:15:45 -0300 Subject: [PATCH 02/12] Fix #162 --- packages/debug-adapter/package.json | 5 +- .../server/src/functionalities/definition.ts | 48 +--- .../server/src/functionalities/reporter.ts | 238 +----------------- packages/server/src/settings.ts | 18 +- yarn.lock | 26 +- 5 files changed, 53 insertions(+), 282 deletions(-) diff --git a/packages/debug-adapter/package.json b/packages/debug-adapter/package.json index 0d0ca4a..cab305e 100644 --- a/packages/debug-adapter/package.json +++ b/packages/debug-adapter/package.json @@ -21,6 +21,9 @@ "@types/node": "^18.14.1", "@types/vscode": "^1.92.0", "@vscode/debugadapter-testsupport": "^1.67.0", - "mocha": "^10.7.3" + "mocha": "^10.7.3", + "nyc": "^17.0.0", + "ts-mocha": "^10.0.0", + "wollok-ts": "file:../../../wollok-ts" } } diff --git a/packages/server/src/functionalities/definition.ts b/packages/server/src/functionalities/definition.ts index 6f571b4..b2520b6 100644 --- a/packages/server/src/functionalities/definition.ts +++ b/packages/server/src/functionalities/definition.ts @@ -1,7 +1,7 @@ import { Location, TextDocumentPositionParams } from 'vscode-languageserver' -import { Environment, Method, Module, Node, Reference, Self, Send, Super, is, match, sendDefinitions, when } from 'wollok-ts' -import { getNodesByPosition, nodeToLocation } from '../utils/text-documents' +import { Environment, getNodeDefinition, Method, Node, Send, sendDefinitions } from 'wollok-ts' import { logger } from '../utils/logger' +import { getNodesByPosition, nodeToLocation } from '../utils/text-documents' export const definition = (environment: Environment) => ( textDocumentPosition: TextDocumentPositionParams @@ -13,42 +13,18 @@ export const definition = (environment: Environment) => ( export const getDefinition = (environment: Environment) => (node: Node): Node[] => { try { + if (node.is(Send)) { + // TODO: migrate to wollok-ts + const getDefinitionFromSyntheticMethod = (method: Method) => { + return method.parent.allFields.find((field) => field.name === method.name && field.isProperty) + } + + const definitions = sendDefinitions(environment)(node) + return definitions.map((method: Method) => method.isSynthetic ? getDefinitionFromSyntheticMethod(method) : method) + } return getNodeDefinition(environment)(node) } catch (error) { logger.error(`✘ Error in getDefinition: ${error}`, error) return [node] } -} - -// TODO: terminar de migrar a wollok-ts estas 4 definiciones -export const getNodeDefinition = (environment: Environment) => (node: Node): Node[] => { - try { - return match(node)( - when(Reference)(node => definedOrEmpty(node.target)), - when(Send)(node => mapSyntheticMethods(environment, node)), - when(Super)(node => definedOrEmpty(superMethodDefinition(node))), - when(Self)(node => definedOrEmpty(getParentModule(node))) - ) - } catch { - return [node] - } -} - -const mapSyntheticMethods = (environment: Environment, node: Send) => { - const definitions = sendDefinitions(environment)(node) - return definitions.map((method: Method) => method.isSynthetic ? getDefinitionFromSyntheticMethod(method) : method) -} - -const getDefinitionFromSyntheticMethod = (method: Method) => { - return method.parent.allFields.find((field) => field.name === method.name && field.isProperty) -} - -const superMethodDefinition = (superNode: Super): Method | undefined => { - const currentMethod = superNode.ancestors.find(is(Method))! - const module = getParentModule(superNode) - return module ? module.lookupMethod(currentMethod.name, superNode.args.length, { lookupStartFQN: module.fullyQualifiedName }) : undefined -} - -const getParentModule = (node: Node) => node.ancestors.find(is(Module)) - -const definedOrEmpty = (value: T | undefined): T[] => value ? [value] : [] \ No newline at end of file +} \ No newline at end of file diff --git a/packages/server/src/functionalities/reporter.ts b/packages/server/src/functionalities/reporter.ts index 93c2b86..63dc9db 100644 --- a/packages/server/src/functionalities/reporter.ts +++ b/packages/server/src/functionalities/reporter.ts @@ -1,203 +1,10 @@ -import { Problem } from 'wollok-ts' +import { getMessage, LANGUAGES, Messages, Problem } from 'wollok-ts' import { lang } from '../settings' // ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ -// VALIDATION MESSAGES DEFINITION +// CUSTOM MESSAGES DEFINITION // ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ -type Message = { [key: string]: string } - -const FAILURE = 'failure' - -const validationMessagesEn: Message = { - nameShouldBeginWithLowercase: 'The name {0} must start with lowercase', - nameShouldBeginWithUppercase: 'The name {0} must start with uppercase', - nameShouldNotBeKeyword: - 'The name {0} is a keyword, you should pick another one', - shouldNotBeEmpty: 'Should not make an empty definition.', - shouldUseConditionalExpression: - 'Bad usage of if! You must return the condition itself without using if.', - shouldPassValuesToAllAttributes: '{0} cannot be instantiated, you must pass values to the following attributes: {1}', - namedArgumentShouldExist: 'Reference {0} not found in {1}', - linearizationShouldNotRepeatNamedArguments: - 'Reference {0} is initialized more than once during linearization', - namedArgumentShouldNotAppearMoreThanOnce: - 'Reference {0} is initialized more than once', - shouldInitializeAllAttributes: - 'You must provide initial value to the following references: {0}', - shouldImplementAllMethodsInHierarchy: - 'Methods in hierachy without super implementation: {0}', - shouldUseSelfAndNotSingletonReference: - "Don't use the name within the object. Use 'self' instead.", - shouldNotReassignConst: 'Cannot modify constants', - shouldNotHaveLoopInHierarchy: 'Infinite loop in hierarchy', - shouldOnlyInheritFromMixin: 'Mixin can only inherit from another mixin', - shouldNotDefineMoreThanOneSuperclass: - 'Bad Linearization: you cannot define multiple parent classes', - superclassShouldBeLastInLinearization: - 'Bad Linearization: superclass should be last in linearization', - shouldNotUseOverride: 'Method does not override anything', - possiblyReturningBlock: - "This method is returning a block, consider removing the '=' before curly braces.", - shouldUseOverrideKeyword: - 'Method should be marked as override, since it overrides a superclass method', - shouldMatchSuperclassReturnValue: - 'Superclass method returned value does not match current definition', - getterMethodShouldReturnAValue: 'Getter should return a value', - methodShouldHaveDifferentSignature: 'Duplicated method', - shouldNotDuplicateVariables: - 'There is already a variable with this name in the hierarchy', - shouldNotDuplicateFields: - 'There is already a field with this name in the hierarchy', - shouldNotDuplicateLocalVariables: - 'There is already a local variable with this name in the hierarchy', - shouldNotDuplicateGlobalDefinitions: - 'There is already a definition with this name in the hierarchy', - shouldNotDuplicateVariablesInLinearization: - 'There are attributes with the same name in the hierarchy: [{0}]', - shouldNotDuplicateEntities: - 'This name is already defined (imported from {0})', - shouldNotImportSameFile: 'Cannot import same file', - shouldNotImportMoreThanOnce: 'This file is already imported', - parameterShouldNotDuplicateExistingVariable: 'Duplicated Name', - methodShouldExist: 'Method does not exist or invalid number of arguments', - shouldImplementInheritedAbstractMethods: - 'You must implement all inherited abstract methods', - shouldHaveBody: - 'Method without body. You must implement it', - shouldNotUseVoidMethodAsValue: - 'Message send "{0}" produces no value (missing return in method?)', - shouldNotAssignValueInLoop: 'Infinite loop in value assignment', - shouldInitializeGlobalReference: 'Reference is never initialized', - shouldNotDefineUnusedVariables: 'Unused variable', - shouldNotDefineGlobalMutableVariables: - "Global 'var' references are not allowed. You should use 'const' instead.", - shouldDefineConstInsteadOfVar: 'Variable should be const', - shouldNotCompareEqualityOfSingleton: - 'Comparing against named object is discouraged (missing polymorphism?)', - shouldUseBooleanValueInIfCondition: 'Expecting a boolean', - shouldUseBooleanValueInLogicOperation: 'Expecting a boolean', - shouldNotDefineUnnecesaryIf: 'Unnecessary if always evaluates to true!', - codeShouldBeReachable: 'Unreachable code', - shouldNotDefineUnnecessaryCondition: 'Unnecessary condition', - shouldCatchUsingExceptionHierarchy: - 'Can only catch wollok.lang.Exception or a subclass of it', - catchShouldBeReachable: 'Unreachable catch block', - shouldNotUseReservedWords: '{0} is a reserved name for a core element', - shouldNotDuplicatePackageName: 'Duplicated package', - shouldMatchFileExtension: "The file extension doesn't allow this definition", - shouldHaveNonEmptyName: 'Tests must have a non-empty description', - shouldHaveAssertInTest: - 'Tests must send at least one message to assert object', - overridingMethodShouldHaveABody: 'Overriding method must have a body', - shouldNotDefineEmptyDescribe: 'Describe should not be empty', - shouldNotMarkMoreThanOneOnlyTest: - "You should mark a single test with the flag 'only' (the others will not be executed)", - [FAILURE]: 'Rule failure: ', -} - -const validationMessagesEs: Message = { - nameShouldBeginWithLowercase: - 'El nombre {0} debe comenzar con min\u00FAsculas', - nameShouldBeginWithUppercase: - 'El nombre {0} debe comenzar con may\u00FAsculas', - nameShouldNotBeKeyword: - 'El nombre {0} es una palabra reservada, debe cambiarla', - shouldNotBeEmpty: - 'El elemento no puede estar vac\u00EDo: falta escribir c\u00F3digo.', - shouldUseConditionalExpression: - 'Est\u00E1s usando incorrectamente el if. Devolv\u00E9 simplemente la expresi\u00F3n booleana.', - shouldPassValuesToAllAttributes: 'No se puede instanciar {0}. Falta pasar valores a los siguientes atributos: {1}', - namedArgumentShouldExist: 'No se encuentra la referencia {0} en {1}', - linearizationShouldNotRepeatNamedArguments: - 'La referencia {0} est\u00E1 inicializada m\u00E1s de una vez', - namedArgumentShouldNotAppearMoreThanOnce: - 'La referencia {0} est\u00E1 inicializada m\u00E1s de una vez', - shouldInitializeAllAttributes: - 'Debe proveer un valor inicial a las siguientes referencias: {0}', - shouldImplementAllMethodsInHierarchy: - 'Existen m\u00E9todos en la jerarqu\u00EDa que requieren implementaci\u00F3n en super: {0}', - shouldUseSelfAndNotSingletonReference: - "No debe usar el nombre del objeto dentro del mismo. Use 'self'.", - shouldNotReassignConst: 'No se pueden modificar las referencias constantes', - shouldNotHaveLoopInHierarchy: - 'La jerarqu\u00EDa de clases produce un ciclo infinito', - shouldOnlyInheritFromMixin: - 'Los mixines solo pueden heredar de otros mixines', - shouldNotDefineMoreThanOneSuperclass: - 'Linearizaci\u00F3n: no se puede definir m\u00E1s de una superclase', - superclassShouldBeLastInLinearization: - 'Linearizaci\u00F3n: la superclase deber\u00EDa estar \u00FAltima en linearizaci\u00F3n', - shouldNotUseOverride: - 'Este m\u00E9todo no sobrescribe ning\u00FAn otro m\u00E9todo', - possiblyReturningBlock: - "Este m\u00E9todo devuelve un bloque, si no es la intenci\u00F3n elimine el '=' antes de las llaves.", - shouldUseOverrideKeyword: - "Deber\u00EDa marcarse el m\u00E9todo con 'override', ya que sobrescribe el de sus superclases", - shouldMatchSuperclassReturnValue: - 'El valor del tipo devuelto no coincide con el m\u00E9todo definido en la superclase', - getterMethodShouldReturnAValue: - 'El m\u00E9todo getter debe retornar un valor', - methodShouldHaveDifferentSignature: 'M\u00E9todo duplicado', - shouldNotDuplicateVariables: - 'Ya existe una variable con este nombre en la jerarqu\u00EDa', - shouldNotDuplicateFields: - 'Ya existe un atributo con este nombre en la jerarqu\u00EDa', - shouldNotDuplicateLocalVariables: - 'Ya existe una variable local con este nombre en la jerarqu\u00EDa', - shouldNotDuplicateGlobalDefinitions: - 'Ya existe una definici\u00F3n con este nombre en la jerarqu\u00EDa', - shouldNotDuplicateVariablesInLinearization: - 'En la jerarqu\u00EDa hay atributos con el mismo nombre: [{0}]', - shouldNotDuplicateEntities: - 'Este nombre ya est\u00E1 definido (importado de {0})', - shouldNotImportSameFile: 'No se puede importar el mismo archivo', - shouldNotImportMoreThanOnce: 'Este archivo ya est\u00E1 importado', - parameterShouldNotDuplicateExistingVariable: 'Nombre duplicado', - methodShouldExist: - 'El m\u00E9todo no existe o n\u00FAmero incorrecto de argumentos', - shouldImplementInheritedAbstractMethods: - 'Debe implementar todos los m\u00E9todos abstractos heredados', - shouldHaveBody: - 'El método debe tener una implementación', - shouldNotUseVoidMethodAsValue: - 'El mensaje "{0}" no retorna ning\u00FAn valor (quiz\u00E1s te falte un return en el m\u00E9todo)', - shouldNotAssignValueInLoop: 'Se genera un loop infinito en la asignaci\u00F3n del valor', - shouldInitializeGlobalReference: 'La referencia nunca se inicializa', - shouldNotDefineUnusedVariables: 'Esta variable nunca se utiliza', - shouldNotDefineGlobalMutableVariables: - 'Solo se permiten las variables globales de tipo const', - shouldDefineConstInsteadOfVar: 'Esta variable deber\u00EDa ser una constante', - shouldNotCompareEqualityOfSingleton: - 'No se aconseja comparar objetos nombrados, considere utilizar polimorfismo.', - shouldUseBooleanValueInIfCondition: 'Se espera un booleano', - shouldUseBooleanValueInLogicOperation: 'Se espera un booleano', - shouldNotDefineUnnecesaryIf: - 'If innecesario. Siempre se eval\u00FAa como verdadero', - codeShouldBeReachable: 'Este c\u00F3digo nunca se va a ejecutar', - shouldNotDefineUnnecessaryCondition: 'Condici\u00F3n innecesaria', - shouldCatchUsingExceptionHierarchy: - "Solo se puede aplicar 'catch' a un objeto de tipo wollok.lang.Exception o una subclase", - catchShouldBeReachable: - 'Este catch nunca se va a ejecutar debido a otro catch anterior', - shouldNotUseReservedWords: - '{0} es una palabra reservada por la biblioteca de Wollok', - shouldNotDuplicatePackageName: 'Package duplicado', - shouldMatchFileExtension: - 'La extensi\u00F3n del archivo no permite esta definici\u00F3n', - shouldHaveNonEmptyName: - 'Los tests deben tener una descripci\u00F3n no vac\u00EDa', - shouldHaveAssertInTest: - 'Los tests deben enviar al menos un mensaje al WKO "assert"', - overridingMethodShouldHaveABody: - 'Si sobrescribe debe especificar el cuerpo del m\u00E9todo', - shouldNotDefineEmptyDescribe: 'El describe no deber\u00EDa estar vac\u00EDo', - shouldNotMarkMoreThanOneOnlyTest: - "Solo un test puede marcarse como 'only' (los otros no se ejecutar\u00E1n)", - [FAILURE]: 'La siguiente regla fall\u00F3: ', -} - - const MISSING_WOLLOK_TS_CLI = 'missing_wollok_ts_cli' const lspMessagesEn = { @@ -208,50 +15,21 @@ const lspMessagesEs = { [MISSING_WOLLOK_TS_CLI]: 'Falta la configuración WollokLSP/cli-path para poder ejecutar tareas de Wollok', } -const messages: { [key: string]: Message } = { - en: { - ...validationMessagesEn, +const lspMessages: Messages = { + [LANGUAGES.ENGLISH]: { ...lspMessagesEn, }, - es: { - ...validationMessagesEs, + [LANGUAGES.SPANISH]: { ...lspMessagesEs, }, } -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ -// INTERNAL FUNCTIONS -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ - -const convertToHumanReadable = (code: string) => { - if (!code) { - return '' - } - const result = code.replace( - /[A-Z0-9]+/g, - (match) => ' ' + match.toLowerCase() - ) - return ( - validationI18nized()[FAILURE] + - result.charAt(0).toUpperCase() + - result.slice(1, result.length) - ) -} - -const interpolateValidationMessage = (message: string, ...values: string[]) => - message.replace(/{\d*}/g, (match: string) => { - const index = match.replace('{', '').replace('}', '') as unknown as number - return values[index] || '' - }) - -const validationI18nized = () => messages[lang()] as Message - // ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ // PUBLIC INTERFACE // ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ export const reportValidationMessage = (problem: Problem): string => - getMessage(problem.code, problem.values.concat()) + getMessage({ message: problem.code, values: problem.values.concat(), language: lang() }) -export const getMessage = (message: string, values: string[]): string => - interpolateValidationMessage(validationI18nized()[message] || convertToHumanReadable(message), ...values) +export const getLSPMessage = (message: string, values: string[]): string => + getMessage({ message, values, language: lang(), customMessages: lspMessages }) diff --git a/packages/server/src/settings.ts b/packages/server/src/settings.ts index 4fa8ccb..3673326 100644 --- a/packages/server/src/settings.ts +++ b/packages/server/src/settings.ts @@ -1,9 +1,10 @@ import { Connection } from 'vscode-languageserver/node' import { wollokLSPExtensionCode } from './shared-definitions' +import { LANGUAGES } from 'wollok-ts' export interface WollokLSPSettings { maxNumberOfProblems: number - language: string, + language: LANGUAGES, openDynamicDiagramOnRepl: boolean, openInternalDynamicDiagram: boolean, dynamicDiagramDarkMode: boolean, @@ -15,13 +16,10 @@ export interface WollokLSPSettings { // INTERNAL & PUBLISHED STATE // ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ -const SPANISH = 'es' -const ENGLISH = 'en' - const envLang = () => { const env = process.env - const fullLanguage = env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE - return fullLanguage ? fullLanguage.substring(0, 2) : SPANISH + const fullLanguage = env.LC_ALL ?? env.LC_MESSAGES ?? env.LANG ?? env.LANGUAGE + return fullLanguage === 'es' ? LANGUAGES.SPANISH : LANGUAGES.ENGLISH } const defaultSettings: WollokLSPSettings = { @@ -36,9 +34,9 @@ const defaultSettings: WollokLSPSettings = { let globalSettings: WollokLSPSettings = defaultSettings -const languageDescription: { [key: string]: string } = { - Spanish: SPANISH, - English: ENGLISH, +const languageDescription: { [key: string]: LANGUAGES } = { + Spanish: LANGUAGES.SPANISH, + English: LANGUAGES.ENGLISH, } // ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ @@ -59,7 +57,7 @@ export const initializeSettings = async ( await updateDocumentSettings(connection) } -export const lang = (): string => +export const lang = (): LANGUAGES => languageDescription[globalSettings.language] || envLang() export const maxThreshold = (): number => globalSettings.maxThreshold diff --git a/yarn.lock b/yarn.lock index 4fe6d49..5630812 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8865,6 +8865,9 @@ __metadata: "@vscode/debugadapter-testsupport": "npm:^1.67.0" "@vscode/debugprotocol": "npm:^1.66.0" mocha: "npm:^10.7.3" + nyc: "npm:^17.0.0" + ts-mocha: "npm:^10.0.0" + wollok-ts: "file:../../../wollok-ts" languageName: unknown linkType: soft @@ -8927,21 +8930,34 @@ __metadata: source-map-support: "npm:^0.5.21" ts-node: "npm:^10.9.1" typescript: "npm:^4.9.5" - wollok-ts: "npm:4.1.6" + wollok-ts: "file:../wollok-ts" yarn-run-all: "npm:^3.1.1" languageName: unknown linkType: soft -"wollok-ts@npm:4.1.6": - version: 4.1.6 - resolution: "wollok-ts@npm:4.1.6" +"wollok-ts@file:../../../wollok-ts::locator=wollok-debug-adapter%40workspace%3Apackages%2Fdebug-adapter": + version: 4.1.7 + resolution: "wollok-ts@file:../../../wollok-ts#../../../wollok-ts::hash=3281d5&locator=wollok-debug-adapter%40workspace%3Apackages%2Fdebug-adapter" + dependencies: + "@types/parsimmon": "npm:^1.10.8" + parsimmon: "npm:^1.18.1" + prettier-printer: "npm:^1.1.4" + unraw: "npm:^3.0.0" + uuid: "npm:^9.0.1" + checksum: 10c0/516142fe553ce7787dfb070217273c943b1d08d66b1992cd43036c7f7345fc3244bd83919153437a5cf3986bbcaee8f6bfb2cef8f607ff0c278bccdd9fa56f16 + languageName: node + linkType: hard + +"wollok-ts@file:../wollok-ts::locator=wollok-lsp-ide%40workspace%3A.": + version: 4.1.7 + resolution: "wollok-ts@file:../wollok-ts#../wollok-ts::hash=3281d5&locator=wollok-lsp-ide%40workspace%3A." dependencies: "@types/parsimmon": "npm:^1.10.8" parsimmon: "npm:^1.18.1" prettier-printer: "npm:^1.1.4" unraw: "npm:^3.0.0" uuid: "npm:^9.0.1" - checksum: 10c0/2248c12858540699ce9c58b6e22255d2dd685ef0ae1c32ca023cc0a7c9d8489057a5b0600c0291e4f45cb831dc4c7ccd43de73b4c041b8569300d66c0c7bbbcf + checksum: 10c0/516142fe553ce7787dfb070217273c943b1d08d66b1992cd43036c7f7345fc3244bd83919153437a5cf3986bbcaee8f6bfb2cef8f607ff0c278bccdd9fa56f16 languageName: node linkType: hard From 104b41ef8856267c4abb1dedecdecb1d9af9ee8e Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 20:16:21 -0300 Subject: [PATCH 03/12] Undo local dependency --- packages/debug-adapter/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/debug-adapter/package.json b/packages/debug-adapter/package.json index cab305e..67cab7f 100644 --- a/packages/debug-adapter/package.json +++ b/packages/debug-adapter/package.json @@ -24,6 +24,6 @@ "mocha": "^10.7.3", "nyc": "^17.0.0", "ts-mocha": "^10.0.0", - "wollok-ts": "file:../../../wollok-ts" + "wollok-ts": "4.1.6" } } From 789bc4e6ad9b1def83dce858fb4e166eb61a4615 Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 20:19:09 -0300 Subject: [PATCH 04/12] Undo local dependency --- yarn.lock | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5630812..700684a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8867,7 +8867,7 @@ __metadata: mocha: "npm:^10.7.3" nyc: "npm:^17.0.0" ts-mocha: "npm:^10.0.0" - wollok-ts: "file:../../../wollok-ts" + wollok-ts: "npm:4.1.6" languageName: unknown linkType: soft @@ -8930,34 +8930,21 @@ __metadata: source-map-support: "npm:^0.5.21" ts-node: "npm:^10.9.1" typescript: "npm:^4.9.5" - wollok-ts: "file:../wollok-ts" + wollok-ts: "npm:4.1.6" yarn-run-all: "npm:^3.1.1" languageName: unknown linkType: soft -"wollok-ts@file:../../../wollok-ts::locator=wollok-debug-adapter%40workspace%3Apackages%2Fdebug-adapter": - version: 4.1.7 - resolution: "wollok-ts@file:../../../wollok-ts#../../../wollok-ts::hash=3281d5&locator=wollok-debug-adapter%40workspace%3Apackages%2Fdebug-adapter" +"wollok-ts@npm:4.1.6": + version: 4.1.6 + resolution: "wollok-ts@npm:4.1.6" dependencies: "@types/parsimmon": "npm:^1.10.8" parsimmon: "npm:^1.18.1" prettier-printer: "npm:^1.1.4" unraw: "npm:^3.0.0" uuid: "npm:^9.0.1" - checksum: 10c0/516142fe553ce7787dfb070217273c943b1d08d66b1992cd43036c7f7345fc3244bd83919153437a5cf3986bbcaee8f6bfb2cef8f607ff0c278bccdd9fa56f16 - languageName: node - linkType: hard - -"wollok-ts@file:../wollok-ts::locator=wollok-lsp-ide%40workspace%3A.": - version: 4.1.7 - resolution: "wollok-ts@file:../wollok-ts#../wollok-ts::hash=3281d5&locator=wollok-lsp-ide%40workspace%3A." - dependencies: - "@types/parsimmon": "npm:^1.10.8" - parsimmon: "npm:^1.18.1" - prettier-printer: "npm:^1.1.4" - unraw: "npm:^3.0.0" - uuid: "npm:^9.0.1" - checksum: 10c0/516142fe553ce7787dfb070217273c943b1d08d66b1992cd43036c7f7345fc3244bd83919153437a5cf3986bbcaee8f6bfb2cef8f607ff0c278bccdd9fa56f16 + checksum: 10c0/2248c12858540699ce9c58b6e22255d2dd685ef0ae1c32ca023cc0a7c9d8489057a5b0600c0291e4f45cb831dc4c7ccd43de73b4c041b8569300d66c0c7bbbcf languageName: node linkType: hard From d82b272675b7f567c79527ec9b6ab42536d9380e Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 20:51:11 -0300 Subject: [PATCH 05/12] Fix #186 --- package.json | 7 + packages/client/src/commands.ts | 7 +- packages/server/src/settings.ts | 4 + server/coverage/base.css | 224 +++++++ server/coverage/block-navigation.js | 87 +++ server/coverage/index.html | 176 ++++++ server/coverage/prettify.css | 1 + server/coverage/prettify.js | 2 + server/coverage/sorter.js | 196 ++++++ .../autocomplete/autocomplete.ts.html | 580 ++++++++++++++++++ .../functionalities/autocomplete/index.html | 161 +++++ .../autocomplete/node-completion.ts.html | 337 ++++++++++ .../autocomplete/options-autocomplete.ts.html | 574 +++++++++++++++++ .../autocomplete/send-completion.ts.html | 232 +++++++ server/coverage/src/index.html | 146 +++++ server/coverage/src/settings.ts.html | 280 +++++++++ .../coverage/src/shared-definitions.ts.html | 118 ++++ .../src/test/mocks/file-contents.ts.html | 106 ++++ server/coverage/src/test/mocks/index.html | 116 ++++ server/coverage/src/test/utils/index.html | 116 ++++ .../src/test/utils/wollok-test-utils.ts.html | 100 +++ server/coverage/src/time-measurer.ts.html | 235 +++++++ server/coverage/src/utils/index.html | 146 +++++ server/coverage/src/utils/logger.ts.html | 181 ++++++ server/coverage/src/utils/strings.ts.html | 88 +++ .../coverage/src/utils/text-documents.ts.html | 517 ++++++++++++++++ server/coverage/src/utils/vm/index.html | 116 ++++ server/coverage/src/utils/vm/wollok.ts.html | 346 +++++++++++ 28 files changed, 5196 insertions(+), 3 deletions(-) create mode 100644 server/coverage/base.css create mode 100644 server/coverage/block-navigation.js create mode 100644 server/coverage/index.html create mode 100644 server/coverage/prettify.css create mode 100644 server/coverage/prettify.js create mode 100644 server/coverage/sorter.js create mode 100644 server/coverage/src/functionalities/autocomplete/autocomplete.ts.html create mode 100644 server/coverage/src/functionalities/autocomplete/index.html create mode 100644 server/coverage/src/functionalities/autocomplete/node-completion.ts.html create mode 100644 server/coverage/src/functionalities/autocomplete/options-autocomplete.ts.html create mode 100644 server/coverage/src/functionalities/autocomplete/send-completion.ts.html create mode 100644 server/coverage/src/index.html create mode 100644 server/coverage/src/settings.ts.html create mode 100644 server/coverage/src/shared-definitions.ts.html create mode 100644 server/coverage/src/test/mocks/file-contents.ts.html create mode 100644 server/coverage/src/test/mocks/index.html create mode 100644 server/coverage/src/test/utils/index.html create mode 100644 server/coverage/src/test/utils/wollok-test-utils.ts.html create mode 100644 server/coverage/src/time-measurer.ts.html create mode 100644 server/coverage/src/utils/index.html create mode 100644 server/coverage/src/utils/logger.ts.html create mode 100644 server/coverage/src/utils/strings.ts.html create mode 100644 server/coverage/src/utils/text-documents.ts.html create mode 100644 server/coverage/src/utils/vm/index.html create mode 100644 server/coverage/src/utils/vm/wollok.ts.html diff --git a/package.json b/package.json index 1991fd5..8ee4e7b 100644 --- a/package.json +++ b/package.json @@ -223,6 +223,13 @@ "description": "Traces the communication between VS Code and the language server.", "order": 20 }, + "wollokLSP.repl.portNumber": { + "scope": "resource", + "type": "number", + "default": 3000, + "description": "Port number that will be used when running the REPL.", + "order": 25 + }, "wollokLSP.dynamicDiagram.openDynamicDiagramOnRepl": { "scope": "resource", "type": "boolean", diff --git a/packages/client/src/commands.ts b/packages/client/src/commands.ts index 3b9a943..bfee1fa 100644 --- a/packages/client/src/commands.ts +++ b/packages/client/src/commands.ts @@ -14,6 +14,7 @@ import { fsToShell, } from './platform-string-utils' import { COMMAND_RUN_ALL_TESTS, COMMAND_RUN_GAME, COMMAND_RUN_PROGRAM, COMMAND_RUN_TEST, COMMAND_START_REPL, wollokLSPExtensionCode, COMMAND_INIT_PROJECT } from './shared-definitions' +import { DEFAULT_PORT } from '../../server/src/settings' export const subscribeWollokCommands = (context: ExtensionContext): void => { context.subscriptions.push(registerCLICommand(COMMAND_START_REPL, startRepl)) @@ -74,16 +75,16 @@ const getCurrentFileName = (document: vscode.TextDocument | undefined) => const getFiles = (document: vscode.TextDocument | undefined): [ReturnType] | [] => document ? [fsToShell(document.uri.fsPath)] : [] -const DYNAMIC_DIAGRAM_URI = 'http://localhost:3000/' - export const startRepl = (): Task => { const currentDocument = window.activeTextEditor?.document const wollokLSPConfiguration = workspace.getConfiguration(wollokLSPExtensionCode) const dynamicDiagramDarkMode = wollokLSPConfiguration.get('dynamicDiagram.dynamicDiagramDarkMode') as boolean const openDynamicDiagram = wollokLSPConfiguration.get('dynamicDiagram.openDynamicDiagramOnRepl') as boolean const millisecondsToOpenDynamicDiagram = wollokLSPConfiguration.get('dynamicDiagram.millisecondsToOpenDynamicDiagram') as number + const portNumber = wollokLSPConfiguration.get('repl.portNumber') as number ?? DEFAULT_PORT + const DYNAMIC_DIAGRAM_URI = `http://localhost:${portNumber}/` - const cliCommands = [`repl`, ...getFiles(currentDocument), '--skipValidations', dynamicDiagramDarkMode ? '--darkMode' : '', openDynamicDiagram ? '': '--skipDiagram'] + const cliCommands = [`repl`, ...getFiles(currentDocument), '--skipValidations', '--port', portNumber.toString(), dynamicDiagramDarkMode ? '--darkMode' : '', openDynamicDiagram ? '': '--skipDiagram'] // Terminate previous tasks vscode.commands.executeCommand('workbench.action.terminal.killAll') const replTask = wollokCLITask('repl', `Wollok Repl: ${getCurrentFileName(currentDocument)}`, cliCommands) diff --git a/packages/server/src/settings.ts b/packages/server/src/settings.ts index 3673326..bca4198 100644 --- a/packages/server/src/settings.ts +++ b/packages/server/src/settings.ts @@ -2,9 +2,12 @@ import { Connection } from 'vscode-languageserver/node' import { wollokLSPExtensionCode } from './shared-definitions' import { LANGUAGES } from 'wollok-ts' +export const DEFAULT_PORT = 3000 + export interface WollokLSPSettings { maxNumberOfProblems: number language: LANGUAGES, + portNumber: number, openDynamicDiagramOnRepl: boolean, openInternalDynamicDiagram: boolean, dynamicDiagramDarkMode: boolean, @@ -25,6 +28,7 @@ const envLang = () => { const defaultSettings: WollokLSPSettings = { maxNumberOfProblems: 1000, language: envLang(), + portNumber: DEFAULT_PORT, openDynamicDiagramOnRepl: true, openInternalDynamicDiagram: true, dynamicDiagramDarkMode: true, diff --git a/server/coverage/base.css b/server/coverage/base.css new file mode 100644 index 0000000..f418035 --- /dev/null +++ b/server/coverage/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/server/coverage/block-navigation.js b/server/coverage/block-navigation.js new file mode 100644 index 0000000..cc12130 --- /dev/null +++ b/server/coverage/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/server/coverage/index.html b/server/coverage/index.html new file mode 100644 index 0000000..1da944c --- /dev/null +++ b/server/coverage/index.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 80.79% + Statements + 265/328 +
+ + +
+ 62.57% + Branches + 107/171 +
+ + +
+ 73.62% + Functions + 67/91 +
+ + +
+ 80.3% + Lines + 208/259 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
92.3%48/5256.25%9/1678.57%11/1493.33%42/45
src/functionalities/autocomplete +
+
90.36%150/16673.21%82/11288.46%46/5290.22%120/133
src/test/mocks +
+
100%1/1100%0/0100%0/0100%1/1
src/test/utils +
+
100%4/4100%0/0100%1/1100%4/4
src/utils +
+
59.04%62/10537.2%16/4337.5%9/2453.94%41/76
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/prettify.css b/server/coverage/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/server/coverage/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/server/coverage/prettify.js b/server/coverage/prettify.js new file mode 100644 index 0000000..b322523 --- /dev/null +++ b/server/coverage/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/server/coverage/sorter.js b/server/coverage/sorter.js new file mode 100644 index 0000000..2bb296a --- /dev/null +++ b/server/coverage/sorter.js @@ -0,0 +1,196 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if ( + row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()) + ) { + row.style.display = ''; + } else { + row.style.display = 'none'; + } + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/server/coverage/src/functionalities/autocomplete/autocomplete.ts.html b/server/coverage/src/functionalities/autocomplete/autocomplete.ts.html new file mode 100644 index 0000000..4e24b55 --- /dev/null +++ b/server/coverage/src/functionalities/autocomplete/autocomplete.ts.html @@ -0,0 +1,580 @@ + + + + + + Code coverage report for src/functionalities/autocomplete/autocomplete.ts + + + + + + + + + +
+
+

All files / src/functionalities/autocomplete autocomplete.ts

+
+ +
+ 81.25% + Statements + 65/80 +
+ + +
+ 60.78% + Branches + 31/51 +
+ + +
+ 79.16% + Functions + 19/24 +
+ + +
+ 81.25% + Lines + 52/64 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +1661x +1x +1x +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +1x +  +9x +97x +97x +  +97x +97x +  +  +  +  +11x +11x +  +  +  +  +97x +  +  +  +  +  +  +  +  +1x +932x +932x +  +  +1x +972x +  +768x +  +  +35x +  +  +153x +  +  +16x +  +  +  +  +975x +  +1x +932x +750x +585x +585x +  +  +1x +932x +932x +  +  +  +  +  +  +623x +  +  +  +  +  +  +66x +  +  +  +68x +76x +  +  +  +  +  +  +  +  +  +1x +30x +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +1x +13x +13x +  +  +  +  +10x +  +  +3x +  +  +  + 
import { CompletionItem, CompletionItemKind, CompletionParams, InsertTextFormat, Position, TextEdit } from 'vscode-languageserver'
+import { Class, Entity, Field, Method, Mixin, Module, Name, Node, OBJECT_MODULE, Parameter, Reference, Singleton, Environment, Import, parentModule, getAllUninitializedAttributes } from 'wollok-ts'
+import { TimeMeasurer } from '../../time-measurer'
+import { cursorNode, relativeFilePath, packageToURI } from '../../utils/text-documents'
+import { isNotImportedIn } from 'wollok-ts'
+import { completionsForNode } from './node-completion'
+import { completeMessages } from './send-completion'
+import { match, when } from 'wollok-ts/dist/extensions'
+ 
+export const completions = (environment: Environment) => (
+  params: CompletionParams,
+): CompletionItem[] => {
+  const timeMeasurer = new TimeMeasurer()
+ 
+  const { position, textDocument, context } = params
+  const selectionNode = cursorNode(environment, position, textDocument)
+ 
+  timeMeasurer.addTime(`Autocomplete - ${selectionNode?.kind}`)
+ 
+  const autocompleteMessages = context?.triggerCharacter === '.' && !selectionNode.parent.is(Import)
+  if (autocompleteMessages) {
+    // ignore dot
+    position.character -= 1
+  }
+  const result = autocompleteMessages ? completeMessages(environment, selectionNode) : completionsForNode(selectionNode)
+  timeMeasurer.finalReport()
+  return result
+}
+ 
+// -----------------
+// -----MAPPERS-----
+// -----------------
+type CompletionItemMapper<T extends Node> = (node: T) => CompletionItem
+ 
+export const parameterCompletionItem: CompletionItemMapper<Parameter> = namedCompletionItem(CompletionItemKind.Variable)
+ 
+export const fieldCompletionItem: CompletionItemMapper<Field> = namedCompletionItem(CompletionItemKind.Field)
+ 
+export const singletonCompletionItem: CompletionItemMapper<Singleton> = moduleCompletionItem(CompletionItemKind.Class)
+ 
+export const withImport = <T extends Node>(mapper: CompletionItemMapper<T>) => (relativeTo: Node): CompletionItemMapper<T> => (node) => {
+  const importedPackage = node.parentPackage!
+  const originalPackage = relativeTo.parentPackage!
+ 
+  const result = mapper(node)
+  if(
+    importedPackage &&
+    originalPackage &&
+    isNotImportedIn(importedPackage, originalPackage)
+  ) {
+    result.detail = `Add import ${importedPackage.fileName ? relativeFilePath(packageToURI(importedPackage)) : importedPackage.name}${result.detail ? ` - ${result.detail}` : ''}`
+    result.additionalTextEdits = (result.additionalTextEdits ?? []).concat(
+      TextEdit.insert(Position.create(0, 0), `import ${importedPackage.name}.*\n`)
+    )
+  }
+ 
+  return result
+}
+/**
+ * We want
+ * - first: methods belonging to the same file we are using
+ * - then, concrete classes/singletons
+ * - then, library methods having this order: 1. lang, 2. lib, 3. game
+ * - and last: object
+ */
+const getSortText = (node: Node, method: Method) => {
+  const methodContainer = parentModule(method)
+  return formatSortText((node.sourceFileName === method.sourceFileName ? 1 : getLibraryIndex(method)) + additionalIndex(method, methodContainer))
+}
+ 
+const getLibraryIndex = (node: Node) => {
+  switch (node.sourceFileName) {
+    case 'wollok/lang.wlk': {
+      return 20
+    }
+    case 'wollok/lib.wlk': {
+      return 30
+    }
+    case 'wollok/game.wlk': {
+      return 40
+    }
+    default: {
+      return 10
+    }
+  }
+}
+ 
+const formatSortText = (index: number) => ('000' + index).slice(-3)
+ 
+const additionalIndex = (method: Method, methodContainer: Module): number => {
+  if (methodContainer.fullyQualifiedName === OBJECT_MODULE) return 50
+  if (methodContainer instanceof Class && methodContainer.isAbstract) return 5
+  Iif (method.isAbstract()) return 3
+  return 1
+}
+ 
+export const methodCompletionItem = (node: Node, method: Method): CompletionItem => {
+  const params = method.parameters.map((parameter, i) => `\${${i+1}:${parameter.name}}`).join(', ')
+  return {
+    label: method.name,
+    filterText: method.name,
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: `${method.name}(${params})`,
+    kind: CompletionItemKind.Method,
+    detail: `${method.parent.name} \n\n\n File ${method.parent.sourceFileName?.split('/').pop()}`,
+    labelDetails: { description: method.parent.name, detail: `(${method.parameters.map(parameter => parameter.name).join(', ')})` },
+    sortText: getSortText(node, method),
+  }
+}
+ 
+ 
+function moduleCompletionItem<T extends Module>(kind: CompletionItemKind){
+  return (module: T) => namedCompletionItem(kind)(module.name ? module as {name: Name} : { name: 'unnamed' })
+}
+ 
+function namedCompletionItem<T extends {name: string}>(kind: CompletionItemKind) {
+  return (namedNode: T): CompletionItem => {
+    return {
+      label: namedNode.name,
+      insertText: namedNode.name,
+      insertTextFormat: InsertTextFormat.PlainText,
+      kind,
+      sortText: '001',
+    }
+  }
+}
+ 
+export const classCompletionItem = (clazz: Class): CompletionItem => {
+  return {
+    label: clazz.name,
+    filterText: clazz.name,
+    insertTextFormat: InsertTextFormat.PlainText,
+    insertText: `${clazz.name}`,
+    kind: CompletionItemKind.Class,
+    detail: `${clazz.name} \n\n\n File ${clazz.parent.sourceFileName?.split('/').pop()}`,
+    sortText: formatSortText(getLibraryIndex(clazz)),
+  }
+}
+ 
+export const initializerCompletionItem = (clazz: Class): CompletionItem => {
+  const initializers = getAllUninitializedAttributes(clazz).map((attributeName, i) => `\${${2*i+1}:${attributeName}} = \${${2*i+2}}`).join(', ')
+  return {
+    label: 'initializers',
+    filterText: 'initializers',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: initializers,
+    kind: CompletionItemKind.Constructor,
+    sortText: '010',
+  }
+}
+ 
+export const entityCompletionItem = (entity: Entity): CompletionItem => {
+  const label = entity.fullyQualifiedName
+  return {
+    label,
+    filterText: label,
+    insertTextFormat: InsertTextFormat.PlainText,
+    kind: match(entity)(
+      when(Class)(() => CompletionItemKind.Class),
+      when(Mixin)(() => CompletionItemKind.Interface),
+      when(Reference)(() => CompletionItemKind.Reference),
+      when(Singleton)(() => CompletionItemKind.Module),
+    ),
+    sortText: formatSortText(getLibraryIndex(entity)),
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/functionalities/autocomplete/index.html b/server/coverage/src/functionalities/autocomplete/index.html new file mode 100644 index 0000000..5c28fcd --- /dev/null +++ b/server/coverage/src/functionalities/autocomplete/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/functionalities/autocomplete + + + + + + + + + +
+
+

All files src/functionalities/autocomplete

+
+ +
+ 90.36% + Statements + 150/166 +
+ + +
+ 73.21% + Branches + 82/112 +
+ + +
+ 88.46% + Functions + 46/52 +
+ + +
+ 90.22% + Lines + 120/133 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
autocomplete.ts +
+
81.25%65/8060.78%31/5179.16%19/2481.25%52/64
node-completion.ts +
+
98%49/5080%28/3594.44%17/1897.14%34/35
options-autocomplete.ts +
+
100%13/13100%0/0100%0/0100%13/13
send-completion.ts +
+
100%23/2388.46%23/26100%10/10100%21/21
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/functionalities/autocomplete/node-completion.ts.html b/server/coverage/src/functionalities/autocomplete/node-completion.ts.html new file mode 100644 index 0000000..f13961d --- /dev/null +++ b/server/coverage/src/functionalities/autocomplete/node-completion.ts.html @@ -0,0 +1,337 @@ + + + + + + Code coverage report for src/functionalities/autocomplete/node-completion.ts + + + + + + + + + +
+
+

All files / src/functionalities/autocomplete node-completion.ts

+
+ +
+ 98% + Statements + 49/50 +
+ + +
+ 80% + Branches + 28/35 +
+ + +
+ 94.44% + Functions + 17/18 +
+ + +
+ 97.14% + Lines + 34/35 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85  +1x +1x +1x +1x +  +1x +27x +27x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +2x +  +1x +  +1x +  +  +  +  +  +1x +  +  +  +1x +  +  +  +  +8x +  +  +  +  +3x +  +1x +7x +7x +7x +  +  +34653x +  +  +  +1x +  +1x +12x +11x +  +  +1x +2x +2x +4954x +1x +  +  +1x +1x +  +4953x +  +1x + 
import { CompletionItem } from 'vscode-languageserver'
+import { Node, Body, Method, Singleton, Module, Environment, Package, Class, Mixin, Describe, Program, Test, Reference, New, Import, Entity, implicitImport, is, parentImport, match, when } from 'wollok-ts'
+import { classCompletionItem, fieldCompletionItem, initializerCompletionItem, parameterCompletionItem, singletonCompletionItem, entityCompletionItem, withImport } from './autocomplete'
+import { optionModules, optionImports, optionDescribes, optionTests, optionReferences, optionMethods, optionPrograms, optionAsserts, optionConstReferences, optionInitialize, optionPropertiesAndReferences } from './options-autocomplete'
+import { logger } from '../../utils/logger'
+ 
+export const completionsForNode = (node: Node): CompletionItem[] => {
+  try {
+    return match(node)(
+      when(Environment)(_ => []),
+      when(Package)(completePackage),
+      when(Singleton)(completeModule),
+      when(Class)(completeModule),
+      when(Mixin)(completeModule),
+      when(Program)(completeProgram),
+      when(Test)(completeTest),
+      when(Body)(completeBody),
+      when(Method)(completeMethod),
+      when(Describe)(completeDescribe),
+      when(Reference<Class>)(completeReference),
+      when(New)(completeNew)
+    )
+  } catch (error) {
+    logger.error(`✘ Completions for node failed: ${error}`, error)
+    return completeForParent(node)
+  }
+}
+ 
+const isTestFile = (node: Node) => node.sourceFileName?.endsWith('wtest')
+ 
+const isProgramFile = (node: Node) => node.sourceFileName?.endsWith('wpgm')
+ 
+const completePackage = (node: Package): CompletionItem[] => [
+  ...optionImports,
+  ...optionConstReferences,
+  ...isTestFile(node) ? optionDescribes : isProgramFile(node) ? optionPrograms : optionModules,
+]
+ 
+const completeProgram = (): CompletionItem[] => [
+  ...optionReferences,
+]
+ 
+const completeTest = (): CompletionItem[] => [
+  ...optionReferences,
+  ...optionAsserts,
+]
+ 
+const completeModule = (): CompletionItem[] => [
+  ...optionPropertiesAndReferences,
+  ...optionMethods,
+]
+ 
+const completeBody = (node: Body): CompletionItem[] => completeForParent(node)
+ 
+const completeMethod = (node: Method): CompletionItem[] => {
+  const parent = node.parent
+  const fields = is(Module) ? parent.fields : []
+  return [
+    ...node.parameters.map(parameterCompletionItem),
+    ...fields.map(fieldCompletionItem),
+    ...(node.environment.descendants.filter(node => node.is(Singleton) && !!node.name) as Singleton[]).map(withImport(singletonCompletionItem)(node)),
+  ]
+}
+ 
+const completeDescribe = (node: Describe): CompletionItem[] => isTestFile(node) ? [...optionConstReferences, ...optionTests, ...optionInitialize] : []
+ 
+export const completeForParent = (node: Node): CompletionItem[] => {
+  if (!node.parent) throw new Error('Node has no parent')
+  return completionsForNode(node.parent)
+}
+ 
+const completeReference = (node: Reference<Class>): CompletionItem[] => {
+  const nodeImport = parentImport(node)
+  if (nodeImport) return completeImports(nodeImport)
+  const classes = node.environment.descendants.filter(child => child.is(Class) && !child.isAbstract) as Class[]
+  return classes.map(withImport(classCompletionItem)(node)).concat(completeForParent(node))
+}
+ 
+const completeNew = (node: New): CompletionItem[] =>
+  node.instantiated.target && node.instantiated.target.is(Class) ? [withImport(initializerCompletionItem)(node)(node.instantiated.target)] : []
+ 
+const availableForImport = (node: Node) => (node.is(Class) || node.is(Singleton) || node.is(Reference) || node.is(Mixin)) && node.name && (node as Entity).fullyQualifiedName && !implicitImport(node)
+ 
+const completeImports = (node: Import) => (node.environment.descendants.filter(availableForImport) as Entity[]).map(entityCompletionItem)
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/functionalities/autocomplete/options-autocomplete.ts.html b/server/coverage/src/functionalities/autocomplete/options-autocomplete.ts.html new file mode 100644 index 0000000..5177b7c --- /dev/null +++ b/server/coverage/src/functionalities/autocomplete/options-autocomplete.ts.html @@ -0,0 +1,574 @@ + + + + + + Code coverage report for src/functionalities/autocomplete/options-autocomplete.ts + + + + + + + + + +
+
+

All files / src/functionalities/autocomplete options-autocomplete.ts

+
+ +
+ 100% + Statements + 13/13 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 13/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +1641x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  + 
import { CompletionItemKind, InsertTextFormat } from 'vscode-languageserver'
+ 
+export const optionImports = [
+  {
+    label: 'import',
+    kind: CompletionItemKind.File,
+    insertTextFormat: InsertTextFormat.Snippet,
+    sortText: '010',
+    insertText: 'import ${1:dependency}\n${0}',
+  },
+]
+ 
+export const optionPrograms = [
+  {
+    label: 'program',
+    kind: CompletionItemKind.Unit,
+    sortText: '050',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'program ${1:name} {\n  ${0}\n}',
+  },
+]
+ 
+export const optionTests = [
+  {
+    label: 'test',
+    kind: CompletionItemKind.Event,
+    sortText: '050',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'test "${1:description}" {\n  ${0}\n}',
+  },
+]
+ 
+export const optionConstReferences = [
+  {
+    label: 'const attribute',
+    kind: CompletionItemKind.Field,
+    sortText: '020',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'const ${1:name} = ${0}',
+  },
+]
+ 
+const optionVarReferences = [
+  {
+    label: 'var attribute',
+    kind: CompletionItemKind.Field,
+    sortText: '015',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'var ${1:name} = ${0}',
+  },
+]
+ 
+export const optionReferences = [
+  ...optionVarReferences,
+  ...optionConstReferences,
+]
+ 
+export const optionPropertiesAndReferences = [
+  ...optionVarReferences,
+  {
+    label: 'var property',
+    kind: CompletionItemKind.Property,
+    sortText: '020',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'var property ${1:name} = ${0}',
+  },
+  ...optionConstReferences,
+  {
+    label: 'const property',
+    kind: CompletionItemKind.Property,
+    sortText: '025',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'const property ${1:propertyName} = ${0}',
+  },
+]
+ 
+export const optionModules = [
+  {
+    label: 'object',
+    kind: CompletionItemKind.Module,
+    insertTextFormat: InsertTextFormat.Snippet,
+    sortText: '030',
+    insertText: 'object ${1:name} {\n  ${0}\n}',
+  },
+  {
+    label: 'class',
+    kind: CompletionItemKind.Class,
+    sortText: '035',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'class ${1:Name} {\n  ${0}\n}',
+  },
+]
+ 
+export const optionDescribes = [
+  {
+    label: 'describe',
+    kind: CompletionItemKind.Folder,
+    insertTextFormat: InsertTextFormat.Snippet,
+    sortText: '050',
+    insertText: 'describe "${1:name}" {\n  test "${2:description}" {\n    ${0}\n  }\n}',
+  },
+  ...optionTests,
+  // we could potentially hide modules autocompletion, but when you design unit tests you need some abstraction
+  ...optionModules,
+  //
+]
+ 
+export const optionMethods = [
+  {
+    label: 'method (effect)',
+    kind: CompletionItemKind.Method,
+    sortText: '040',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'method ${1:name}($2) {\n  ${0}\n}',
+  },
+  {
+    label: 'method (return)',
+    kind: CompletionItemKind.Method,
+    sortText: '040',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'method ${1:name}($2) = ${0}',
+  },
+]
+ 
+export const optionAsserts = [
+  {
+    label: 'assert equality',
+    kind: CompletionItemKind.Snippet,
+    sortText: '060',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'assert.equals(${1:value}, ${2:expression})${0}',
+  },
+  {
+    label: 'assert boolean',
+    kind: CompletionItemKind.Snippet,
+    sortText: '065',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'assert.that(${1:booleanExpression})${0}',
+  },
+  {
+    label: 'assert throws',
+    kind: CompletionItemKind.Snippet,
+    sortText: '070',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'assert.throwsException({ ${1:expression} })${0}',
+  },
+  {
+    label: 'assert throws message',
+    kind: CompletionItemKind.Snippet,
+    sortText: '075',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'assert.throwsExceptionWithMessage(${1:message}, { ${2:expression} })${0}',
+  },
+]
+ 
+export const optionInitialize = [
+  {
+    label: 'initializer',
+    kind: CompletionItemKind.Constructor,
+    sortText: '030',
+    insertTextFormat: InsertTextFormat.Snippet,
+    insertText: 'method initialize() {\n  ${0}\n}',
+  },
+]
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/functionalities/autocomplete/send-completion.ts.html b/server/coverage/src/functionalities/autocomplete/send-completion.ts.html new file mode 100644 index 0000000..18c1bd6 --- /dev/null +++ b/server/coverage/src/functionalities/autocomplete/send-completion.ts.html @@ -0,0 +1,232 @@ + + + + + + Code coverage report for src/functionalities/autocomplete/send-completion.ts + + + + + + + + + +
+
+

All files / src/functionalities/autocomplete send-completion.ts

+
+ +
+ 100% + Statements + 23/23 +
+ + +
+ 88.46% + Branches + 23/26 +
+ + +
+ 100% + Functions + 10/10 +
+ + +
+ 100% + Lines + 21/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50  +1x +1x +  +1x +932x +  +  +  +12x +2x +  +10x +6x +  +4x +2x +  +2x +1x +1x +1x +  +  +1x +  +  +  +6x +  +  +  +554x +  +  +  +563x +  +  +  +563x +  +  +  +563x +  +  +  +554x + 
import { CompletionItem } from 'vscode-languageserver'
+import { Body, Describe, Environment, Literal, Method, New, Node, Reference, Singleton, List, is, CLOSURE_EVALUATE_METHOD, allAvailableMethods, allMethods, firstNodeWithProblems, literalValueToClass } from 'wollok-ts'
+import { methodCompletionItem } from './autocomplete'
+ 
+export function completeMessages(environment: Environment, node: Node): CompletionItem[] {
+  return methodPool(environment, node).map((method: Method) => methodCompletionItem(node, method))
+}
+ 
+function methodPool(environment: Environment, node: Node): List<Method> {
+  if (node.is(Reference) && node.target?.is(Singleton)) {
+    return node.target.allMethods
+  }
+  if (node.is(Literal)) {
+    return literalMethods(environment, node)
+  }
+  if (node.is(New)) {
+    return allMethods(environment, node.instantiated)
+  }
+  if (node.is(Body) && node.hasProblems) {
+    const childAutocomplete = firstNodeWithProblems(node)
+    Eif (childAutocomplete) {
+      return methodPool(environment, childAutocomplete)
+    }
+  }
+  return allPossibleMethods(environment, node)
+}
+ 
+function literalMethods(environment: Environment, literal: Literal){
+  return literalValueToClass(environment, literal.value).allMethods
+}
+ 
+function isSymbol(message: string) {
+  return /^[^a-zA-Z0-9áéíóúÁÉÍÓÚñÑäëïöüàèìòù]+$/g.test(message)
+}
+ 
+function allPossibleMethods(environment: Environment, node: Node): Method[] {
+  return allAvailableMethods(environment).filter((method: Method) => availableForAutocomplete(method, node))
+}
+ 
+function availableForAutocomplete(method: Method, node: Node) {
+  return fileValidForAutocomplete(method.sourceFileName) && methodNameValidForAutocomplete(method) && (!method.parent.is(Describe) || node.ancestors.some(is(Describe)))
+}
+ 
+function fileValidForAutocomplete(sourceFileName: string | undefined) {
+  return sourceFileName && !['wollok/vm.wlk', 'wollok/mirror.wlk'].includes(sourceFileName)
+}
+ 
+function methodNameValidForAutocomplete(method: Method) {
+  return !isSymbol(method.name) && method.name !== CLOSURE_EVALUATE_METHOD
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/index.html b/server/coverage/src/index.html new file mode 100644 index 0000000..a68b557 --- /dev/null +++ b/server/coverage/src/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 92.3% + Statements + 48/52 +
+ + +
+ 56.25% + Branches + 9/16 +
+ + +
+ 78.57% + Functions + 11/14 +
+ + +
+ 93.33% + Lines + 42/45 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
settings.ts +
+
86.36%19/2240%4/1040%2/582.35%14/17
shared-definitions.ts +
+
100%7/7100%0/0100%0/0100%7/7
time-measurer.ts +
+
95.65%22/2383.33%5/6100%9/9100%21/21
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/settings.ts.html b/server/coverage/src/settings.ts.html new file mode 100644 index 0000000..6c3190c --- /dev/null +++ b/server/coverage/src/settings.ts.html @@ -0,0 +1,280 @@ + + + + + + Code coverage report for src/settings.ts + + + + + + + + + +
+
+

All files / src settings.ts

+
+ +
+ 86.36% + Statements + 19/22 +
+ + +
+ 40% + Branches + 4/10 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 82.35% + Lines + 14/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +1x +1x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +2x + 
import { Connection } from 'vscode-languageserver/node'
+import { wollokLSPExtensionCode } from './shared-definitions'
+ 
+export interface WollokLSPSettings {
+  maxNumberOfProblems: number
+  language: string,
+  openDynamicDiagramOnRepl: boolean,
+  openInternalDynamicDiagram: boolean,
+  dynamicDiagramDarkMode: boolean,
+  maxThreshold: number,
+  millisecondsToOpenDynamicDiagram: number,
+}
+ 
+// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════
+// INTERNAL & PUBLISHED STATE
+// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════
+ 
+const SPANISH = 'es'
+const ENGLISH = 'en'
+ 
+const envLang = () => {
+  const env = process.env
+  const fullLanguage = env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE
+  return fullLanguage ? fullLanguage.substring(0, 2) : SPANISH
+}
+ 
+const defaultSettings: WollokLSPSettings = {
+  maxNumberOfProblems: 1000,
+  language: envLang(),
+  openDynamicDiagramOnRepl: true,
+  openInternalDynamicDiagram: true,
+  dynamicDiagramDarkMode: true,
+  maxThreshold: 100,
+  millisecondsToOpenDynamicDiagram: 1000,
+}
+ 
+let globalSettings: WollokLSPSettings = defaultSettings
+ 
+const languageDescription: { [key: string]: string } = {
+  Spanish: SPANISH,
+  English: ENGLISH,
+}
+ 
+// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════
+// PUBLIC INTERFACE
+// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════
+export const updateDocumentSettings = async (
+  connection: Connection,
+): Promise<void> => {
+  globalSettings =
+    ((await connection.workspace.getConfiguration({
+      section: wollokLSPExtensionCode,
+    })) as WollokLSPSettings) || defaultSettings
+}
+ 
+export const initializeSettings = async (
+  connection: Connection,
+): Promise<void> => {
+  await updateDocumentSettings(connection)
+}
+ 
+export const lang = (): string =>
+  languageDescription[globalSettings.language] || envLang()
+ 
+export const maxThreshold = (): number => globalSettings.maxThreshold
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/shared-definitions.ts.html b/server/coverage/src/shared-definitions.ts.html new file mode 100644 index 0000000..f614497 --- /dev/null +++ b/server/coverage/src/shared-definitions.ts.html @@ -0,0 +1,118 @@ + + + + + + Code coverage report for src/shared-definitions.ts + + + + + + + + + +
+
+

All files / src shared-definitions.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12  +  +  +1x +1x +  +  +1x +1x +1x +1x +1x
// This file is linked from both client and server
+ 
+// IDE
+export const wollokLSPExtensionCode = 'wollokLSP'
+export const wollokLSPExtensionId = 'wollok-lsp-ide'
+ 
+// Commands
+export const COMMAND_START_REPL = 'wollok.start.repl'
+export const COMMAND_RUN_GAME = 'wollok.run.game'
+export const COMMAND_RUN_PROGRAM = 'wollok.run.program'
+export const COMMAND_RUN_ALL_TESTS = 'wollok.run.allTests'
+export const COMMAND_RUN_TEST = 'wollok.run.test'
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/test/mocks/file-contents.ts.html b/server/coverage/src/test/mocks/file-contents.ts.html new file mode 100644 index 0000000..e3ab935 --- /dev/null +++ b/server/coverage/src/test/mocks/file-contents.ts.html @@ -0,0 +1,106 @@ + + + + + + Code coverage report for src/test/mocks/file-contents.ts + + + + + + + + + +
+
+

All files / src/test/mocks file-contents.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8  +1x +  +  +  +  +  + 
// TODO: Create a .wlk file
+export const pepitaFile = `object pepita {
+  var peso = 0
+ 
+  method comer(comida){
+    peso = peso + comida.calorias()
+  }
+}`
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/test/mocks/index.html b/server/coverage/src/test/mocks/index.html new file mode 100644 index 0000000..1c6ec4d --- /dev/null +++ b/server/coverage/src/test/mocks/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/test/mocks + + + + + + + + + +
+
+

All files src/test/mocks

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
file-contents.ts +
+
100%1/1100%0/0100%0/0100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/test/utils/index.html b/server/coverage/src/test/utils/index.html new file mode 100644 index 0000000..4fb97ca --- /dev/null +++ b/server/coverage/src/test/utils/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/test/utils + + + + + + + + + +
+
+

All files src/test/utils

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
wollok-test-utils.ts +
+
100%4/4100%0/0100%1/1100%4/4
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/test/utils/wollok-test-utils.ts.html b/server/coverage/src/test/utils/wollok-test-utils.ts.html new file mode 100644 index 0000000..66cf4c7 --- /dev/null +++ b/server/coverage/src/test/utils/wollok-test-utils.ts.html @@ -0,0 +1,100 @@ + + + + + + Code coverage report for src/test/utils/wollok-test-utils.ts + + + + + + + + + +
+
+

All files / src/test/utils wollok-test-utils.ts

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +61x +1x +  +1x +7x + 
import { buildEnvironment, Environment } from 'wollok-ts'
+import { pepitaFile } from '../mocks/file-contents'
+ 
+export function buildPepitaEnvironment(): Environment {
+  return buildEnvironment([{ name: 'pepita.wlk', content: pepitaFile }])
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/time-measurer.ts.html b/server/coverage/src/time-measurer.ts.html new file mode 100644 index 0000000..72a752d --- /dev/null +++ b/server/coverage/src/time-measurer.ts.html @@ -0,0 +1,235 @@ + + + + + + Code coverage report for src/time-measurer.ts + + + + + + + + + +
+
+

All files / src time-measurer.ts

+
+ +
+ 95.65% + Statements + 22/23 +
+ + +
+ 83.33% + Branches + 5/6 +
+ + +
+ 100% + Functions + 9/9 +
+ + +
+ 100% + Lines + 21/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +511x +1x +  +1x +1x +1x +  +  +1x +1x +  +  +  +1x +1x +2x +2x +2x +2x +  +  +  +  +  +1x +  +  +  +2x +  +  +  +4x +  +  +  +  +2x +2x +2x +  +  +  +4x +  +  +  +  +2x +  + 
import { maxThreshold } from './settings'
+import { logger } from './utils/logger'
+ 
+export class TimeMeasurer {
+  private times: Array<TimeElement> = []
+  private initialTime: number = this.now()
+ 
+  reset(): void {
+    this.times = []
+    this.initialTime = this.now()
+  }
+ 
+  finalReport(): void {
+    Iif (!this.times) return
+    this.times.forEach((timeRow, index) => {
+      const timeElapsed = this.elapsedTime(index)
+      const thresholdReached = timeElapsed > maxThreshold()
+      const icon = thresholdReached ? '⌛ ' : ''
+      logger.info({
+        message: `${icon}${timeRow.processName}`,
+        timeElapsed,
+        private: !thresholdReached,
+      })
+    })
+    this.reset()
+  }
+ 
+  addTime(processName: string): void {
+    this.times.push(new TimeElement(processName, this.now()))
+  }
+ 
+  private now(): number {
+    return this.getTime(process.hrtime.bigint())
+  }
+ 
+  private elapsedTime(index: number): number {
+    const previousTime =
+      index > 0 ? this.times[index - 1].time : this.initialTime
+    const currentTime = this.times[index].time
+    return currentTime - previousTime
+  }
+ 
+  private getTime(value: bigint): number {
+    return Number(value / BigInt(1000000))
+  }
+}
+ 
+class TimeElement {
+  constructor(public processName: string, public time: number) {}
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/utils/index.html b/server/coverage/src/utils/index.html new file mode 100644 index 0000000..c00c915 --- /dev/null +++ b/server/coverage/src/utils/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/utils + + + + + + + + + +
+
+

All files src/utils

+
+ +
+ 59.04% + Statements + 62/105 +
+ + +
+ 37.2% + Branches + 16/43 +
+ + +
+ 37.5% + Functions + 9/24 +
+ + +
+ 53.94% + Lines + 41/76 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
logger.ts +
+
100%11/11100%4/4100%3/3100%9/9
strings.ts +
+
100%3/3100%0/0100%1/1100%1/1
text-documents.ts +
+
52.74%48/9130.76%12/3925%5/2046.96%31/66
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/utils/logger.ts.html b/server/coverage/src/utils/logger.ts.html new file mode 100644 index 0000000..b40191a --- /dev/null +++ b/server/coverage/src/utils/logger.ts.html @@ -0,0 +1,181 @@ + + + + + + Code coverage report for src/utils/logger.ts + + + + + + + + + +
+
+

All files / src/utils logger.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 9/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +331x +  +4x +  +1x +4x +3x +  +  +1x +3x +3x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import winston, { format } from 'winston'
+ 
+export const consoleFormat = format.printf(info => info.message + (info.timeElapsed ? ` | ${info.timeElapsed} ms` : ''))
+ 
+export const ignorePrivate = format(info => {
+  if (info.private) return false
+  return info
+})
+ 
+export const removePrivate = format(info => {
+  delete info.private
+  return info
+})
+ 
+export const logger = winston.createLogger({
+  transports: [
+    new winston.transports.Console({
+      format: consoleFormat,
+    }),
+    new winston.transports.File(
+      {
+        filename: 'log/wollok.log',
+        maxsize: 1000000,
+        format: format.combine(
+          ignorePrivate(),
+          removePrivate(),
+          format.timestamp(),
+          format.json(),
+        ),
+      },
+    ),
+  ],
+})
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/utils/strings.ts.html b/server/coverage/src/utils/strings.ts.html new file mode 100644 index 0000000..edc6f45 --- /dev/null +++ b/server/coverage/src/utils/strings.ts.html @@ -0,0 +1,88 @@ + + + + + + Code coverage report for src/utils/strings.ts + + + + + + + + + +
+
+

All files / src/utils strings.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +22x + 
export const removeQuotes = (str: string): string => str.replace(new RegExp("(^\")|(\"$)", 'g'), "")
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/utils/text-documents.ts.html b/server/coverage/src/utils/text-documents.ts.html new file mode 100644 index 0000000..67b7225 --- /dev/null +++ b/server/coverage/src/utils/text-documents.ts.html @@ -0,0 +1,517 @@ + + + + + + Code coverage report for src/utils/text-documents.ts + + + + + + + + + +
+
+

All files / src/utils text-documents.ts

+
+ +
+ 52.74% + Statements + 48/91 +
+ + +
+ 30.76% + Branches + 12/39 +
+ + +
+ 25% + Functions + 5/20 +
+ + +
+ 46.96% + Lines + 31/66 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +1451x +1x +1x +  +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +7x +7x +7x +  +7x +1x +  +  +6x +  +  +  +  +  +  +  +1x +  +  +  +1x +  +  +  +  +  +  +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +11x +  +11x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +6x +  +  +1x +16x +  +  +1x +  +  +  +1x +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  + 
import * as fs from 'fs'
+import * as path from 'path'
+import { Location, Position, Range, TextDocumentIdentifier, TextDocumentPositionParams } from 'vscode-languageserver'
+import { TextDocument } from 'vscode-languageserver-textdocument'
+import { Environment, FileContent, Node, PROGRAM_FILE_EXTENSION, Package, SourceIndex, SourceMap, TEST_FILE_EXTENSION, WOLLOK_FILE_EXTENSION } from 'wollok-ts'
+ 
+// TODO: Refactor
+const include = (node: Node, { position, textDocument: { uri } }: TextDocumentPositionParams) => {
+  if (!node.sourceFileName) return false
+  if (node.kind === 'Package') {
+    return uri.includes(node.sourceFileName)
+  }
+  if (!node.sourceMap) return false
+ 
+  const startPosition = toVSCPosition(node.sourceMap.start)
+  const endPosition = toVSCPosition(node.sourceMap.end)
+ 
+  return uri.includes(node.sourceFileName!)
+    && node.sourceMap
+    && between(position, startPosition, endPosition)
+}
+ 
+export const between = (pointer: Position, start: Position, end: Position): boolean => {
+  const { line: linePointer, character: charPointer } = pointer
+  const { line: lineStart, character: charStart } = start
+  const { line: lineEnd, character: charEnd } = end
+ 
+  if (lineStart === lineEnd && linePointer === lineStart) {
+    return charPointer >= charStart && charPointer <= charEnd
+  }
+ 
+  return linePointer > lineStart
+    && linePointer < lineEnd
+    || (linePointer === lineStart
+      && charPointer >= charStart
+      || linePointer === lineEnd
+      && charPointer <= charEnd)
+}
+ 
+export const getNodesByPosition = (environment: Environment, textDocumentPosition: TextDocumentPositionParams): Node[] => {
+  return environment.descendants.filter(node => !!node.sourceFileName && include(node, textDocumentPosition))
+}
+ 
+export const toVSCPosition = (position: SourceIndex): Position =>
+  Position.create(
+    Math.max(0, position.line - 1),
+    Math.max(0, position.column - 1)
+  )
+ 
+ 
+export const toVSCRange = (sourceMap: SourceMap): Range =>
+  Range.create(toVSCPosition(sourceMap.start), toVSCPosition(sourceMap.end))
+ 
+export const nodeToLocation = (node: Node): Location => {
+  if (!node.sourceMap || !node.sourceFileName) {
+    throw new Error('No source map found for node')
+  }
+ 
+  return {
+    uri: uriFromRelativeFilePath(node.sourceFileName!),
+    range: toVSCRange(node.sourceMap),
+  }
+}
+ 
+export function trimIn(range: Range, textDocument: TextDocument): Range {
+  const start = textDocument.offsetAt(range.start)
+  const end = textDocument.offsetAt(range.end)
+  const text = textDocument.getText().substring(start, end)
+  const trimmed = text.trim()
+  const startOffset = text.indexOf(trimmed)
+  const endOffset = startOffset + trimmed.length
+  return Range.create(
+    textDocument.positionAt(start + startOffset),
+    textDocument.positionAt(start + endOffset),
+  )
+}
+ 
+export const packageFromURI = (uri: string, environment: Environment): Package | undefined => {
+  const sanitizedURI = relativeFilePath(uri)
+  // TODO: Use projectFQN ?
+  return environment.descendants.find(node => node.is(Package) && node.fileName === sanitizedURI) as Package | undefined
+}
+ 
+export const packageToURI = (pkg: Package): string => fileNameToURI(pkg.fileName!)
+ 
+export const fileNameToURI = (fileName: string): string => `file:///${fileName}`
+ 
+export const getWollokFileExtension = (uri: string): typeof WOLLOK_FILE_EXTENSION | typeof PROGRAM_FILE_EXTENSION | typeof TEST_FILE_EXTENSION => {
+  const extension = uri.split('.').pop()
+  if (!extension) throw new Error('Could not determine file extension')
+ 
+  switch(extension) {
+    case WOLLOK_FILE_EXTENSION:
+    case PROGRAM_FILE_EXTENSION:
+    case TEST_FILE_EXTENSION:
+      return extension
+    default:
+      throw new Error(`Invalid file extension: ${extension}`)
+  }
+}
+ 
+export function cursorNode(
+  environment: Environment,
+  position: Position,
+  textDocument: TextDocumentIdentifier
+): Node {
+  return getNodesByPosition(environment, {
+    position,
+    textDocument,
+  }).reverse()[0]
+}
+ 
+/** URI */
+ 
+export let WORKSPACE_URI = ''
+ 
+export const setWorkspaceUri = (uri: string): void => {
+  WORKSPACE_URI = uri
+}
+ 
+export const relativeFilePath = (absoluteURI: string): string => {
+  return absoluteURI.replaceAll(WORKSPACE_URI + '/', '')
+}
+ 
+export const uriFromRelativeFilePath = (relativeURI: string): string => {
+  return WORKSPACE_URI + '/' + relativeURI
+}
+ 
+export const documentToFile = (doc: TextDocument): FileContent => ({
+  name: relativeFilePath(doc.uri),
+  content: doc.getText(),
+})
+ 
+export const isNodeURI = (node: Node, uri: string): boolean => node.sourceFileName == relativeFilePath(uri)
+ 
+export const findPackageJSON = (uri: string): string => {
+  let baseUri = uri
+  while (!fs.existsSync(baseUri + path.sep + 'package.json') && baseUri) {
+    const lastIndex = baseUri.lastIndexOf(path.sep)
+    if (!lastIndex) return ''
+    baseUri = baseUri.slice(0, lastIndex)
+  }
+  return baseUri
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/utils/vm/index.html b/server/coverage/src/utils/vm/index.html new file mode 100644 index 0000000..8e63ae6 --- /dev/null +++ b/server/coverage/src/utils/vm/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/utils/vm + + + + + + + + + +
+
+

All files src/utils/vm

+
+ +
+ 88.88% + Statements + 72/81 +
+ + +
+ 59.25% + Branches + 32/54 +
+ + +
+ 70% + Functions + 14/20 +
+ + +
+ 88.88% + Lines + 48/54 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
wollok.ts +
+
88.88%72/8159.25%32/5470%14/2088.88%48/54
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/server/coverage/src/utils/vm/wollok.ts.html b/server/coverage/src/utils/vm/wollok.ts.html new file mode 100644 index 0000000..87e1df0 --- /dev/null +++ b/server/coverage/src/utils/vm/wollok.ts.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for src/utils/vm/wollok.ts + + + + + + + + + +
+
+

All files / src/utils/vm wollok.ts

+
+ +
+ 88.88% + Statements + 72/81 +
+ + +
+ 59.25% + Branches + 32/54 +
+ + +
+ 70% + Functions + 14/20 +
+ + +
+ 88.88% + Lines + 48/54 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
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 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +881x +1x +1x +1x +  +1x +  +1x +6x +  +2x +  +1x +  +1x +  +2x +2x +2x +  +  +  +  +  +6x +  +  +1x +1x +  +1x +2x +  +1x +1x +1x +1x +  +  +  +932x +  +5x +  +41x +  +  +1x +1x +  +  +1x +  +1x +  +1x +  +  +1x +10x +10x +32x +32x +30x +  +8x +  +  +1x +5x +5x +5x +4x +  +  +1x +13x +2x +2x +2x +  +  +  +  +1x +  +  + 
import { is } from 'wollok-ts/dist/extensions'
+import { Class, Entity, Environment, Import, LiteralValue, Method, Module, Node, Package, Reference } from 'wollok-ts'
+import fs from 'fs'
+import path from 'path'
+ 
+export const OBJECT_CLASS = 'wollok.lang.Object'
+ 
+export const literalValueToClass = (environment: Environment, literal: LiteralValue): Class => {
+  const clazz = (() => { switch (typeof literal) {
+    case 'number':
+      return 'wollok.lang.Number'
+    case 'string':
+      return 'wollok.lang.String'
+    case 'boolean':
+      return 'wollok.lang.Boolean'
+    case 'object':
+      try {
+        const referenceClasses = literal as unknown as Reference<Class>[]
+        return referenceClasses[0].name
+      } catch (e) {
+        return OBJECT_CLASS
+      }
+    }
+  })()
+  return environment.getNodeByFQN(clazz)
+}
+ 
+export const allAvailableMethods = (environment: Environment): Method[] =>
+  environment.descendants.filter(is(Method)) as Method[]
+ 
+export const allMethods = (environment: Environment, referenceClass: Reference<Module>): Method[] =>
+  (referenceClass.target ?? environment.objectClass).allMethods as Method[]
+ 
+export const firstNodeWithProblems = (node: Node): Node | undefined => {
+  const { start, end } = node.problems![0].sourceMap ?? { start: { offset: -1 }, end: { offset: -1 } }
+  return node.children.find(child =>
+    child.sourceMap?.covers(start.offset) || child.sourceMap?.covers(end.offset)
+  )
+}
+ 
+export const parentModule = (node: Node): Module => (node.ancestors.find(ancestor => ancestor.is(Module))) as Module ?? node.environment.objectClass
+ 
+export const parentImport = (node: Node): Import | undefined => node.ancestors.find(ancestor => ancestor.is(Import)) as Import
+ 
+export const implicitImport = (node: Node): boolean => ['wollok/lang.wlk', 'wollok/lib.wlk'].includes(node.sourceFileName ?? '')
+ 
+// @ToDo Workaround because package fqn is absolute in the lsp.
+export const fqnRelativeToPackage =
+  (pckg: Package, node: Entity): string =>
+    node.fullyQualifiedName.replace(pckg.fullyQualifiedName, pckg.name)
+ 
+export const wollokURI = (uri: string): string => uri.replace('file:///', '')
+ 
+export const isNodeURI = (node: Node, uri: string): boolean => node.sourceFileName == wollokURI(uri)
+ 
+export const workspacePackage = (environment: Environment): Package =>
+  environment.members[1]
+ 
+export const rootFolder = (uri: string): string => {
+  let folderPath = uri
+  while (!fs.existsSync(folderPath + path.sep + 'package.json') && folderPath) {
+    const lastIndex = folderPath.lastIndexOf(path.sep)
+    if (!lastIndex) return ''
+    folderPath = folderPath.slice(0, lastIndex)
+  }
+  return folderPath
+}
+ 
+export const relativeFilePath = (uri: string): string => {
+  const sanitizedUri = uri.replace('file:///', path.sep)
+  const rootPath = rootFolder(sanitizedUri)
+  if (!rootPath) return sanitizedUri
+  return sanitizedUri.replaceAll(rootPath + path.sep, '')
+}
+ 
+export const projectFQN = (node: Entity): string => {
+  if (node.fullyQualifiedName.startsWith('wollok')) return node.fullyQualifiedName
+  const fileName = node.sourceFileName ?? ''
+  const rootPath = rootFolder(path.sep + fileName).slice(1)
+  Eif (!rootPath) return node.fullyQualifiedName
+  const rootFQN = rootPath.replaceAll(path.sep, '.')
+  return node.fullyQualifiedName?.replaceAll(rootFQN + '.', '') ?? ''
+}
+ 
+export const targettingAt = <T extends Node>(aNode: T) => (anotherNode: Node): anotherNode is Reference<T>  => {
+  return anotherNode.is(Reference) && anotherNode.target === aNode
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file From 6e1d85df9cbb6df7c0db1b6b99a8da1bf28fa118 Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 21:42:07 -0300 Subject: [PATCH 06/12] add game port number configuration --- package.json | 9 ++++++++- packages/client/src/commands.ts | 9 ++++++--- packages/server/src/settings.ts | 9 ++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 8ee4e7b..a4aba32 100644 --- a/package.json +++ b/package.json @@ -223,13 +223,20 @@ "description": "Traces the communication between VS Code and the language server.", "order": 20 }, - "wollokLSP.repl.portNumber": { + "wollokLSP.replPortNumber": { "scope": "resource", "type": "number", "default": 3000, "description": "Port number that will be used when running the REPL.", "order": 25 }, + "wollokLSP.gamePortNumber": { + "scope": "resource", + "type": "number", + "default": 4200, + "description": "Port number that will be used when running a game.", + "order": 26 + }, "wollokLSP.dynamicDiagram.openDynamicDiagramOnRepl": { "scope": "resource", "type": "boolean", diff --git a/packages/client/src/commands.ts b/packages/client/src/commands.ts index bfee1fa..acb6a32 100644 --- a/packages/client/src/commands.ts +++ b/packages/client/src/commands.ts @@ -14,7 +14,7 @@ import { fsToShell, } from './platform-string-utils' import { COMMAND_RUN_ALL_TESTS, COMMAND_RUN_GAME, COMMAND_RUN_PROGRAM, COMMAND_RUN_TEST, COMMAND_START_REPL, wollokLSPExtensionCode, COMMAND_INIT_PROJECT } from './shared-definitions' -import { DEFAULT_PORT } from '../../server/src/settings' +import { DEFAULT_REPL_PORT, DEFAULT_GAME_PORT } from '../../server/src/settings' export const subscribeWollokCommands = (context: ExtensionContext): void => { context.subscriptions.push(registerCLICommand(COMMAND_START_REPL, startRepl)) @@ -38,11 +38,14 @@ export const subscribeWollokCommands = (context: ExtensionContext): void => { */ export const runProgram = (isGame = false) => ([fqn]: [string]): Task => { + const wollokLSPConfiguration = workspace.getConfiguration(wollokLSPExtensionCode) + const portNumber = wollokLSPConfiguration.get('gamePortNumber') as number ?? DEFAULT_GAME_PORT + // Terminate previous terminal session vscode.commands.executeCommand('workbench.action.terminal.killAll') return wollokCLITask('run program', `Wollok run ${isGame ? 'game' : 'program'}`, [ 'run', - ...isGame ? ['-g'] : [], + ...isGame ? ['-g', '--port', portNumber.toString()] : [], asShellString(fqn), '--skipValidations', ]) @@ -81,7 +84,7 @@ export const startRepl = (): Task => { const dynamicDiagramDarkMode = wollokLSPConfiguration.get('dynamicDiagram.dynamicDiagramDarkMode') as boolean const openDynamicDiagram = wollokLSPConfiguration.get('dynamicDiagram.openDynamicDiagramOnRepl') as boolean const millisecondsToOpenDynamicDiagram = wollokLSPConfiguration.get('dynamicDiagram.millisecondsToOpenDynamicDiagram') as number - const portNumber = wollokLSPConfiguration.get('repl.portNumber') as number ?? DEFAULT_PORT + const portNumber = wollokLSPConfiguration.get('replPortNumber') as number ?? DEFAULT_REPL_PORT const DYNAMIC_DIAGRAM_URI = `http://localhost:${portNumber}/` const cliCommands = [`repl`, ...getFiles(currentDocument), '--skipValidations', '--port', portNumber.toString(), dynamicDiagramDarkMode ? '--darkMode' : '', openDynamicDiagram ? '': '--skipDiagram'] diff --git a/packages/server/src/settings.ts b/packages/server/src/settings.ts index bca4198..1938b51 100644 --- a/packages/server/src/settings.ts +++ b/packages/server/src/settings.ts @@ -2,12 +2,14 @@ import { Connection } from 'vscode-languageserver/node' import { wollokLSPExtensionCode } from './shared-definitions' import { LANGUAGES } from 'wollok-ts' -export const DEFAULT_PORT = 3000 +export const DEFAULT_REPL_PORT = 3000 +export const DEFAULT_GAME_PORT = 4200 export interface WollokLSPSettings { maxNumberOfProblems: number language: LANGUAGES, - portNumber: number, + replPortNumber: number, + gamePortNumber: number, openDynamicDiagramOnRepl: boolean, openInternalDynamicDiagram: boolean, dynamicDiagramDarkMode: boolean, @@ -28,7 +30,8 @@ const envLang = () => { const defaultSettings: WollokLSPSettings = { maxNumberOfProblems: 1000, language: envLang(), - portNumber: DEFAULT_PORT, + replPortNumber: DEFAULT_REPL_PORT, + gamePortNumber: DEFAULT_GAME_PORT, openDynamicDiagramOnRepl: true, openInternalDynamicDiagram: true, dynamicDiagramDarkMode: true, From 441c20bc11fa8259604d658c319ea4db864b56d3 Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 22:04:39 -0300 Subject: [PATCH 07/12] i18n command message --- packages/client/src/commands.ts | 8 +++++--- packages/client/src/messages.ts | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 packages/client/src/messages.ts diff --git a/packages/client/src/commands.ts b/packages/client/src/commands.ts index acb6a32..ea0c6fa 100644 --- a/packages/client/src/commands.ts +++ b/packages/client/src/commands.ts @@ -15,6 +15,8 @@ import { } from './platform-string-utils' import { COMMAND_RUN_ALL_TESTS, COMMAND_RUN_GAME, COMMAND_RUN_PROGRAM, COMMAND_RUN_TEST, COMMAND_START_REPL, wollokLSPExtensionCode, COMMAND_INIT_PROJECT } from './shared-definitions' import { DEFAULT_REPL_PORT, DEFAULT_GAME_PORT } from '../../server/src/settings' +import { getMessage } from 'wollok-ts' +import { lang, lspClientMessages } from './messages' export const subscribeWollokCommands = (context: ExtensionContext): void => { context.subscriptions.push(registerCLICommand(COMMAND_START_REPL, startRepl)) @@ -118,11 +120,11 @@ const registerCLICommand = ( ) const wollokCLITask = (task: string, name: string, cliCommands: Array) => { - const wollokCliPath: string = workspace.getConfiguration(wollokLSPExtensionCode).get('cli-path') - // TODO: i18n - but it's in the server + const wollokLSPConfiguration = workspace.getConfiguration(wollokLSPExtensionCode) + const wollokCliPath: string = wollokLSPConfiguration.get('cli-path') if (!wollokCliPath) { vscode.commands.executeCommand('workbench.action.openSettings', wollokLSPExtensionCode) - throw new Error('Missing configuration WollokLSP/cli-path. Set the path where wollok-ts-cli is located in order to run Wollok tasks') + throw new Error(getMessage({ message: 'missingWollokCliPath', language: lang(wollokLSPConfiguration.get('wollokLSP.language')), customMessages: lspClientMessages })) } const folder = workspace.workspaceFolders[0] diff --git a/packages/client/src/messages.ts b/packages/client/src/messages.ts new file mode 100644 index 0000000..8f300ca --- /dev/null +++ b/packages/client/src/messages.ts @@ -0,0 +1,17 @@ +import { LANGUAGES, Messages } from 'wollok-ts' + +export const languageDescription: { [key: string]: LANGUAGES } = { + Spanish: LANGUAGES.SPANISH, + English: LANGUAGES.ENGLISH, +} + +export const lang = (selectedLanguage: string): LANGUAGES => languageDescription[selectedLanguage] ?? LANGUAGES.ENGLISH + +export const lspClientMessages: Messages = { + [LANGUAGES.ENGLISH]: { + missingWollokCliPath: 'Falta configurar la ruta donde está instalado wollok-ts-cli. Este paso es necesario para ejecutar cualquier comando de Wollok.', + }, + [LANGUAGES.SPANISH]: { + missingWollokCliPath: 'Missing configuration WollokLSP/cli-path. Set the path where wollok-ts-cli is located in order to run Wollok tasks', + }, +} \ No newline at end of file From 26d861f87349a09c2411ae51bbba3e23204d54c5 Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Mon, 7 Oct 2024 23:37:55 -0300 Subject: [PATCH 08/12] i18n extension texts --- packages/client/src/commands.ts | 7 +++---- packages/client/src/extension.ts | 5 +++-- packages/client/src/messages.ts | 14 ++++++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/client/src/commands.ts b/packages/client/src/commands.ts index ea0c6fa..44c1fc1 100644 --- a/packages/client/src/commands.ts +++ b/packages/client/src/commands.ts @@ -9,14 +9,13 @@ import { window, workspace, } from 'vscode' +import { DEFAULT_GAME_PORT, DEFAULT_REPL_PORT } from '../../server/src/settings' import { asShellString, fsToShell, } from './platform-string-utils' import { COMMAND_RUN_ALL_TESTS, COMMAND_RUN_GAME, COMMAND_RUN_PROGRAM, COMMAND_RUN_TEST, COMMAND_START_REPL, wollokLSPExtensionCode, COMMAND_INIT_PROJECT } from './shared-definitions' -import { DEFAULT_REPL_PORT, DEFAULT_GAME_PORT } from '../../server/src/settings' -import { getMessage } from 'wollok-ts' -import { lang, lspClientMessages } from './messages' +import { getLSPMessage } from './messages' export const subscribeWollokCommands = (context: ExtensionContext): void => { context.subscriptions.push(registerCLICommand(COMMAND_START_REPL, startRepl)) @@ -124,7 +123,7 @@ const wollokCLITask = (task: string, name: string, cliCommands: Array { if (progress.kind === 'begin' || progress.kind === 'report') { - statusBarItem.text = '$(loading~spin) Wollok Building...' + statusBarItem.text = '$(loading~spin) ' + getLSPMessage('wollokBuilding') statusBarItem.show() } else { statusBarItem.hide() diff --git a/packages/client/src/messages.ts b/packages/client/src/messages.ts index 8f300ca..ecb5e86 100644 --- a/packages/client/src/messages.ts +++ b/packages/client/src/messages.ts @@ -1,4 +1,6 @@ -import { LANGUAGES, Messages } from 'wollok-ts' +import { getMessage, LANGUAGES, Messages } from 'wollok-ts' +import { wollokLSPExtensionCode } from './shared-definitions' +import { workspace } from 'vscode' export const languageDescription: { [key: string]: LANGUAGES } = { Spanish: LANGUAGES.SPANISH, @@ -9,9 +11,13 @@ export const lang = (selectedLanguage: string): LANGUAGES => languageDescription export const lspClientMessages: Messages = { [LANGUAGES.ENGLISH]: { - missingWollokCliPath: 'Falta configurar la ruta donde está instalado wollok-ts-cli. Este paso es necesario para ejecutar cualquier comando de Wollok.', + missingWollokCliPath: 'Missing configuration WollokLSP/cli-path. Set the path where wollok-ts-cli is located in order to run Wollok tasks', + wollokBuilding: 'Wollok Building...', }, [LANGUAGES.SPANISH]: { - missingWollokCliPath: 'Missing configuration WollokLSP/cli-path. Set the path where wollok-ts-cli is located in order to run Wollok tasks', + missingWollokCliPath: 'Falta configurar la ruta donde está instalado wollok-ts-cli. Este paso es necesario para ejecutar cualquier comando de Wollok.', + wollokBuilding: 'Generando Wollok...', }, -} \ No newline at end of file +} + +export const getLSPMessage = (message: string): string => getMessage({ message, language: lang(workspace.getConfiguration(wollokLSPExtensionCode).get('language')), customMessages: lspClientMessages }) \ No newline at end of file From 9293d844372345f3831adaa9f4d69ca5fc2760df Mon Sep 17 00:00:00 2001 From: Publishing Bot Date: Wed, 9 Oct 2024 01:00:54 +0000 Subject: [PATCH 09/12] =?UTF-8?q?=F0=9F=93=9D=20Update=20contributors=20li?= =?UTF-8?q?st?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 49d1eeb..f4a8027 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + # Wollok IDE @@ -41,6 +41,6 @@ Do you want to contribute? Great, you are always welcome! ## 👥 Contributors -ivojawer fdodino PalumboN npasserini FerRomMu dependabot[bot]  +ivojawer fdodino PalumboN npasserini Miranda-03 FerRomMu dependabot[bot]  \ No newline at end of file From 20792223a11bd819d7994da595bc42420c806a4d Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Tue, 8 Oct 2024 22:07:28 -0300 Subject: [PATCH 10/12] Updating yarn.lock --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 700684a..1d0b2e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6500,7 +6500,7 @@ __metadata: languageName: node linkType: hard -"nyc@npm:^17.1.0": +"nyc@npm:^17.0.0, nyc@npm:^17.1.0": version: 17.1.0 resolution: "nyc@npm:17.1.0" dependencies: From 56395f5528b285422ee1ce45828606833f4652ec Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Tue, 8 Oct 2024 22:10:47 -0300 Subject: [PATCH 11/12] Updating wollok-ts dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4aba32..b2cd8ee 100644 --- a/package.json +++ b/package.json @@ -343,7 +343,7 @@ "lint-staged": "lint-staged" }, "dependencies": { - "wollok-ts": "4.1.6" + "wollok-ts": "4.1.8" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", From dc26df6d7731d7cd838d620d8c63f4852fe17d5e Mon Sep 17 00:00:00 2001 From: Fernando Dodino Date: Tue, 8 Oct 2024 22:43:17 -0300 Subject: [PATCH 12/12] Fix yarn.lock & tests --- packages/client/src/test/commands.test.ts | 15 ++++++++++++++- yarn.lock | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/client/src/test/commands.test.ts b/packages/client/src/test/commands.test.ts index 968b32c..f4f89c4 100644 --- a/packages/client/src/test/commands.test.ts +++ b/packages/client/src/test/commands.test.ts @@ -4,14 +4,23 @@ import * as sinon from 'sinon' import { ShellExecution, ShellQuotedString, ShellQuoting, Task, Uri, workspace } from 'vscode' import { initProject, runAllTests, runProgram, runTest, startRepl } from '../commands' import { activate, getDocumentURI, getFolderURI } from './helper' +import { DEFAULT_GAME_PORT, DEFAULT_REPL_PORT } from '../../../server/src/settings' suite('Should run commands', () => { const folderURI = getFolderURI() const pepitaURI = getDocumentURI('pepita.wlk') + const configuration = { + gamePortNumber: DEFAULT_GAME_PORT, + replPortNumber: DEFAULT_REPL_PORT, + 'cli-path': '/usr/bin/wollok-ts-cli', + 'dynamicDiagram.dynamicDiagramDarkMode': true, + 'dynamicDiagram.openDynamicDiagramOnRepl': true, + } + beforeEach(() => { sinon.stub(workspace, 'getConfiguration').value((_configuration: string) => ({ - get: (_value: string) => '/usr/bin/wollok-ts-cli', + get: (_value: string) => configuration[_value], })) }) @@ -40,6 +49,8 @@ suite('Should run commands', () => { [ 'run', '-g', + '--port', + DEFAULT_GAME_PORT.toString(), quoted('file.program'), '--skipValidations', '-p', @@ -91,6 +102,8 @@ suite('Should run commands', () => { 'repl', quoted(pepitaURI.fsPath), '--skipValidations', + '--port', + DEFAULT_REPL_PORT.toString(), '--darkMode', '', // do not open dynamic diagram '-p', diff --git a/yarn.lock b/yarn.lock index 1d0b2e4..af91851 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8930,7 +8930,7 @@ __metadata: source-map-support: "npm:^0.5.21" ts-node: "npm:^10.9.1" typescript: "npm:^4.9.5" - wollok-ts: "npm:4.1.6" + wollok-ts: "npm:4.1.8" yarn-run-all: "npm:^3.1.1" languageName: unknown linkType: soft @@ -8948,6 +8948,19 @@ __metadata: languageName: node linkType: hard +"wollok-ts@npm:4.1.8": + version: 4.1.8 + resolution: "wollok-ts@npm:4.1.8" + dependencies: + "@types/parsimmon": "npm:^1.10.8" + parsimmon: "npm:^1.18.1" + prettier-printer: "npm:^1.1.4" + unraw: "npm:^3.0.0" + uuid: "npm:^9.0.1" + checksum: 10c0/57656102b6bfc7d4c3b84a6c27038fd8b6a9708c0e8a18526cdcb9e369ca229639503f7d26ef720c15644ab9230f019a422b39837e1bee90fa911afbd1a1b90d + languageName: node + linkType: hard + "word-wrap@npm:^1.2.5": version: 1.2.5 resolution: "word-wrap@npm:1.2.5"