diff --git a/server/src/lua/coroutine.ts b/server/src/lua/coroutine.ts new file mode 100644 index 00000000..3398c48b --- /dev/null +++ b/server/src/lua/coroutine.ts @@ -0,0 +1,165 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict' + +import { CompletionItem, CompletionItemKind, MarkupKind, ParameterInformation, SignatureInformation } from 'vscode-languageserver' + +const coroutineCompletions: Array = [ + { + kind: CompletionItemKind.Module, + label: 'coroutine' + }, + { + data: ['coroutine'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction create(f)\n```\n\ncoroutine.create(f) -> thread\n\ +\n\ +Creates and returns a new coroutine whose body is the given function f.' + }, + kind: CompletionItemKind.Function, + label: 'create' + }, + { + data: ['coroutine'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction resume(co, ...)\n```\n\ +\n\ +coroutine.resume(co, ...) -> false, string\n\ +\n\ +coroutine.resume(co, ...) -> true, yield arguments\n\ +\n\ +Starts the execution of the given coroutine co or resumes its execution from the last yield call. The first value \ +returned by this function indicates the error status of the coroutine co.\n\ +\n\ +If the error status is false, then the next value returned is the error message; otherwise the following values are \ +those passed to the yield function.' + }, + kind: CompletionItemKind.Function, + label: 'resume' + }, + { + data: ['coroutine'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction status(co)\n```\n\ncoroutine.status(co) -> string\n\ +\n\ +Returns the status of the given coroutine co as a string. Possible statuses are "running", "suspended", and "dead".' + }, + kind: CompletionItemKind.Function, + label: 'status' + }, + { + data: ['coroutine'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction wrap(f)\n```\n\ncoroutine.wrap(f) -> function\n\ +\n\ +Creates a new coroutine whose body is the given function f and returns a function that resumes the coroutine each \ +time it is called.\n\ +\n\ +Arguments passed to the returned function behave like those passed to a typical resume call. Return values from the \ +resulting function do not include an error status boolean.' + }, + kind: CompletionItemKind.Function, + label: 'wrap' + }, + { + data: ['coroutine'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction yield(...)\n```\n\ncoroutine.yield(...)\n\ +\n\ +Suspends execution of the current coroutine. Any arguments given are returned as extra results to the resume function.' + }, + kind: CompletionItemKind.Function, + label: 'yield' + }, +] + +const coroutineSignatures: Array = [ + SignatureInformation.create( + 'coroutine.create(f)', + undefined, + ParameterInformation.create( + 'f', + 'A function to use as the coroutine body.' + ), + ), + SignatureInformation.create( + 'coroutine.resume(co, ...)', + undefined, + ParameterInformation.create( + 'co', + 'A coroutine object of type "thread".' + ), + ParameterInformation.create( + '...', + 'Zero or more arguments to pass to the coroutine.' + ), + ), + SignatureInformation.create( + 'coroutine.status(co)', + undefined, + ParameterInformation.create( + 'co', + 'A coroutine object of type "thread".' + ), + ), + SignatureInformation.create( + 'coroutine.wrap(f)', + undefined, + ParameterInformation.create( + 'f', + 'A function to use as the coroutine body.' + ), + ), + SignatureInformation.create( + 'coroutine.yield(...)', + undefined, + ParameterInformation.create( + '...', + 'Zero or more arguments to return as extra results to the resume function.' + ), + ), +] + +export async function getCoroutineCompletions(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(coroutineCompletions) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} + +export async function getCoroutineSignatures(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(coroutineSignatures) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} diff --git a/server/src/lua/functions.ts b/server/src/lua/functions.ts new file mode 100644 index 00000000..4d96361a --- /dev/null +++ b/server/src/lua/functions.ts @@ -0,0 +1,620 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict' + +import { CompletionItem, CompletionItemKind, MarkupKind, ParameterInformation, SignatureInformation } from 'vscode-languageserver' + +const functionCompletions: Array = [ + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction assert(condition, message)\n```\n\nassert(condition[, message])\n\ +\n\ +Logs an error message when the boolean condition evaluates to false or nil. The message parameter defaults to \ +"assertion failed!"' + }, + kind: CompletionItemKind.Function, + label: 'assert' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction collectgarbage(limit)\n```\n\ncollectgarbage([limit])\n\ +\n\ +Sets the garbage-collection threshold to the given limit (in Kbytes) and checks it against the byte counter. If the \ +new threshold is smaller than the byte counter, then Lua immediately runs the garbage collector. If limit is absent, \ +it defaults to zero (thus forcing a garbage-collection cycle).' + }, + kind: CompletionItemKind.Function, + label: 'collectgarbage' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction dofile(filename)\n```\n\ndofile(filename) -> any\n\ +\n\ +Opens the named file and executes its contents as a Lua chunk. Returns any value returned by the chunk.' + }, + kind: CompletionItemKind.Function, + label: 'dofile' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction error(message, level)\n```\n\nerror(message[, level])\n\ +\n\ +Terminates the last protected function called and returns message as the error message. The level argument specifies \ +where the error message points the error and defaults to 1.\n\ +\n\ +When level is set to 1, the error position is where the error function was called. Level 2 points the error to where \ +the function that called error was called; and so on.' + }, + kind: CompletionItemKind.Function, + label: 'error' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction gcinfo()\n```\n\ngcinfo() -> number, number\n\ +\n\ +Returns `inUse, threshold` where \ +*inUse* is the number of Kbytes of dynamic memory Lua is using \ +and *threshold* is the current garbage collector threshold in Kbytes.' + }, + kind: CompletionItemKind.Function, + label: 'gcinfo' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction getfenv(f)\n```\n\ngetfenv([f]) -> table | f.__fenv\n\ +\n\ +Returns the current environment in use by the function. f can be a Lua function or a number, which specifies the \ +function at that stack level and defaults to 1. If the given function is not a Lua function, or if f is 0, getfenv \ +returns the global environment.\n\ +\n\ +If the environment has a "__fenv" field, its associated value is returned instead of the environment.\n\ +\n\ +Stack level 1 is the function calling this function.' + }, + kind: CompletionItemKind.Function, + label: 'getfenv' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction getmetatable(object)\n```\n\ngetmetatable(object) -> table | object.__metatable\n\ +\n\ +Returns the metatable of the given object. If the object does not have a metatable, then nil is returned. If the \ +object has a metatable and it has a "__metatable" field, the value of that field is returned.' + }, + kind: CompletionItemKind.Function, + label: 'getmetatable' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction ipairs(t)\n```\n\nipairs(t) -> iterator, table, 0\n\ +\n\ +Returns an iterator function, a table t, and 0 so that the construction\n\ +\n\ +`for i,v in ipairs(t) do ... end`\n\ +\n\ +will iterate over the pairs `(1,t[1])`, `(2,t[2])`, ..., up to the first integer key with a nil value.' + }, + kind: CompletionItemKind.Function, + label: 'ipairs' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction loadfile(filename)\n```\n\nloadfile(filename) -> function | nil\n\ +\n\ +Loads a file as a Lua chunk without running it. If there are no errors, the compiled chunk is returned as a function; \ +otherwise nil is returned and an error logged.\n\ +\n\ +The returned function resides in the global environment.' + }, + kind: CompletionItemKind.Function, + label: 'loadfile' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction loadstring(chunkString, chunkName)\n```\n\ +\n\ +loadstring(chunkString[, chunkName]) -> function | nil\n\ +\n\ +Loads chunkString as a Lua chunk without running it. If there are no errors, the compiled chunk is returned as a \ +function; otherwise nil is returned and an error logged. The optional chunkName is a string to be used in error \ +messages and debug information.\n\ +\n\ +The returned function resides in the global environment.' + }, + kind: CompletionItemKind.Function, + label: 'loadstring' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction next(t, i)\n```\n\nnext(t[, i]) -> number, any\n\ +\n\ +Returns `nextIndex, nextValue` where \ +*nextIndex* is the index of the next non-nil value of table t \ +and *nextValue* is the value of table t at nextIndex.\n\ +\n\ +If index i is omitted or nil, then nextIndex is the index of the first non-nil value found in table t.' + }, + kind: CompletionItemKind.Function, + label: 'next' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction pairs(t)\n```\npairs(t) -> iterator, table, nil\n\ +\n\ +Returns an iterator function, a table t, and nil so that the construction\n\ +\n\ +`for k,v in pairs(t) do ... end`\n\ +\n\ +will iterate over all key-value pairs of the given table t.' + }, + kind: CompletionItemKind.Function, + label: 'pairs' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction pcall(f, ...)\n```\n\ +\n\ +pcall(f[, ...]) -> false, string\n\ +\n\ +pcall(f[, ...]) -> true, f return values\n\ +\n\ +Calls function f with the given arguments in protected mode. In this mode, errors are caught before being logged. The \ +first value returned by this function indicates the error status of the given function f.\n\ +\n\ +If the error status is false, then the next value returned is the error message; otherwise the following values are \ +those returned by function f.' + }, + kind: CompletionItemKind.Function, + label: 'pcall' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction print(...)\n```\n\ +\n\ +Generate a response message.\n\ +\n\ +The output of each parameter is separated by a tab character.\n\ +\n\ +Numbers are printed using the format.asciiprecision attribute.' + }, + kind: CompletionItemKind.Function, + label: 'print', + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction rawequal(x, y)\n```\n\nrawequal(x, y) -> boolean\n\ +\n\ +Checks whether x is equal to y without invoking any metamethod. Returns true is x equals y and false otherwise.' + }, + kind: CompletionItemKind.Function, + label: 'rawequal' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction rawget(t, i)\n```\n\nrawget(t, i) -> any\n\ +\n\ +Returns the value of table t at index i without invoking any metamethod.\n\ +\n\ +t must be a table and i cannot be nil.' + }, + kind: CompletionItemKind.Function, + label: 'rawget' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction rawset(t, i, v)\n```\n\ +\n\ +Sets the value of table t at index i to value v without invoking any metamethod.\n\ +\n\ +t must be a table, i cannot be nil, and v is any value.' + }, + kind: CompletionItemKind.Function, + label: 'rawset' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction require(packagename)\n```\n\nrequire(packagename) -> any\n\ +\n\ +Loads the given package and returns what ever value is returned by that package. Return values of nil are converted \ +to true.' + }, + kind: CompletionItemKind.Function, + label: 'require' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction setfenv(f, t)\n```\n\ +\n\ +Sets the current environment table t to be used by the target f. f can be a Lua function or a number, which \ +specifies the function at that stack level. If f is 0, then the global environment of the current execution context \ +is changed.\n\ +\n\ +If the current environment of the target f has a "__fenv" field, then an error is raised.\n\ +\n\ +Stack level 1 is the function calling this function.' + }, + kind: CompletionItemKind.Function, + label: 'setfenv' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction setmetatable(t, m)\n```\n\ +\n\ +Set the metatable for the table t to the given table m. If table m is nil, then the metatable of table t is removed.\n\ +\n\ +If the table t has a metatable and it has a "__metatable" field, then an error is raised.' + }, + kind: CompletionItemKind.Function, + label: 'setmetatable' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction tonumber(v, base)\n```\n\ntonumber(v[, base]) -> number | nil\n\ +\n\ +Tries to convert the value v to a number. If it cannot be converted, then nil is returned. base defaults to 10.\n\ +\n\ +When converting to base 10, the value v may have a decimal or exponent. For all other bases, only unsigned integers \ +are accepted.' + }, + kind: CompletionItemKind.Function, + label: 'tonumber' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction tostring(v)\n```\n\ntostring(v) -> string\n\ +\n\ +Converts an argument of any type to a reasonably formatted string.\n\ +\n\ +If the metatable of v has a "__tostring" field, then it is invoked using the value v and its return value is used for \ +this result.' + }, + kind: CompletionItemKind.Function, + label: 'tostring' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction type(v)\n```\n\ntype(v) -> string\n\ +\n\ +Returns the Lua type of the argument as a string.' + }, + kind: CompletionItemKind.Function, + label: 'type' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction unpack(list)\n```\n\nunpack(list) -> list[1], ..., list[n]\n\ +\n\ +Returns all elements from the given list.' + }, + kind: CompletionItemKind.Function, + label: 'unpack' + }, + { + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction xpcall(f, errHandler)\n```\n\ +\n\ +pcall(f, errHandler) -> false, errHandler return values\n\ +\n\ +pcall(f, errHandler) -> true, f return values\n\ +\n\ +Calls function f in protected mode. In this mode, errors are caught before being logged. The first value returned by \ +this function indicates the error status of the given function f.\n\ +\n\ +If the error status is false, then the specified errHandler function is called and its return values are listed; \ +otherwise the following values are those returned by function f.' + }, + kind: CompletionItemKind.Function, + label: 'xpcall' + }, +] + +const functionSignatures: Array = [ + SignatureInformation.create( + 'assert(condition[, message])', + undefined, + ParameterInformation.create( + 'condition', + 'A boolean condition to evaluate.' + ), + ParameterInformation.create( + 'message', + 'Optional failure message string. Defaults to "assertion failed!"' + ), + ), + SignatureInformation.create( + 'collectgarbage([limit])', + undefined, + ParameterInformation.create( + 'limit', + 'A number representing the garbage-collection threshold in kilobytes.' + ), + ), + SignatureInformation.create( + 'dofile(filename)', + undefined, + ParameterInformation.create( + 'filename', + 'A string representing the path of the file to execute.' + ), + ), + SignatureInformation.create( + 'error(message[, level])', + undefined, + ParameterInformation.create( + 'message', + 'An error message string.' + ), + ParameterInformation.create( + 'level', + 'Stack level of the error location starting at 1. Defaults to 1 (here).' + ), + ), + SignatureInformation.create( + 'getfenv([f])', + undefined, + ParameterInformation.create( + 'f', + 'A function name or a stack level starting at 0 (global environment). Defaults to 1 (here).' + ), + ), + SignatureInformation.create( + 'getmetatable(object)', + undefined, + ParameterInformation.create( + 'object', + 'The target object of the function call.' + ), + ), + SignatureInformation.create( + 'ipairs(t)', + undefined, + ParameterInformation.create( + 't', + 'The table to iterate over.' + ), + ), + SignatureInformation.create( + 'loadfile(filename)', + undefined, + ParameterInformation.create( + 'filename', + 'A string representing the path of the file to load.' + ), + ), + SignatureInformation.create( + 'loadstring(chunkString[, chunkName])', + undefined, + ParameterInformation.create( + 'chunkString', + 'The string to load as a chunk.' + ), + ParameterInformation.create( + 'chunkName', + 'A string representing the name of the loaded chunk.' + ), + ), + SignatureInformation.create( + 'next(t[, i])', + undefined, + ParameterInformation.create( + 't', + 'The table to iterate over.' + ), + ParameterInformation.create( + 'i', + 'The previously returned index or nil to return the first index.' + ), + ), + SignatureInformation.create( + 'pairs(t)', + undefined, + ParameterInformation.create( + 't', + 'The table to iterate over.' + ), + ), + SignatureInformation.create( + 'pcall(f[, ...])', + undefined, + ParameterInformation.create( + 'f', + 'The function to call in protected mode.' + ), + ParameterInformation.create( + '...', + 'Zero or more arguments that will be passed to function f.' + ), + ), + SignatureInformation.create( + 'print(...)', + undefined, + ParameterInformation.create( + '...', + 'One or more values separated with commas.' + ), + ), + SignatureInformation.create( + 'rawequal(x, y)', + undefined, + ParameterInformation.create( + 'x', + 'An object whose equality will be compared against object y.' + ), + ParameterInformation.create( + 'y', + 'An object whose equality will be compared against object x.' + ), + ), + SignatureInformation.create( + 'rawget(t, i)', + undefined, + ParameterInformation.create( + 't', + 'The table to access.' + ), + ParameterInformation.create( + 'i', + 'The index of table t to access.' + ), + ), + SignatureInformation.create( + 'rawset(t, i, v)', + undefined, + ParameterInformation.create( + 't', + 'The table to access.' + ), + ParameterInformation.create( + 'i', + 'The index of table t to set.' + ), + ParameterInformation.create( + 'v', + 'The value of the table t at index i.' + ), + ), + SignatureInformation.create( + 'require(packagename)', + undefined, + ParameterInformation.create( + 'packagename', + 'A string or path string representing the package to load.' + ), + ), + SignatureInformation.create( + 'setfenv(f, t)', + undefined, + ParameterInformation.create( + 'f', + 'A function name or a stack level starting at 0 (current execution context).' + ), + ParameterInformation.create( + 't', + 'The new environment table.' + ), + ), + SignatureInformation.create( + 'setmetatable(t, m)', + undefined, + ParameterInformation.create( + 't', + 'The table whose metatable will be altered.' + ), + ParameterInformation.create( + 'm', + 'The new metatable or nil.' + ), + ), + SignatureInformation.create( + 'tonumber(v[, base])', + undefined, + ParameterInformation.create( + 'v', + 'Some value to convert.' + ), + ParameterInformation.create( + 'base', + 'Desired numeric base.' + ), + ), + SignatureInformation.create( + 'tostring(v)', + undefined, + ParameterInformation.create( + 'v', + 'Some value to convert.' + ), + ), + SignatureInformation.create( + 'type(v)', + undefined, + ParameterInformation.create( + 'v', + 'Some value to query.' + ), + ), + SignatureInformation.create( + 'unpack(list)', + undefined, + ParameterInformation.create( + 'list', + 'The list whose values will be returned.' + ), + ), + SignatureInformation.create( + 'xpcall(f, errHandler)', + undefined, + ParameterInformation.create( + 'f', + 'The function to call in protected mode.' + ), + ParameterInformation.create( + 'errHandler', + 'The function to call if an error occurs.' + ), + ), +] + +export async function getFunctionCompletions(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(functionCompletions) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} + +export async function getFunctionSignatures(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(functionSignatures) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} diff --git a/server/src/lua/index.ts b/server/src/lua/index.ts new file mode 100644 index 00000000..f9699485 --- /dev/null +++ b/server/src/lua/index.ts @@ -0,0 +1,48 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { CompletionItem, SignatureInformation } from 'vscode-languageserver' + +import { getCoroutineCompletions, getCoroutineSignatures } from './coroutine' +import { getFunctionCompletions, getFunctionSignatures } from './functions' +import { getKeywordCompletions } from './keywords' +import { getMathCompletions, getMathSignatures } from './math' +import { getOSCompletions, getOSSignatures } from './os' +import { getStringCompletions, getStringSignatures } from './string' +import { getTableCompletions, getTableSignatures } from './table' + +const completionsLua: Array = new Array() +const signaturesLua: Array = new Array() + +export async function getLuaCompletions(): Promise> { + return completionsLua + .concat(await getCoroutineCompletions()) + .concat(await getFunctionCompletions()) + .concat(await getKeywordCompletions()) + .concat(await getMathCompletions()) + .concat(await getOSCompletions()) + .concat(await getStringCompletions()) + .concat(await getTableCompletions()) +} + +export async function getLuaSignatures(): Promise> { + return signaturesLua + .concat(await getCoroutineSignatures()) + .concat(await getFunctionSignatures()) + .concat(await getMathSignatures()) + .concat(await getOSSignatures()) + .concat(await getStringSignatures()) + .concat(await getTableSignatures()) +} diff --git a/server/src/lua/keywords.ts b/server/src/lua/keywords.ts new file mode 100644 index 00000000..e64c83f1 --- /dev/null +++ b/server/src/lua/keywords.ts @@ -0,0 +1,94 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict' + +import { CompletionItem, CompletionItemKind } from 'vscode-languageserver' + +const keywordCompletions: Array = [ + { + kind: CompletionItemKind.Keyword, + label: 'break' + }, + { + kind: CompletionItemKind.Keyword, + label: 'do' + }, + { + kind: CompletionItemKind.Keyword, + label: 'else' + }, + { + kind: CompletionItemKind.Keyword, + label: 'elseif' + }, + { + kind: CompletionItemKind.Keyword, + label: 'end' + }, + { + kind: CompletionItemKind.Keyword, + label: 'for' + }, + { + kind: CompletionItemKind.Keyword, + label: 'function' + }, + { + kind: CompletionItemKind.Keyword, + label: 'if' + }, + { + kind: CompletionItemKind.Keyword, + label: 'in' + }, + { + kind: CompletionItemKind.Keyword, + label: 'local' + }, + { + kind: CompletionItemKind.Keyword, + label: 'repeat' + }, + { + kind: CompletionItemKind.Keyword, + label: 'return' + }, + { + kind: CompletionItemKind.Keyword, + label: 'then' + }, + { + kind: CompletionItemKind.Keyword, + label: 'until' + }, + { + kind: CompletionItemKind.Keyword, + label: 'while' + }, +] + +export async function getKeywordCompletions(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(keywordCompletions) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} diff --git a/server/src/lua/math.ts b/server/src/lua/math.ts new file mode 100644 index 00000000..6e6be5a8 --- /dev/null +++ b/server/src/lua/math.ts @@ -0,0 +1,519 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict' + +import { CompletionItem, CompletionItemKind, MarkupKind, ParameterInformation, SignatureInformation } from 'vscode-languageserver' + +const mathCompletions: Array = [ + { + kind: CompletionItemKind.Module, + label: 'math' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction abs(x)\n```\n\nmath.abs(x) -> number\n\ +\n\ +Returns the absolute value of x.' + }, + kind: CompletionItemKind.Function, + label: 'abs' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction acos(x)\n```\n\nmath.acos(x) -> number\n\ +\n\ +Returns the arc cosine, in radians, of the value x that lays in the interval [-1, +1]. An error is logged if the \ +given x is outside this interval.' + }, + kind: CompletionItemKind.Function, + label: 'acos' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction asin(x)\n```\n\nmath.asin(x) -> number\n\ +\n\ +Returns the arc sine, in radians, of the value x that lays in the interval [-1, +1]. An error is logged if the given \ +x is outside this interval.' + }, + kind: CompletionItemKind.Function, + label: 'asin' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction atan(x)\n```\n\nmath.atan(x) -> number\n\ +\n\ +Returns the arc tangent, in radians, of the value x.' + }, + kind: CompletionItemKind.Function, + label: 'atan' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction atan2(y, x)\n```\n\nmath.atan2(y, x) -> number\n\ +\n\ +Returns the arc tangent, in radians, of the value y/x.' + }, + kind: CompletionItemKind.Function, + label: 'atan2' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction ceil(x)\n```\n\nmath.ceil(x) -> number\n\ +\n\ +Rounds x upward, returning the smallest integer value greater than or equal to x.' + }, + kind: CompletionItemKind.Function, + label: 'ceil' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction cos(x)\n```\n\nmath.cos(x) -> number\n\ +\n\ +Returns the cosine of angle x in radians.' + }, + kind: CompletionItemKind.Function, + label: 'cos' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction deg(x)\n```\n\nmath.deg(x) -> number\n\ +\n\ +Convert from radians to degrees and return the result.' + }, + kind: CompletionItemKind.Function, + label: 'deg' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction exp(x)\n```\n\nmath.exp(x) -> number\n\ +\n\ +Returns the base-e exponential function of x (e^x).' + }, + kind: CompletionItemKind.Function, + label: 'exp' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction floor(x)\n```\n\nmath.floor(x) -> number\n\ +\n\ +Rounds x downward, returning the largest integer value less than or equal to x.' + }, + kind: CompletionItemKind.Function, + label: 'floor' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction frexp(x)\n```\n\nmath.frexp(x) -> number, number\n\ +\n\ +Breaks x into its binary significand and exponent, returning `significand, exponent` where \ +*significand* is an absolute value that lays in the interval [0.5, 1) \ +and *exponent* is the integer exponent of 2.\n\ +\n\ +The significand and exponent are calculated from the expression:\n\ +\n\ +`x = significand * 2^exponent`' + }, + kind: CompletionItemKind.Function, + label: 'frexp' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction ldexp(x, exp)\n```\n\nmath.ldexp(x, exp) -> number\n\ +\n\ +Returns the result of the following expression:\n\ +\n\ +`x * 2 ^ exp`' + }, + kind: CompletionItemKind.Function, + label: 'ldexp' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction log(x)\n```\n\nmath.log(x) -> number\n\ +\n\ +Returns the natural logarithm of x.' + }, + kind: CompletionItemKind.Function, + label: 'log' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction log10(x)\n```\n\nmath.log10(x) -> number\n\ +\n\ +Returns the common (base-10) logarithm of x.' + }, + kind: CompletionItemKind.Function, + label: 'log10' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction max(...)\n```\n\nmath.max(...) -> number\n\ +\n\ +Returns the maximum value of its numeric arguments.' + }, + kind: CompletionItemKind.Function, + label: 'max' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction min(...)\n```\n\nmath.min(...) -> number\n\ +\n\ +Returns the minimum value of its numeric arguments.' + }, + kind: CompletionItemKind.Function, + label: 'min' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction pow(base, exp)\n```\n\nmath.pow(base, exp) -> number\n\ +\n\ +Returns the result of base raised to the power exp.' + }, + kind: CompletionItemKind.Function, + label: 'pow' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction rad(x)\n```\n\nmath.rad(x) -> number\n\ +\n\ +Convert from degrees to radians and return the result.' + }, + kind: CompletionItemKind.Function, + label: 'rad' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction random(x, y)\n```\n\nmath.random([x[, y]]) -> number\n\ +\n\ +When called without arguments, return a pseudo-random value that lays in the interval [0, 1). When x is specified, \ +this interval is [1, x]. When both x and y are specified, the interval is [x, y].' + }, + kind: CompletionItemKind.Function, + label: 'random' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction randomseed(x)\n```\n\ +\n\ +Use the given seed x for the pseudo-random number generator.' + }, + kind: CompletionItemKind.Function, + label: 'randomseed' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction sin(x)\n```\n\nmath.sin(x) -> number\n\ +\n\ +Returns the sine of angle x in radians.' + }, + kind: CompletionItemKind.Function, + label: 'sin' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction sqrt(x)\n```\n\nmath.sqrt(x) -> number\n\ +\n\ +Return the square root of x. An error is logged if x is negative.' + }, + kind: CompletionItemKind.Function, + label: 'sqrt' + }, + { + data: ['math'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction tan(x)\n```\n\nmath.tan(x) -> number\n\ +\n\ +Returns the tangent of angle x in radians.' + }, + kind: CompletionItemKind.Function, + label: 'tan' + }, +] + +const mathSignatures: Array = [ + SignatureInformation.create( + 'math.abs(x)', + undefined, + ParameterInformation.create( + 'x' + ), + ), + SignatureInformation.create( + 'math.acos(x)', + undefined, + ParameterInformation.create( + 'x', + 'A number on the interval [-1, +1].' + ), + ), + SignatureInformation.create( + 'math.asin(x)', + undefined, + ParameterInformation.create( + 'x', + 'A number on the interval [-1, +1].' + ), + ), + SignatureInformation.create( + 'math.atan(x)', + undefined, + ParameterInformation.create( + 'x' + ), + ), + SignatureInformation.create( + 'math.atan2(y, x)', + undefined, + ParameterInformation.create( + 'y', + 'A number representing the y-coordinate.' + ), + ParameterInformation.create( + 'x', + 'A number representing the x-coordinate.' + ), + ), + SignatureInformation.create( + 'math.ceil(x)', + undefined, + ParameterInformation.create( + 'x', + 'Number to round upward.' + ), + ), + SignatureInformation.create( + 'math.cos(x)', + undefined, + ParameterInformation.create( + 'x', + 'An angle in radians.' + ), + ), + SignatureInformation.create( + 'math.deg(x)', + undefined, + ParameterInformation.create( + 'x', + 'An angle in radians.' + ), + ), + SignatureInformation.create( + 'math.exp(x)', + undefined, + ParameterInformation.create( + 'x', + 'The exponent to raise e.' + ), + ), + SignatureInformation.create( + 'math.floor(x)', + undefined, + ParameterInformation.create( + 'x', + 'Number to round downward.' + ), + ), + SignatureInformation.create( + 'math.frexp(x)', + undefined, + ParameterInformation.create( + 'x', + 'Number to decompose into a significand and power of 2.' + ), + ), + SignatureInformation.create( + 'math.ldexp(x, exp)', + undefined, + ParameterInformation.create( + 'x', + 'Binary significand.' + ), + ParameterInformation.create( + 'exp', + 'Binary exponent.' + ), + ), + SignatureInformation.create( + 'math.log(x)', + undefined, + ParameterInformation.create( + 'x' + ), + ), + SignatureInformation.create( + 'math.log10(x)', + undefined, + ParameterInformation.create( + 'x' + ), + ), + SignatureInformation.create( + 'math.max(...)', + undefined, + ParameterInformation.create( + '...', + 'One or more numbers to compare.' + ), + ), + SignatureInformation.create( + 'math.min(...)', + undefined, + ParameterInformation.create( + '...', + 'One or more numbers to compare.' + ), + ), + SignatureInformation.create( + 'math.pow(base, exp)', + undefined, + ParameterInformation.create( + 'base' + ), + ParameterInformation.create( + 'exp' + ), + ), + SignatureInformation.create( + 'math.rad(x)', + undefined, + ParameterInformation.create( + 'x', + 'An angle in degrees.' + ), + ), + SignatureInformation.create( + 'math.random(x)', + undefined, + ParameterInformation.create( + 'x', + 'Upper bound of the inclusive interval [1, x].' + ), + ), + SignatureInformation.create( + 'math.random(x, y)', + undefined, + ParameterInformation.create( + 'x', + 'Lower bound of the inclusive interval [x, y].' + ), + ParameterInformation.create( + 'y', + 'Upper bound of the inclusive interval [x, y].' + ), + ), + SignatureInformation.create( + 'math.randomseed(x)', + undefined, + ParameterInformation.create( + 'x' + ), + ), + SignatureInformation.create( + 'math.sin(x)', + undefined, + ParameterInformation.create( + 'x', + 'An angle in degrees.' + ), + ), + SignatureInformation.create( + 'math.sqrt(x)', + undefined, + ParameterInformation.create( + 'x', + 'A non-negative number.' + ), + ), + SignatureInformation.create( + 'math.tan(x)', + undefined, + ParameterInformation.create( + 'x', + 'An angle in degrees.' + ), + ), +] + +export async function getMathCompletions(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(mathCompletions) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} + +export async function getMathSignatures(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(mathSignatures) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} diff --git a/server/src/lua/os.ts b/server/src/lua/os.ts new file mode 100644 index 00000000..40f1e528 --- /dev/null +++ b/server/src/lua/os.ts @@ -0,0 +1,167 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict' + +import { CompletionItem, CompletionItemKind, MarkupKind, ParameterInformation, SignatureInformation } from 'vscode-languageserver' + +const osCompletions: Array = [ + { + kind: CompletionItemKind.Module, + label: 'os' + }, + { + data: ['os'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction clock()\n```\n\nos.clock() -> number\n\ +\n\ +Returns an approximation of the total CPU time used by the calling program, in seconds.' + }, + kind: CompletionItemKind.Function, + label: 'clock' + }, + { + data: ['os'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction date(format, time)\n```\n\nos.date([format[, time]]) -> string | table\n\ +\n\ +Converts the number of time seconds to a string or table based on the supplied format and returns the resulting \ +value. If time is omitted, then the current time is used. If format is omitted, then it defaults to "%c".\n\ +\n\ +If the format string begins with "!", then the date is formatted in Coordinated Universal Time. After the UTC \ +optional character, if format is "*t", then the current date is returned as a table. All other format specifiers will \ +result in a string and follow the convention set by the C-language strftime function.\n\ +\n\ +Tables returned from this function contain the fields year (four digits), month (1-12), day (1-31), hour (0-23), min \ +(0-59), sec (0-61), wday (1-7, where 1 is Sunday), yday (1-366), and isdst (daylight savings boolean).' + }, + kind: CompletionItemKind.Function, + label: 'date' + }, + { + data: ['os'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction difftime(t1, t2)\n```\n\nos.difftime(t1, t2) -> number\n\ +\n\ +Returns the number of seconds from time t1 to time t2.' + }, + kind: CompletionItemKind.Function, + label: 'difftime' + }, + { + data: ['os'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction rename(source, destination)\n```\n\ +\n\ +os.rename(source, destination) -> void | nil, string\n\ +\n\ +Renames the source file to destination. If the function fails, it returns nil and the error message as a string; \ +otherwise nothing is returned.' + }, + kind: CompletionItemKind.Function, + label: 'rename' + }, + { + data: ['os'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction time(t)\n```\n\nos.time(t) -> number\n\ +\n\ +Converts a time table into seconds since January 1, 1970 and returns the resulting value.\n\ +\n\ +A time table must contain a year, month, and day field. If present, the hour, min, sec, and isdst fields will be used \ +for a more accurate conversion.' + }, + kind: CompletionItemKind.Function, + label: 'time' + }, +] + +const osSignatures: Array = [ + SignatureInformation.create( + 'os.date([format[, time]])', + undefined, + ParameterInformation.create( + 'format', + 'A date format string. Optionally begins with "!" for UTC. "*t" returns a time table. All other format \ +specifiers follow the convention set by the C-language strftime function.' + ), + ParameterInformation.create( + 'time', + 'An optional number representing a time in seconds.' + ), + ), + SignatureInformation.create( + 'os.difftime(t1, t2)', + undefined, + ParameterInformation.create( + 't1' + ), + ParameterInformation.create( + 't2' + ), + ), + SignatureInformation.create( + 'os.rename(source, destination)', + undefined, + ParameterInformation.create( + 'source', + 'The filepath of the target file as a string.' + ), + ParameterInformation.create( + 'destination', + 'The new filepath of the source file.' + ), + ), + SignatureInformation.create( + 'os.time(t)', + undefined, + ParameterInformation.create( + 't', + 'A time table that contains a year, month, and day field. The hour, min, sec, and isdst fields are used \ +if available.' + ), + ), +] + +export async function getOSCompletions(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(osCompletions) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} + +export async function getOSSignatures(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(osSignatures) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} diff --git a/server/src/lua/string.ts b/server/src/lua/string.ts new file mode 100644 index 00000000..af2f4856 --- /dev/null +++ b/server/src/lua/string.ts @@ -0,0 +1,327 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict' + +import { CompletionItem, CompletionItemKind, MarkupKind, ParameterInformation, SignatureInformation } from 'vscode-languageserver' + +const stringCompletions: Array = [ + { + kind: CompletionItemKind.Module, + label: 'string' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction byte(s, index)\n```\n\nstring.byte(s[, index]) -> number | nil\n\ +\n\ +Returns the numeric representation of the character at the index of s or nil if index is out of range. If omitted, \ +then index defaults to 1.' + }, + kind: CompletionItemKind.Function, + label: 'byte' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction char(...)\n```\n\nstring.char([...]) -> string\n\ +\n\ +Returns a string comprised of the given arguments concatenated together, where each argument is a numeric character \ +representation.' + }, + kind: CompletionItemKind.Function, + label: 'char' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction dump(f)\n```\n\nstring.dump(f) -> string\n\ +\n\ +Returns a binary string representation of the given function f.' + }, + kind: CompletionItemKind.Function, + label: 'dump' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction find(s, pattern, start, plain)\n```\n\ +\n\ +string.find(s, pattern[, start[, plain]]) -> number, number, captures\n\ +\n\ +Looks for the first match of pattern in the string s, starting at the given start index (or 1 if omitted). If a match \ +is found, then the start and end indices of the match are returned; otherwise nil is returned. Any group captures are \ +returned as extra results. If plain is true, then a plain-text search is performed; defaults to false if omitted.' + }, + kind: CompletionItemKind.Function, + label: 'find' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction format(formatstring, ...)\n```\n\ +\n\ +string.format(formatstring[, ...]) -> string\n\ +\n\ +Returns a formatted string based on its formatstring and variable arguments. The formatstring adheres to a C-like \ +printf syntax.' + }, + kind: CompletionItemKind.Function, + label: 'format' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction gsub(s, pattern, repl, n)\n```\n\ +\n\ +string.gsub(s, pattern, repl[, n]) -> string, number\n\ +\n\ +Returns a copy of s in which the first n occurrences of the pattern have been replaced with the string repl. If n is \ +omitted, then all occurrences are replaced. The second return value is the total number of replacements made.\n\ +\n\ +If repl is a string, then it may contain capture-group specifiers of the form "%n", where n is a number between 1 and \ +9.\n\ +\n\ +If repl is a function, then it is called for every match, with all captured substrings being passed as arguments in \ +order of capture. If pattern contains no capture groups, then the whole match is passed as a single argument. If the \ +repl function returns a string, then it is used as the replacement; otherwise an empty string is used.' + }, + kind: CompletionItemKind.Function, + label: 'gsub' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction len(s)\n```\n\nstring.len(s) -> number\n\ +\n\ +Returns the length of the given string s, including any embedded null characters.' + }, + kind: CompletionItemKind.Function, + label: 'len' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction lower(s)\n```\n\nstring.lower(s) -> string\n\ +\n\ +Returns a copy of the string s with all cased characters converted to lowercase.' + }, + kind: CompletionItemKind.Function, + label: 'lower' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction rep(s, n)\n```\n\nstring.rep(s, n) -> string\n\ +\n\ +Returns a string that is the concatenation of n copies of the string s.' + }, + kind: CompletionItemKind.Function, + label: 'rep' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction sub(s, start, end)\n```\n\nstring.sub(s, start[, end]) -> string\n\ +\n\ +Returns the substring of s that begins at the start index and continues until the end index. Both indices are \ +inclusive. If omitted, the end index defaults to -1 (the last index).' + }, + kind: CompletionItemKind.Function, + label: 'sub' + }, + { + data: ['string'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction upper(s)\n```\n\nstring.upper(s) -> string\n\ +\n\ +Returns a copy of the string s with all cased characters converted to uppercase.' + }, + kind: CompletionItemKind.Function, + label: 'upper' + }, +] + +const stringSignatures: Array = [ + SignatureInformation.create( + 'string.byte(s[, index])', + undefined, + ParameterInformation.create( + 's', + 'The target string.' + ), + ParameterInformation.create( + 'index', + 'An optional one-based index. Defaults to 1.' + ), + ), + SignatureInformation.create( + 'string.char([...])', + undefined, + ParameterInformation.create( + '...', + 'Zero or more integers representing character codes.' + ), + ), + SignatureInformation.create( + 'string.dump(f)', + undefined, + ParameterInformation.create( + 'f', + 'A function to convert to a binary string.' + ), + ), + SignatureInformation.create( + 'string.find(s, pattern[, start[, plain]])', + undefined, + ParameterInformation.create( + 's', + 'The target string.' + ), + ParameterInformation.create( + 'pattern', + 'A pattern string.' + ), + ParameterInformation.create( + 'start', + 'The index to start searching. Defaults to 1.' + ), + ParameterInformation.create( + 'plain', + 'Whether or not to perform a plain-text search. Defaults to false (disabled).' + ), + ), + SignatureInformation.create( + 'string.format(formatstring[, ...])', + undefined, + ParameterInformation.create( + 'formatstring', + 'A C-like printf format string.' + ), + ParameterInformation.create( + '...', + 'Zero or more arguments as required by the formatstring.' + ), + ), + SignatureInformation.create( + 'string.gsub(s, pattern, repl[, n])', + undefined, + ParameterInformation.create( + 's', + 'The target string.' + ), + ParameterInformation.create( + 'pattern', + 'A pattern string.' + ), + ParameterInformation.create( + 'repl', + 'A replacement string or replacement function that returns the string to use for the match substitution.' + ), + ParameterInformation.create( + 'n', + 'The maximum number of substitutions to perform. Defaults to all occurrences.' + ), + ), + SignatureInformation.create( + 'string.len(s)', + undefined, + ParameterInformation.create( + 's', + 'The target string.' + ), + ), + SignatureInformation.create( + 'string.lower(s)', + undefined, + ParameterInformation.create( + 's', + 'The target string.' + ), + ), + SignatureInformation.create( + 'string.rep(s, n)', + undefined, + ParameterInformation.create( + 's', + 'The source string.' + ), + ParameterInformation.create( + 'n', + 'The number of times to duplicate the source string s.' + ), + ), + SignatureInformation.create( + 'string.sub(s, start[, end])', + undefined, + ParameterInformation.create( + 's', + 'The target string.' + ), + ParameterInformation.create( + 'start', + 'The one-based index to begin the substring (inclusive). May be negative.' + ), + ParameterInformation.create( + 'end', + 'An optional one-based index to end the substring (inclusive). May be negative. Defaults to -1.' + ), + ), + SignatureInformation.create( + 'string.upper(s)', + undefined, + ParameterInformation.create( + 's', + 'The target string.' + ), + ), +] + +export async function getStringCompletions(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(stringCompletions) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} + +export async function getStringSignatures(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(stringSignatures) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} diff --git a/server/src/lua/table.ts b/server/src/lua/table.ts new file mode 100644 index 00000000..4391ec3a --- /dev/null +++ b/server/src/lua/table.ts @@ -0,0 +1,179 @@ +/* + * Copyright 2018 Tektronix Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict' + +import { CompletionItem, CompletionItemKind, MarkupKind, ParameterInformation, SignatureInformation } from 'vscode-languageserver' + +const tableCompletions: Array = [ + { + kind: CompletionItemKind.Module, + label: 'table' + }, + { + data: ['table'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction concat(t, sep, start, end)\n```\n\ +\n\ +table.concat(t[, sep[, start[, end]]]) -> string\n\ +\n\ +Returns the concatenation of all sequential, non-nil values of the given table t starting at index 1. An emtpy string \ +is returned if the start index is greater than the end index. The string separator sep defaults to an empty string, \ +the start index defaults to 1, and the end index defaults to the size of the table.' + }, + kind: CompletionItemKind.Function, + label: 'concat' + }, + { + data: ['table'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction insert(t, index, v)\n```\n\ntable.insert(t[, index], v)\n\ +\n\ +Inserts the value v into table t at the index. If index is omitted, then the new value is inserted at the end of the \ +table.' + }, + kind: CompletionItemKind.Function, + label: 'insert' + }, + { + data: ['table'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction remove(t, index)\n```\n\ntable.remove(t[, index]) -> any\n\ +\n\ +Remove and return the element of table t at the index. If index is omitted, then the last table element is removed.' + }, + kind: CompletionItemKind.Function, + label: 'remove' + }, + { + data: ['table'], + documentation: { + kind: MarkupKind.Markdown, + value: '```lua\nfunction sort(t, f)\n```\n\ntable.sort(t[, f])\n\ +\n\ +Performs an in-place sort of table t using the function f as a callback. If the function f is omitted, then the less \ +than operator (<) is used.\n\ +\n\ +Function f must accept two arguments and return true when the first is less than the second.' + }, + kind: CompletionItemKind.Function, + label: 'sort' + }, +] + +const tableSignatures: Array = [ + SignatureInformation.create( + 'table.concat(t[, sep[, start[, end]]])', + undefined, + ParameterInformation.create( + 't', + 'The target table.' + ), + ParameterInformation.create( + 'sep', + 'The string to add between each element. Defaults to an empty string.' + ), + ParameterInformation.create( + 'start', + 'The starting index (inclusive). Defaults to 1.' + ), + ParameterInformation.create( + 'end', + 'The ending index (inclusive). Defaults to the size of the table.' + ), + ), + SignatureInformation.create( + 'table.insert(t, v)', + 'Insert an element into the last position of the table.', + ParameterInformation.create( + 't', + 'The target table.' + ), + ParameterInformation.create( + 'v', + 'The value to insert.' + ), + ), + SignatureInformation.create( + 'table.insert(t, index, v)', + 'Insert an element into the specified table index.', + ParameterInformation.create( + 't', + 'The target table.' + ), + ParameterInformation.create( + 'index', + 'The one-based index of the new value.' + ), + ParameterInformation.create( + 'v', + 'The value to insert.' + ), + ), + SignatureInformation.create( + 'table.remove(t[, index])', + undefined, + ParameterInformation.create( + 't', + 'The target table.' + ), + ParameterInformation.create( + 'index', + 'The one-based index to remove.' + ), + ), + SignatureInformation.create( + 'table.sort(t[, f])', + undefined, + ParameterInformation.create( + 't', + 'The target table.' + ), + ParameterInformation.create( + 'f', + 'An optional sorting function that accepts two arguments and returns true when the first is less than the \ +second. Defaults to using the less than operator (<).' + ), + ), +] + +export async function getTableCompletions(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(tableCompletions) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} + +export async function getTableSignatures(): Promise> { + return new Promise>(( + resolve: (value?: Array) => void, + reject: (reason?: Error) => void + ): void => { + try { + resolve(tableSignatures) + } catch (e) { + reject(new Error(e.toString())) + } + }) +} diff --git a/server/src/tspManager.ts b/server/src/tspManager.ts index 7d98a3ac..11fb5a67 100644 --- a/server/src/tspManager.ts +++ b/server/src/tspManager.ts @@ -201,6 +201,8 @@ export class TspManager { resolve: (value?: TspItem) => void, reject: (reason?: Error) => void ): Promise => { + const luaCompletions: Array = new Array() + const luaSignatures: Array = new Array() let shebangTokens: Array try { // get native Lua completions diff --git a/server/src/tspPool.ts b/server/src/tspPool.ts index 3c590fe2..747a33fe 100644 --- a/server/src/tspPool.ts +++ b/server/src/tspPool.ts @@ -92,6 +92,23 @@ export class TspPool { resolve: (value?: PoolEntry) => void, reject: (reason?: Error) => void ) : Promise => { + let complLua: Array = new Array() + let signaLua: Array = new Array() + + try { + complLua = await getLuaCompletions() + } + catch (e) { + reject(new Error('Unable to load Lua completions')) + } + + try { + signaLua = await getLuaSignatures() + } + catch (e) { + reject(new Error('Unable to load Lua signatures')) + } + switch (model) { case Model.KI2450: try {