diff --git a/uni/ulsp/Makefile b/uni/ulsp/Makefile index a5244e306..62a1cfb77 100644 --- a/uni/ulsp/Makefile +++ b/uni/ulsp/Makefile @@ -5,10 +5,10 @@ UFLAGS=-s -u prog=ulsp -SRC=launch-lsp.icn workspace.icn database.icn server.icn completion.icn signature.icn hover.icn \ - definition.icn jsonrpc.icn logger.icn -OBJ=launch-lsp.u workspace.u database.u server.u completion.u signature.u hover.u definition.u \ - jsonrpc.u logger.u +SRC=launch-lsp.icn file_handler.icn database.icn server.icn completion.icn signature.icn hover.icn \ + definition.icn jsonrpc.icn logger.icn lsif.icn +OBJ=launch-lsp.u file_handler.u database.u server.u completion.u signature.u hover.u definition.u \ + jsonrpc.u logger.u lsif.u export IPATH=$(UNI)/unidoc @@ -22,14 +22,14 @@ $(prog): $(OBJ) jsonrpc-test: jsonrpc-test.u jsonrpc.u $(UC) -o jsonrpc-test jsonrpc-test.u jsonrpc.u -launch-lsp.u:launch-lsp.icn workspace.u database.u server.u completion.u signature.u hover.u definition.u +launch-lsp.u: launch-lsp.icn file_handler.u database.u server.u completion.u signature.u hover.u definition.u -server.u:server.icn database.u completion.u workspace.u signature.u hover.u definition.u jsonrpc.u logger.u -hover.u:hover.icn signature.u +server.u: server.icn database.u completion.u file_handler.u signature.u hover.u definition.u jsonrpc.u logger.u +hover.u: hover.icn signature.u definition.u: definition.icn hover.u zip: zip ulsp.zip Makefile *.icn clean: - $(RM) -f *.u $(prog) uniclass* + $(RM) -f *.u $(prog) uniclass* \ No newline at end of file diff --git a/uni/ulsp/completion.icn b/uni/ulsp/completion.icn index 4a362f6bf..0b5b4d911 100644 --- a/uni/ulsp/completion.icn +++ b/uni/ulsp/completion.icn @@ -3,12 +3,12 @@ package ulsp import json class CompletionHandler( - workspace, + filehandler, params ) - method setVariables(new_workspace, new_params) - workspace := new_workspace + method setVariables(new_filehandler, new_params) + filehandler := new_filehandler params := new_params end @@ -18,7 +18,7 @@ class CompletionHandler( line := params["position"]["line"] + 1 character := params["position"]["character"] + 1 - context := workspace.getContext(line, character) + context := filehandler.getContext(line, character) desired_line := context.line _context := context.getCase() @@ -34,10 +34,10 @@ class CompletionHandler( results_table["items"] := [] } "object" : { - workspace.buildObjectCompletionItems(results_table, context.objectName) + filehandler.buildObjectCompletionItems(results_table, context.objectName) } "packdualcolon" : { - workspace.buildPackageConstructorItems(results_table, context.packageName) + filehandler.buildPackageConstructorItems(results_table, context.packageName) } "package" : { addPackageCompletionItems(results_table) @@ -46,7 +46,7 @@ class CompletionHandler( addFileCompletionItems(results_table) } default : { - buildDefaultCompletionItems(results_table, workspace) + buildDefaultCompletionItems(results_table, filehandler) } } @@ -55,115 +55,115 @@ class CompletionHandler( method addBuiltInFunctionsCompletionItems(results_table) local _function - every _function := key(workspace.getBuiltInFunctions()) do { + every _function := key(filehandler.getBuiltInFunctions()) do { put(results_table["items"], table("label", _function, "kind", 3)) } end method addActionWordsCompletionItems(results_table) local _actionWord - every _actionWord := !workspace.getActionWords() do { + every _actionWord := !filehandler.getActionWords() do { put(results_table["items"], table("label", _actionWord)) } end method addDeclarativeExpressionsCompletionItems(results_table) local _declarativeExpression - every _declarativeExpression := !workspace.getDeclarativeExpressions() do { + every _declarativeExpression := !filehandler.getDeclarativeExpressions() do { put(results_table["items"], table("label", _declarativeExpression)) } end method addSyntaxReservedWordsCompletionItems(results_table) local _syntaxReservedWord - every _syntaxReservedWord := !workspace.getSyntaxReservedWords() do { + every _syntaxReservedWord := !filehandler.getSyntaxReservedWords() do { put(results_table["items"], table("label", _syntaxReservedWord)) } end method addKeywordsCompletionItems(results_table) local _keyword - every _keyword := !workspace.getKeywords() do { + every _keyword := !filehandler.getKeywords() do { put(results_table["items"], table("label", _keyword, "kind", 14)) } end method addPreprocessorCompletionItems(results_table) local _preprocessor - every _preprocessor := !workspace.getPreprocessors() do { + every _preprocessor := !filehandler.getPreprocessors() do { put(results_table["items"], table("label", _preprocessor)) } end - method addWorkspaceProcedures(results_table, workspace) + method addFileHandlerProcedures(results_table, filehandler) local _internalProcedure, _linkedProcedure, _importedProcedure, _packageProcedure - every _internalProcedure := key(workspace.getInternalProcedures()) do { + every _internalProcedure := key(filehandler.getInternalProcedures()) do { put(results_table["items"], table("label", _internalProcedure, "kind", 3)) } - every _linkedProcedure := key(workspace.getLinkedProcedures()) do { + every _linkedProcedure := key(filehandler.getLinkedProcedures()) do { put(results_table["items"], table("label", _linkedProcedure, "kind", 3)) } - every _importedProcedure := key(workspace.getImportedProcedures()) do { + every _importedProcedure := key(filehandler.getImportedProcedures()) do { put(results_table["items"], table("label", _importedProcedure, "kind", 3)) } - every _packageProcedure := key(workspace.getPackageProcedures()) do { + every _packageProcedure := key(filehandler.getPackageProcedures()) do { put(results_table["items"], table("label", _packageProcedure, "kind", 3)) } end - method addWordspaceClasses(results_table, workspace) + method addWordspaceClasses(results_table, filehandler) local _internalClass, _linkedClass, _importedClass, _packageClass - every _internalClass := key(workspace.getInternalClasses()) do { + every _internalClass := key(filehandler.getInternalClasses()) do { put(results_table["items"], table("label", _internalClass, "kind", 4)) } - every _linkedClass := key(workspace.getLinkedClasses()) do { + every _linkedClass := key(filehandler.getLinkedClasses()) do { put(results_table["items"], table("label", _linkedClass, "kind", 4)) } - every _importedClass := key(workspace.getImportedClasses()) do { + every _importedClass := key(filehandler.getImportedClasses()) do { put(results_table["items"], table("label", _importedClass, "kind", 4)) } - every _packageClass := key(workspace.getPackageClasses()) do { + every _packageClass := key(filehandler.getPackageClasses()) do { put(results_table["items"], table("label", _packageClass, "kind", 4)) } end - method addInternalObjects(results_table, workspace) + method addInternalObjects(results_table, filehandler) local _object - every _object := key(workspace.getObjects()) do { + every _object := key(filehandler.getObjects()) do { put(results_table["items"], table("label", _object, "kind", 6)) } end - method addInternalVariables(results_table, workspace) + method addInternalVariables(results_table, filehandler) local _variable - every _variable := key(workspace.getVariables()) do { + every _variable := key(filehandler.getVariables()) do { put(results_table["items"], table("label", _variable, "kind", 6)) } end - method buildDefaultCompletionItems(results_table, workspace) + method buildDefaultCompletionItems(results_table, filehandler) addActionWordsCompletionItems(results_table) addBuiltInFunctionsCompletionItems(results_table) addDeclarativeExpressionsCompletionItems(results_table) addKeywordsCompletionItems(results_table) addPreprocessorCompletionItems(results_table) addSyntaxReservedWordsCompletionItems(results_table) - addWordspaceClasses(results_table, workspace) - addWorkspaceProcedures(results_table, workspace) - addInternalObjects(results_table, workspace) - addInternalVariables(results_table, workspace) + addWordspaceClasses(results_table, filehandler) + addFileHandlerProcedures(results_table, filehandler) + addInternalObjects(results_table, filehandler) + addInternalVariables(results_table, filehandler) end method addFileCompletionItems(results_table) local _file - every _file := !workspace.getFileNames() do { + every _file := !filehandler.getFileNames() do { put(results_table["items"], table("label", _file, "kind", 17)) } end method addPackageCompletionItems(results_table) local _package - every _package := key(workspace.getPackages()) do { + every _package := key(filehandler.getPackages()) do { if _package === "(main)" then next put(results_table["items"], table("label", _package, "kind", 12)) } diff --git a/uni/ulsp/database.icn b/uni/ulsp/database.icn index 6ee5deec1..415179823 100644 --- a/uni/ulsp/database.icn +++ b/uni/ulsp/database.icn @@ -11,7 +11,6 @@ package ulsp import UniDoc - link paths global Logger @@ -24,19 +23,23 @@ class LSPDB( syntax_reserved_words, # List containing the syntax reserved words (subset of reserved words) keywords, # List containing all keywords preprocessors, # List containing all preprocessors - + dir_list, unicon_dir ) - method build() + method build(lsif_path) built_in_functions := table() package_db := table() + dir_list := [] if \unicon_dir then { build_bnf() - build_package_db() + if \lsif_path then + build_package_db(lsif_path) + else + build_package_db() } else { write(&errout, "Unable to find Unicon envirionment.") @@ -97,11 +100,17 @@ class LSPDB( } end - method build_package_db() + method build_package_db(lsif_path) local dirPath, db_paths := [], dir dirPath := unicon_dir - + if (\lsif_path) then { + lsif_path := map(lsif_path, "\\", "/") + put(dir_list, lsif_path) + Logger.debug2_kind("db:path", "Processing ", lsif_path) + build_by_path(lsif_path) + return + } every dir := !ipaths_get() do # remove the current dir, also skip parser due to a unidoc bug if not((dir == ("." | "")) | find("uni/parser"|"uni\\parser", dir))then @@ -112,15 +121,23 @@ class LSPDB( Logger.debug1_kind("db", "Looking in unicon paths") every dir := !db_paths do { + dir := map(dir, "\\", "/") + put(dir_list, dir) Logger.debug2_kind("db:path", "Processing ", dir) build_by_path(dir) } + put(dir_list, unicon_dir || "uni/ulsp") end method build_by_path(path) local idoc, x, pack, file_in_pack, file_without_ext, import_in_file, procedure_in_file, param_in_procedure, - paramName, paramType, paramDef, class_in_file, method_in_class, param_in_method, class_param, class_comment, - constructor_param + paramName, paramType, paramDef, class_in_file, method_in_class, param_in_method, class_param, + class_comment, constructor_param, package_table, file_table, file_wo_ext_table, import_table, + procedure_table, procedure_in_file_table, param_table, classes_table, class_in_file_table, + constructor_table, method_table, attributes_table, comments_table, superclass_table, src_table, + cons_name_table, cons_comments_table, cons_params_table, method_name_table, method_name_comments_table, + method_name_params_table + idoc := UniAll() idoc.setSourcePath(path) @@ -132,8 +149,13 @@ class LSPDB( Logger.debug3_kind("db:path:package", "Processing ", pack.getName()) if /package_db[pack.getName()] then { - package_db[pack.getName()] := table() - package_db[pack.getName()]["files"] := table() + package_db[pack.getName()] := package_table := table() + package_table["files"] := file_table := table() + } + if /package_table then { + package_db[pack.getName()] := package_table := table() + package_table["files"] := file_table := table() + Logger.debug4_kind("db:path:package", "Initialize package table for package ", pack.getName()) } every file_in_pack := pack.getFiles().get() do { @@ -143,70 +165,73 @@ class LSPDB( file_without_ext := tab(upto(".")) } - package_db[pack.getName()]["files"][file_without_ext] := table() - if /package_db[pack.getName()]["files"][file_without_ext]["imports"] then package_db[pack.getName()]["files"][file_without_ext]["imports"] := [] + + file_table[file_without_ext] := table() + + /file_table[file_without_ext]["imports"] := [] + import_table := file_table[file_without_ext]["imports"] every import_in_file := file_in_pack.getImports().get() do { - put(package_db[pack.getName()]["files"][file_without_ext]["imports"], import_in_file.getName()) + put(import_table, import_in_file.getName()) } - if /package_db[pack.getName()]["files"][file_without_ext]["procedures"] then package_db[pack.getName()]["files"][file_without_ext]["procedures"] := table() + if /file_table[file_without_ext]["procedures"] then file_table[file_without_ext]["procedures"] := procedure_table := table() every procedure_in_file := file_in_pack.getProcedures().get() do { procedure_in_file.setSrcFile(idoc.getTargetDir() || file_in_pack.getName()) - package_db[pack.getName()]["files"][file_without_ext]["procedures"][procedure_in_file.getName()] := table() - package_db[pack.getName()]["files"][file_without_ext]["procedures"][procedure_in_file.getName()]["comments"] := makeComment(procedure_in_file) + procedure_table[procedure_in_file.getName()] := procedure_in_file_table := table() + procedure_in_file_table["comments"] := makeComment(procedure_in_file) - package_db[pack.getName()]["files"][file_without_ext]["procedures"][procedure_in_file.getName()]["params"] := [] + procedure_in_file_table["params"] := param_table := [] every param_in_procedure := procedure_in_file.getParams().get() do { paramName := param_in_procedure.getName() paramType := param_in_procedure.getTypeValue() | &null paramDef := param_in_procedure.getDefValue() | &null - put(package_db[pack.getName()]["files"][file_without_ext]["procedures"][procedure_in_file.getName()]["params"], table( + put(param_table, table( "name", paramName, "type", paramType, "default", paramDef)) } - package_db[pack.getName()]["files"][file_without_ext]["procedures"][procedure_in_file.getName()]["source"] := procedure_in_file.getSrcFile() + procedure_in_file_table["source"] := procedure_in_file.getSrcFile() } - if /package_db[pack.getName()]["files"][file_without_ext]["classes"] then package_db[pack.getName()]["files"][file_without_ext]["classes"] := table() + if /file_table[file_without_ext]["classes"] then file_table[file_without_ext]["classes"] := classes_table := table() every class_in_file := file_in_pack.getClasses().get() do { class_in_file.setSrcFile(idoc.getTargetDir() || file_in_pack.getName()) - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()] := table() - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["methods"] := table() - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["attributes"] := [] - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["comments"] := [] - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["superclass"] := [] - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["source"] := class_in_file.getSrcFile() - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["constructor"] := table() - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["constructor"]["name"] := class_in_file.getConstructor().getName() - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["constructor"]["comments"] := makeComment(class_in_file) - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["constructor"]["params"] := [] + file_table[file_without_ext]["classes"][class_in_file.getName()] := class_in_file_table := table() + class_in_file_table["methods"] := method_table := table() + class_in_file_table["attributes"] := attributes_table := [] + class_in_file_table["comments"] := comments_table := [] + class_in_file_table["superclass"] := superclass_table := [] + class_in_file_table["source"] := src_table := class_in_file.getSrcFile() + class_in_file_table["constructor"] := constructor_table := table() + constructor_table["name"] := cons_name_table := class_in_file.getConstructor().getName() + constructor_table["comments"] := cons_comments_table := makeComment(class_in_file) + constructor_table["params"] := cons_params_table := [] every method_in_class := class_in_file.getMethods().get() do { method_in_class.setSrcFile(idoc.getTargetDir() || file_in_pack.getName()) - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["methods"][method_in_class.getName()] := table() - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["methods"][method_in_class.getName()]["comments"] := makeComment(method_in_class) + method_table[method_in_class.getName()] := method_name_table := table() + method_name_table["comments"] := method_name_comments_table := makeComment(method_in_class) - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["methods"][method_in_class.getName()]["params"] := [] + method_name_table["params"] := method_name_params_table := [] every param_in_method := method_in_class.getParams().get() do { paramName := param_in_method.getName() paramType := param_in_method.getTypeValue() | &null paramDef := param_in_method.getDefValue() | &null - put(package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["methods"][method_in_class.getName()]["params"], table( + put(method_name_params_table, table( "name", paramName, "type", paramType, "default", paramDef)) } - package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["methods"][method_in_class.getName()]["source"] := method_in_class.getSrcFile() + method_name_table["source"] := method_in_class.getSrcFile() } every class_param := class_in_file.getParams().get() do { paramName := class_param.getName() paramType := class_param.getTypeValue() | &null paramDef := class_param.getDefValue() | &null - put(package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["attributes"], table( + put(attributes_table, table( "name", paramName, "type", paramType, "default", paramDef)) @@ -216,21 +241,21 @@ class LSPDB( paramName := constructor_param.getName() paramType := constructor_param.getTypeValue() | &null paramDef := constructor_param.getDefValue() | &null - put(package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["constructor"]["params"], table( + put(cons_params_table, table( "name", paramName, "type", paramType, "default", paramDef)) } every class_comment := class_in_file.getComments().get() do { - put(package_db[pack.getName()]["files"][file_without_ext]["classes"][class_in_file.getName()]["comments"], class_comment.get()) + put(comments_table, class_comment.get()) } } } } end - initially - unicon_dir := ulibprefix() + initially + unicon_dir := map(ulibprefix(), "\\", "/") end diff --git a/uni/ulsp/definition.icn b/uni/ulsp/definition.icn index c3857e0f5..beffabe39 100644 --- a/uni/ulsp/definition.icn +++ b/uni/ulsp/definition.icn @@ -5,12 +5,12 @@ link regexp link ximage class DefinitionHandler( - workspace, + filehandler, params ) - method setVariables(new_workspace, new_params) - workspace := new_workspace + method setVariables(new_filehandler, new_params) + filehandler := new_filehandler params := new_params end @@ -26,10 +26,10 @@ class DefinitionHandler( line := params["position"]["line"] + 1 character := params["position"]["character"] + 1 - context := workspace.getContext(line, character) + context := filehandler.getContext(line, character) signatureHandler := SignatureHandler() - signatureHandler.setVariables(workspace) + signatureHandler.setVariables(filehandler) signatureHandler.handleNewSignature(context) possibleItems := signatureHandler.getCurrentSigItems() diff --git a/uni/ulsp/workspace.icn b/uni/ulsp/file_handler.icn similarity index 98% rename from uni/ulsp/workspace.icn rename to uni/ulsp/file_handler.icn index b83243d80..89bc8b99f 100644 --- a/uni/ulsp/workspace.icn +++ b/uni/ulsp/file_handler.icn @@ -1,9 +1,9 @@ # ------------------------------------------------------------------------- -# ---------------------- Workspace Class ---------------------------------- +# ---------------------- FileHandler Class ---------------------------------- # ------------------------------------------------------------------------- # # Description: -# -Contains all items related to a particular opened workspace file. +# -Contains all items related to a particular opened filehandler file. # -This includes: # -The uri of the file # -The contents of the file (synchronized contents coming from client - updating in textDocument/didChange) @@ -29,7 +29,7 @@ import parser global identifiers -class Workspace( +class FileHandler( uri, lsp_database, temp_file, @@ -53,7 +53,7 @@ class Workspace( context ) - method updateWorkspace() + method updateFileHandler() setLinks() setImports() setPackage() @@ -295,7 +295,7 @@ class Workspace( "type", paramType, "default", paramDef)) } - + internal_classes[_class.getName()]["methods"][_method.getName()]["source"] := uri } @@ -599,7 +599,7 @@ class Workspace( identifiers := &letters ++ &digits ++ '_' ++ '-' end -class Context(uniAll, uri, line, lineNum, charNum, objectName, methodName, contextCase, packageName) +class Context(uniAll, uri, line, lineNum, charNum, objectName, methodName, contextCase, packageName, totalFileLines) method getDesiredLine(lineNum) line := uniAll.getUniFileLine(uri, lineNum) end @@ -767,12 +767,19 @@ class Context(uniAll, uri, line, lineNum, charNum, objectName, methodName, conte end initially(uniAll, uri, lineNum, charNum) + local f self.uniAll := uniAll self.uri := uri self.lineNum := lineNum self.charNum := charNum line := getDesiredLine(lineNum) contextCase := findContext() + totalFileLines := 0 + f := open(uri) | fail + reads(f, stat(uri).size) ? + every upto('\n') do + totalFileLines +:= 1 + f := close(f) end # Creates a working comments diff --git a/uni/ulsp/hover.icn b/uni/ulsp/hover.icn index 0dbf1172b..d6c0a46b9 100644 --- a/uni/ulsp/hover.icn +++ b/uni/ulsp/hover.icn @@ -4,32 +4,34 @@ import json link regexp link ximage +global begins, ends + class HoverHandler( - workspace, + filehandler, params ) - method setVariables(new_workspace, new_params) - workspace := new_workspace + method setVariables(new_filehandler, new_params) + filehandler := new_filehandler params := new_params end - method run() + method run(lsif) local line, character, desired_line, hover_item, signatureHandler, sig_table, results_table, _context, context - + if /filehandler then return results_table := table() line := params["position"]["line"] + 1 character := params["position"]["character"] + 1 - context := workspace.getContext(line, character) + context := filehandler.getContext(line, character) desired_line := context.line character := context.charNum if /desired_line | /character then return signatureHandler := SignatureHandler() - signatureHandler.setVariables(workspace) + signatureHandler.setVariables(filehandler) hover_item := \getHoverItem(desired_line, character) | return results_table _context := \getContext(context) | return results_table @@ -48,12 +50,27 @@ class HoverHandler( results_table["contents"] := table("kind", "markdown", "value", "(_" || _context || "_) " || hover_item ) } + if \lsif then { + if \sig_table & member(sig_table[1], "documentation") then { + return table( + "item", "(_" || _context || "_) " || hover_item || "\n \n --- \n \n" || sig_table[1]["documentation"]["value"], + "begins", begins, + "ends", ends, + "line", line) + } else { + return table( + "item", "(_" || _context || "_) " || hover_item, + "begins", begins, + "ends", ends, + "line", line) + } + } return results_table end method getContext(context) local line_num, procedure_name, method_name, class_name, single_quote, double_quote, ch, _item, c, desired_line, - num_params, param, num_attributes, _attribute, line, character + num_params, param, num_attributes, _attribute, line, character, begin, ends line := context.line \line | fail @@ -62,15 +79,16 @@ class HoverHandler( # Begin initial string scanning line ? { - # Check if position is within a comment + # Check if position is within a comment or quoted text single_quote := 0 double_quote := 0 while (&pos < character) do { ch := move(1) | break - if ch == "\'" then single_quote +:= 1 - if ch == "\"" then double_quote +:= 1 - if (ch == "#") & ((single_quote % 2) = 0 & (double_quote % 2) = 0) then fail + if (ch == "\'" & (line[&pos-2] ~== "\\")) then single_quote +:= 1 + if (ch == "\"" & (line[&pos-2] ~== "\\")) then double_quote +:= 1 + if (ch == "#") & ((single_quote % 2) == 0 & (double_quote % 2) == 0) then fail } + if (single_quote % 2) ~== 0 | (double_quote % 2) ~== 0 then fail # If item is a function then find the type &pos := character @@ -91,14 +109,14 @@ class HoverHandler( # If item is method of the class it's inside of then return method line_num := params["position"]["line"] + 1 - context := workspace.getContext(line_num, character) + context := filehandler.getContext(line_num, character) desired_line := context.line character := context.charNum until ReMatch("^[\ \t]*class[\ \t]+", desired_line) | ReMatch("^[\ \t]*procedure[\ \t]+", desired_line) | line_num = 0 do { - context := workspace.getContext(line_num, character) + context := filehandler.getContext(line_num, character) desired_line := context.line character := context.charNum @@ -110,24 +128,24 @@ class HoverHandler( class_name := tab(many(identifiers)) } - if member(workspace.internal_classes[class_name]["methods"], _item) then + if member(filehandler.internal_classes[class_name]["methods"], _item) then return "method" } line_num -:= 1 } # If item is an associated class then return constructor - if member(workspace.linked_classes, _item) | member(workspace.imported_classes, _item) | - member(workspace.internal_classes, _item) | member(workspace.package_classes, _item) then + if member(filehandler.linked_classes, _item) | member(filehandler.imported_classes, _item) | + member(filehandler.internal_classes, _item) | member(filehandler.package_classes, _item) then return "constructor" # If item is an associated procedure then return procedure - if member(workspace.linked_procedures, _item) | member(workspace.imported_procedures, _item) | - member(workspace.internal_procedures, _item) | member(workspace.package_procedures, _item) then + if member(filehandler.linked_procedures, _item) | member(filehandler.imported_procedures, _item) | + member(filehandler.internal_procedures, _item) | member(filehandler.package_procedures, _item) then return "procedure" # If item is a built-in-function then return built-in-function - if member(workspace.getBuiltInFunctions(), _item) then + if member(filehandler.getBuiltInFunctions(), _item) then return "built-in-function" # If all else fails @@ -139,7 +157,7 @@ class HoverHandler( # Process for determining if item is parameter until line_num = 1 do { - context := workspace.getContext(line_num, character) + context := filehandler.getContext(line_num, character) desired_line := context.line character := context.charNum @@ -152,9 +170,9 @@ class HoverHandler( procedure_name := tab(many(identifiers)) } - if member(workspace.internal_procedures, procedure_name) then { - num_params := *workspace.internal_procedures[procedure_name]["params"] - every param := workspace.internal_procedures[procedure_name]["params"][1 to num_params] do { + if member(filehandler.internal_procedures, procedure_name) then { + num_params := *filehandler.internal_procedures[procedure_name]["params"] + every param := filehandler.internal_procedures[procedure_name]["params"][1 to num_params] do { if param["name"] == getHoverItem(line, character) then return "parameter" } } @@ -172,7 +190,7 @@ class HoverHandler( line_num -:= 1 until line_num = 1 do { - context := workspace.getContext(line_num, character) + context := filehandler.getContext(line_num, character) desired_line := context.line character := context.charNum @@ -188,17 +206,17 @@ class HoverHandler( line_num -:= 1 } - if member(workspace.internal_classes, class_name) & member(workspace.internal_classes[class_name]["methods"], method_name) then { - num_params := *workspace.internal_classes[class_name]["methods"][method_name]["params"] - every param := workspace.internal_classes[class_name]["methods"][method_name]["params"][1 to num_params] do { + if member(filehandler.internal_classes, class_name) & member(filehandler.internal_classes[class_name]["methods"], method_name) then { + num_params := *filehandler.internal_classes[class_name]["methods"][method_name]["params"] + every param := filehandler.internal_classes[class_name]["methods"][method_name]["params"][1 to num_params] do { if param["name"] == getHoverItem(line, character) then return "parameter" } } # If item is an attribute (class parameter) then return class parameter - if member(workspace.internal_classes, class_name) then { - num_attributes := *workspace.internal_classes[class_name]["attributes"] - every _attribute := workspace.internal_classes[class_name]["attributes"][1 to num_attributes] do { + if member(filehandler.internal_classes, class_name) then { + num_attributes := *filehandler.internal_classes[class_name]["attributes"] + every _attribute := filehandler.internal_classes[class_name]["attributes"][1 to num_attributes] do { if _attribute["name"] == getHoverItem(line, character) then return "class parameter" } } @@ -213,9 +231,9 @@ class HoverHandler( class_name := tab(many(identifiers)) } - if member(workspace.internal_classes, class_name) then { - num_attributes := *workspace.internal_classes[class_name]["attributes"] - every _attribute := workspace.internal_classes[class_name]["attributes"][1 to num_attributes] do { + if member(filehandler.internal_classes, class_name) then { + num_attributes := *filehandler.internal_classes[class_name]["attributes"] + every _attribute := filehandler.internal_classes[class_name]["attributes"][1 to num_attributes] do { if _attribute["name"] == getHoverItem(line, character) then return "class parameter" } } @@ -226,15 +244,15 @@ class HoverHandler( line_num := params["position"]["line"] + 1 # If item is a member of global variables then return global - if member(workspace.global_variables, getHoverItem(line, character)) then return "global" + if member(filehandler.global_variables, getHoverItem(line, character)) then return "global" # If item is an associated variable or object then return variable or object respectively - if member(workspace.objects, getHoverItem(line, character)) then return "object" - if member(workspace.variables, getHoverItem(line, character)) then return "variable" + if member(filehandler.objects, getHoverItem(line, character)) then return "object" + if member(filehandler.variables, getHoverItem(line, character)) then return "variable" end method getHoverItem(line, character) - local c + local c, b if (line[character] ** identifiers) ~== line[character] then fail line ? { @@ -245,8 +263,10 @@ class HoverHandler( } if &pos ~= 1 then move(1) - - return tab(many(identifiers)) + begins := &pos + b := tab(many(identifiers)) + ends := &pos + return b } end end \ No newline at end of file diff --git a/uni/ulsp/launch-lsp.icn b/uni/ulsp/launch-lsp.icn index 0b89a0334..30d5c09a2 100644 --- a/uni/ulsp/launch-lsp.icn +++ b/uni/ulsp/launch-lsp.icn @@ -28,15 +28,16 @@ procedure usage() write("\t --logfile : log file") write("\t --loglevel : log level from 0-17. log levels 8-17 are used for debugging") write("\t --debug-kind : debug kind to log") + write("\t --build-lsif : directory to parse for LSIF information or \"all\" for all directories") write("\t -h : show this help\n") exit(-1) end procedure validate_args(args) local opts - opts := options(args, "--socket+ --logfile: --loglevel+ --debug-kind: -h! -c! -s!", usage) + opts := options(args, "--socket+ --logfile: --loglevel+ --debug-kind: -h! -c! -s! --build-lsif:", usage) if *opts = 0 then usage() - member(opts, "-socket") | usage() + member(opts, "-socket") | member(opts, "-build-lsif") | usage() return opts end @@ -50,7 +51,7 @@ procedure ulsp_sig_handler(siganl) end procedure main(args) - local opts, sock, mode + local opts, sock, mode, lsp_database, indexer trap("SIGINT", ulsp_sig_handler) @@ -62,6 +63,17 @@ procedure main(args) if \opts["-debug-kind"] then Logger.add_debug_kind(opts["-debug-kind"]) + if member(opts, "-build-lsif") then { + lsp_database := LSPDB() + if (opts["-build-lsif"] == "all") then { + lsp_database.build(); + } else { + lsp_database.build(opts["-build-lsif"]) + } + indexer := LSIFIndexer(lsp_database) + indexer.build_index() + exit(0) + } # Allow passing full host:port as an arg sock := opts["-socket"] if &features == ("MacOS" | "MS Windows NT") then { diff --git a/uni/ulsp/lsif.icn b/uni/ulsp/lsif.icn new file mode 100644 index 000000000..95f0ef80b --- /dev/null +++ b/uni/ulsp/lsif.icn @@ -0,0 +1,402 @@ +import UniDoc +import ulsp +import json +link ximage + +# Generates LSIF information by going through the packages in the database and create LSIF vertices and edges +# from each project, file, hover info, etc. +class LSIFIndexer( + db, # The provided database to index + outFile # The file to output to + ) + + # The main method of the LSIFIndexer class; this method will take the assigned database (db) and + # use it to build an index file of all relevant information in each of the files and output it + # to a directed file in LSIF JSON format. + # This function works by looping through each directory in the provided database, then looping + # through each package and each file in the package. For each file it will loop through every + # line and every character of every line, creating parameters to pass through to hoverHandler + # and definitionHandler objects. Depending on the response from the hoverHandler, it will create + # a range vertex. It then checks the definitionHandler. If the requested position is a definition + # it creates a definition vertex. If it's defined elsewhere, it will save it in a table to check + # later. At the end it will go through all the references and match them up with definitions. + method build_index() + local i, j, k, idoc, path, x, pack, file_in_pack, uri, filehandler_object, fake_params, result, hoverHandler, + context, char_end, line_end, definitionHandler, result2, resultSet_table, resultSet, reference, + reference_table, projectID, referenceID, resultSetID, rangeID, documentID, document_list, range_list, + c, b := 0 + hoverHandler := HoverHandler() + definitionHandler := DefinitionHandler() + resultSet_table := table() + reference_table := table() + fake_params := table() + fake_params["position"] := table() + createMetaDataVertex(db.unicon_dir) + every i := 1 to *db.dir_list do { + path := db.dir_list[i] + + idoc := UniAll() + + idoc.setSourcePath(path) + idoc.setTargetDir(path) + idoc.processFile(path) + x := idoc.packages + path := replace(path, "C:", "c:") + path ? { + &pos := 0 + while c := move(-1) do { + if c == "/" | c == "\\" then b +:= 1 + if b == 2 then break + } + projectID := createProjectVertex(path, path[&pos + 1:0]) + } + createEventVertex("project", "begin", projectID) + document_list := [] + every pack := !x do { + every file_in_pack := pack.getFiles().get() do { + fake_params["position"]["line"] := 0 + fake_params["position"]["character"] := 0 + range_list := [] + uri := path || "/" || file_in_pack.getName() + + Logger.info("[LSIF] Processing: " || uri) + documentID := createDocumentVertex(uri) + put(document_list, documentID) + createEventVertex("document", "begin", documentID) + filehandler_object := FileHandler(uri, db) + filehandler_object.setFile() + filehandler_object.updateFileHandler() + context := filehandler_object.getContext(1, 1) + line_end := context.totalFileLines + k := 0 + every j := 0 to line_end-1 do { + fake_params["position"]["line"] := j + context := filehandler_object.getContext(j+1, 1) + char_end := *context.line + while k < char_end do { + fake_params["position"]["character"] := k + hoverHandler.setVariables(filehandler_object, fake_params) + definitionHandler.setVariables(filehandler_object, fake_params) + result := hoverHandler.run("lsif") + if \result & *result ~= 0 then { + rangeID := createRangeVertex(result["line"], result["begins"], result["ends"]) + put(range_list, rangeID) + result2 := definitionHandler.run() + if \result2 & *result2 ~= 0 & result2["uri"] == uri then { + if (result2["range"]["start"]["line"] <= j <= result2["range"]["end"]["line"] && + result2["range"]["start"]["character"] <= k <= result2["range"]["end"]["character"]) then { + resultSetID := createResultSetVertex() + createHoverResultVertex(result["item"], resultSetID) + createNextEdge(rangeID, resultSetID) + createDefinitionResultVertex(resultSetID, rangeID, documentID) + referenceID := createReferenceResultVertex(resultSetID, "definitions", rangeID, documentID) + result2["resultSetID"] := resultSetID + result2["docID"] := documentID + result2["referenceID"] := referenceID + resultSet_table[resultSetID] := result2 + } else { + result2["rangeID"] := rangeID + result2["result"] := result + result2["docID"] := documentID + reference_table[rangeID] := result2 + } + } else if \result2 & *result2 ~= 0 & result2["uri"] ~== uri then { + result2["rangeID"] := rangeID + result2["result"] := result + result2["docID"] := documentID + reference_table[rangeID] := result2 + } else { + createHoverResultVertex(result["item"], rangeID) + } + k := result["ends"] + } + k +:= 1 + } + k := 0 + } + if \range_list then { + createContainsEdge(documentID, range_list) + } + } + } + if \resultSet_table then { + every resultSet := !resultSet_table do { + every reference := !reference_table do { + if (resultSet["uri"] == reference["uri"] && + resultSet["range"]["start"]["line"] == reference["range"]["start"]["line"] && + resultSet["range"]["end"]["line"] == reference["range"]["end"]["line"] && + resultSet["range"]["start"]["character"] == reference["range"]["start"]["character"] && + resultSet["range"]["end"]["character"] == reference["range"]["end"]["character"]) then { + createHoverResultVertex(reference["result"]["item"], reference["rangeID"]) + createItemEdge(resultSet["referenceID"], reference["rangeID"], reference["docID"], "references") + delete(reference_table, reference["rangeID"]) + delete(resultSet_table, resultSet["resultSetID"]) + } + } + } + } + if \document_list then { + every documentID := !document_list do { + createEventVertex("document", "end", documentID) + } + createContainsEdge(projectID, document_list) + } + createEventVertex("project", "end", projectID) + } + close(outFile) + end + + # Iterates nextID up one. + # This is intended for internal use only! + method getNextID() + static nextID := 0 + return nextID +:= 1 + end + + # Creates a metaData vertex with the given information and outputs it to the output file. + # Params: path - The path of the main Unicon directory. + # This is intended for internal use only! + method createMetaDataVertex(path) + local lsif_table + + lsif_table := [ + "id" : getNextID(); + "type" : "vertex"; + "label" : "metaData"; + "version" : "0.6.0"; + "projectRoot" : "file:///" || replace(path, "C:", "c:"); + "positionEncoding" : "utf-16" + ] + write(outFile, tojson(lsif_table)) + end + + # Creates a Project vertex with the given information and outputs it to the output file. + # Params: path - The path of the project. + # dir_name - The name of the directory for the project. + # This is intended for internal use only! + method createProjectVertex(path, dir_name) + local lsif_table, proID := getNextID() + lsif_table := [ + "id" : proID; + "type" : "vertex"; + "label" : "project"; + "resource" : "file:///" || path; + "kind" : "unicon"; + "name" : dir_name + ] + write(outFile, tojson(lsif_table)) + return proID + end + + # Creates an Event vertex with the given information and outputs it to the output file. + # Params: scope - The scope of this event, i.e. project or document. + # kind - Whether this event is a begin or an end event. + # scopeID - The ID for the project or document that the scope belongs to. + # This is intended for internal use only! + method createEventVertex(scope, kind, scopeID) + local lsif_table + + lsif_table := [ + "id" : getNextID(); + "type" : "vertex"; + "label" : "$event"; + "kind" : kind; + "scope" : scope; + "data" : scopeID + ] + write(outFile, tojson(lsif_table)) + end + + # Creates a Document vertex and the associated contains edge that links it to + # the project that it is a part of. + # Params: uri - The uri of the file of the document vertex. + # This is intended for internal use only! + method createDocumentVertex(uri) + local lsif_table, docID := getNextID() + + lsif_table := [ + "id" : docID; + "type" : "vertex"; + "label" : "document"; + "uri" : "file:///" || uri; + "languageId" : "unicon" + ] + write(outFile, tojson(lsif_table)) + return docID + end + + # Creates a resultSet vertex that will link relevant information together. + # This is intended for internal use only! + method createResultSetVertex() + local lsif_table, resID := getNextID() + + lsif_table := [ + "id" : resID; + "type" : "vertex"; + "label" : "resultSet" + ] + write(outFile, tojson(lsif_table)) + return resID + end + + # Creates a range vertex with the relevant data. + # Params: lineNum - The line number that the token is located on. + # startCharNum - The starting character position. + # endCharNum - The ending character position. + # This is intended for internal use only! + method createRangeVertex(lineNum, startCharNum, endCharNum) + local lsif_table, ranID := getNextID() + + lsif_table := [ + "id" : ranID; + "type" : "vertex"; + "label" : "range"; + "start" : table("line", lineNum, "character", startCharNum); + "end" : table("line", lineNum, "character", endCharNum) + ] + write(outFile, tojson(lsif_table)) + return ranID + end + + # Creates a hoverResult vertex, along with a range vertex and a textdocument/hover edge. + # Params: value - The value of the token that is being hovered over. + # outID - For regular hover results, it will be the rangeID. For hover results linked to a resultSet, + # it will be the resultSetID. + # This is intended for internal use only! + method createHoverResultVertex(value, outID) + local lsif_table, hoverID := getNextID() + + lsif_table := [ + "id" : hoverID; + "type" : "vertex"; + "label" : "hoverResult"; + "result" : table("contents", [table("language", "unicon", "value", value)]) + ] + write(outFile, tojson(lsif_table)) + lsif_table := [ + "id" : getNextID(); + "type" : "edge"; + "label" : "textDocument/hover"; + "inV" : hoverID; + "outV" : outID + ] + write(outFile, tojson(lsif_table)) + end + + # Creates a next edge that links a given range vertex to a resultSet vertex. + # Params: rangeID - The range of the token that is being hovered over. + # resultSetID - The result set belonging to that range. + # This is intended for internal use only! + method createNextEdge(rangeID, resultSetID) + local lsif_table + + lsif_table := [ + "id" : getNextID(); + "type" : "edge"; + "label" : "next"; + "outV" : rangeID; + "inV" : resultSetID + ] + write(outFile, tojson(lsif_table)) + end + + # Creates a definitionResult vertex and a textDocument/definition edge that links a given range + # vertex to a resultSet vertex. + # Params: resultSetID - The result set of the token that is being hovered over. + # rangeID - The range of the token that is being hovered over. + # documentID - The ID of the associated document. + # This is intended for internal use only! + method createDefinitionResultVertex(resultSetID, rangeID, documentID) + local lsif_table, definitionID := getNextID() + + lsif_table := [ + "id" : definitionID; + "type" : "vertex"; + "label" : "definitionResult" + ] + write(outFile, tojson(lsif_table)) + lsif_table := [ + "id" : getNextID(); + "type" : "edge"; + "label" : "textDocument/definition"; + "outV" : resultSetID; + "inV": definitionID + ] + write(outFile, tojson(lsif_table)) + createItemEdge(definitionID, rangeID, documentID) + end + + # Creates a referenceResult vertex and a textDocument/references edge that links a given range + # vertex to a resultSet vertex. + # Params: outID - The result set that this reference belongs to. + # property - Either "definitions" or "references". + # rangeID - The range of the token that is being hovered over. + # documentID - The ID of the associated document. + # This is intended for internal use only! + method createReferenceResultVertex(outID, property, rangeID, documentID) + local lsif_table, refID := getNextID() + + lsif_table := [ + "id" : refID; + "type" : "vertex"; + "label" : "referenceResult" + ] + write(outFile, tojson(lsif_table)) + lsif_table := [ + "id" : getNextID(); + "type" : "edge"; + "label" : "textDocument/references"; + "outV" : outID; + "inV" : refID + ] + write(outFile, tojson(lsif_table)) + createItemEdge(refID, rangeID, documentID, property) + return refID + end + + # Creates an item edge that links a given range vertex to a definitionResult. + # Params: outID - The ID for the definitionResult or referenceResult associated with this edge. + # ItemRangeID - The ID of the range that this Item edge belongs to + # docID - The ID for the document that this Item edge belongs to + # property - Whether this edge belongs to definitions or references + # This is intended for internal use only! + method createItemEdge(outID, ItemRangeID, docID, property) + local lsif_table, ranges + + ranges := [] + put(ranges, ItemRangeID) + lsif_table := [ + "id" : getNextID(); + "type" : "edge"; + "label" : "item"; + "outV" : outID; + "inVs" : ranges; + "shard" : docID + ] + if \property then lsif_table["property"] := property + write(outFile, tojson(lsif_table)) + end + + # Creates an contains edge that links all of the ranges in a document to that document. + # or all the documents to a project. + # Params: outID - The ID that this edge is pointing out from, either the document or project ID. + # contains_table - The table with ID's of all ranges in a document or documents in a project. + # This is intended for internal use only! + method createContainsEdge(outID, contains_table) + local lsif_table + + lsif_table := [ + "id" : getNextID(); + "type" : "edge"; + "label" : "contains"; + "outV" : outID; + "inVs" : contains_table + ] + write(outFile, tojson(lsif_table)) + end + + # Initially set this class' database and create/open the unicon.lsif file to be written to. + initially(db) + self.db := db + self.outFile := open(db.unicon_dir || "uni/ulsp/unicon.lsif", "w") +end diff --git a/uni/ulsp/server.icn b/uni/ulsp/server.icn index 23399a665..5eda2da21 100644 --- a/uni/ulsp/server.icn +++ b/uni/ulsp/server.icn @@ -80,7 +80,7 @@ class Server( method run() local msg jrpc_handler := JRPC_HTTPSocket(sock) - repeat + repeat if msg := jrpc_handler.get_msg() then { #Logger.info("msg= ", image(msg.get_content())) case msg.get_kind() of { @@ -138,7 +138,7 @@ class Server( ######################################################## method didOpen(request_params) - local fname, uri, f, initial_file_contents, workspace_object + local fname, uri, f, initial_file_contents, filehandler_object if \(uri := request_params["textDocument"]["uri"]) then { # uri: file:// uri ? { @@ -151,11 +151,14 @@ class Server( close(f) } } - - openFiles[\uri] := Workspace(fname, lsp_database) - workspace_object := openFiles[\uri] - workspace_object.setFile() - workspace_object.updateWorkspace() + # Get rid of root / and change unicode encoded "%3A" back to ":" on Windows machines + if &features == ("MS Windows NT") then { + fname := fname[2] || ":" || fname[6:0] + } + openFiles[\uri] := FileHandler(fname, lsp_database) + filehandler_object := openFiles[\uri] + filehandler_object.setFile() + filehandler_object.updateFileHandler() end @@ -174,7 +177,7 @@ class Server( ######################################################## method didChange(request_params) - local fname, uri, f, file_contents, workspace_object, initial_file_contents + local fname, uri, f, file_contents, filehandler_object, initial_file_contents if \(uri := request_params["textDocument"]["uri"]) then { # uri: file:// uri ? { @@ -190,9 +193,9 @@ class Server( uri := request_params["textDocument"]["uri"] file_contents := request_params["contentChanges"][1]["text"] - workspace_object := openFiles[\uri] - workspace_object.updateUniDoc(fname, file_contents) - workspace_object.updateWorkspace() + filehandler_object := openFiles[\uri] + filehandler_object.updateUniDoc(fname, file_contents) + filehandler_object.updateFileHandler() end ######################################################## @@ -200,9 +203,9 @@ class Server( ######################################################## method completion(msg) - local workspace_object, result - workspace_object := openFiles[\msg.get_param_uri()] - completionHandler.setVariables(workspace_object, msg.get_params()) + local filehandler_object, result + filehandler_object := openFiles[\msg.get_param_uri()] + completionHandler.setVariables(filehandler_object, msg.get_params()) result := completionHandler.run() msg.make_result_response(result) jrpc_handler.send_msg(msg) @@ -213,9 +216,9 @@ class Server( ######################################################## method signatureHelp(msg) - local workspace_object, result - workspace_object := openFiles[\msg.get_param_uri()] - signatureHandler.setVariables(workspace_object, msg.get_params()) + local filehandler_object, result + filehandler_object := openFiles[\msg.get_param_uri()] + signatureHandler.setVariables(filehandler_object, msg.get_params()) result := signatureHandler.run() msg.make_result_response(result) jrpc_handler.send_msg(msg) @@ -226,9 +229,9 @@ class Server( ######################################################## method hoverHelp(msg) - local workspace_object, result - workspace_object := openFiles[\msg.get_param_uri()] - hoverHandler.setVariables(workspace_object, msg.get_params()) + local filehandler_object, result + filehandler_object := openFiles[\msg.get_param_uri()] + hoverHandler.setVariables(filehandler_object, msg.get_params()) result := hoverHandler.run() msg.make_result_response(result) jrpc_handler.send_msg(msg) @@ -239,10 +242,11 @@ class Server( ######################################################## method definitionHelp(msg) - local workspace_object, result - workspace_object := openFiles[\msg.get_param_uri()] - definitionHandler.setVariables(workspace_object, msg.get_params()) + local filehandler_object, result + filehandler_object := openFiles[\msg.get_param_uri()] + definitionHandler.setVariables(filehandler_object, msg.get_params()) result := definitionHandler.run() + \result["uri"] := replace(result["uri"], "c:/", "/c%3A/") msg.make_result_response(result) jrpc_handler.send_msg(msg) end diff --git a/uni/ulsp/signature.icn b/uni/ulsp/signature.icn index 06a3dbbe5..3dc565eef 100644 --- a/uni/ulsp/signature.icn +++ b/uni/ulsp/signature.icn @@ -4,13 +4,13 @@ import json global triggerCharLoc class SignatureHandler( - workspace, + filehandler, params, currentSigItems ) - method setVariables(new_workspace, new_params) - workspace := new_workspace + method setVariables(new_filehandler, new_params) + filehandler := new_filehandler params := new_params end @@ -27,7 +27,7 @@ class SignatureHandler( results_table["activeSignature"] := &null # Collect context information (inside comment, space before, object before, no object before) # - context := workspace.getContext(line, character) + context := filehandler.getContext(line, character) desired_line := context.line \desired_line | return results_table \params["context"] | return results_table @@ -77,10 +77,10 @@ class SignatureHandler( /triggerCharLoc := charNum - linked_classes := workspace.getLinkedClasses() - imported_classes := workspace.getImportedClasses() - internal_classes := workspace.getInternalClasses() - package_classes := workspace.getPackageClasses() + linked_classes := filehandler.getLinkedClasses() + imported_classes := filehandler.getImportedClasses() + internal_classes := filehandler.getInternalClasses() + package_classes := filehandler.getPackageClasses() case _context of { @@ -90,7 +90,7 @@ class SignatureHandler( objectName := context.objectName methodName := context.methodName - objects := workspace.getObjects() + objects := filehandler.getObjects() className := objects[objectName] # Check if function is a method of a linked class # @@ -131,11 +131,11 @@ class SignatureHandler( methodName := context.methodName - built_in_functions := workspace.getBuiltInFunctions() - linked_procedures := workspace.getLinkedProcedures() - imported_procedures := workspace.getImportedProcedures() - internal_procedures := workspace.getInternalProcedures() - package_procedures := workspace.getPackageProcedures() + built_in_functions := filehandler.getBuiltInFunctions() + linked_procedures := filehandler.getLinkedProcedures() + imported_procedures := filehandler.getImportedProcedures() + internal_procedures := filehandler.getInternalProcedures() + package_procedures := filehandler.getPackageProcedures() # Check if function is an internal procedure # if member(internal_procedures, methodName) then { @@ -263,7 +263,7 @@ class SignatureHandler( move(-1) } - temp_context := workspace.getContext(params["position"]["line"] + 1, &pos) + temp_context := filehandler.getContext(params["position"]["line"] + 1, &pos) new_signatures |||:= handleNewSignature(temp_context, results_table) } }