From 4d60c4dad0f03b6120c87505cacc1d89d6750b06 Mon Sep 17 00:00:00 2001 From: CppCXY <812125110@qq.com> Date: Thu, 29 Jun 2023 17:45:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BAemmylua=E5=8F=AF=E7=94=A8?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tang/vscode/LuaLanguageServer.kt | 1 - .../com/tang/vscode/LuaTextDocumentService.kt | 1028 +++++------------ .../com/tang/vscode/LuaWorkspaceService.kt | 114 +- .../com/tang/vscode/api/impl/LuaFile.kt | 93 +- 4 files changed, 364 insertions(+), 872 deletions(-) diff --git a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaLanguageServer.kt b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaLanguageServer.kt index 5e05870..32213c5 100644 --- a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaLanguageServer.kt +++ b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaLanguageServer.kt @@ -101,7 +101,6 @@ class LuaLanguageServer : LanguageServer, LanguageClientAware { capabilities.workspace.workspaceFolders = WorkspaceFoldersOptions() capabilities.workspace.workspaceFolders.supported = true capabilities.workspace.workspaceFolders.changeNotifications = Either.forLeft(WORKSPACE_FOLDERS_CAPABILITY_ID) - capabilities.foldingRangeProvider = Either.forLeft(true) capabilities.textDocumentSync = Either.forLeft(TextDocumentSyncKind.Full) diff --git a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaTextDocumentService.kt b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaTextDocumentService.kt index e1f9241..6a74559 100644 --- a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaTextDocumentService.kt +++ b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaTextDocumentService.kt @@ -55,18 +55,22 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD @JsonRequest("emmy/annotator") fun updateAnnotators(ann: AnnotatorParams): CompletableFuture> { return computeAsync { - val file = workspace.findFile(ann.uri) as? ILuaFile - if (file != null) - findAnnotators(file) - else - emptyList() + workspace.ready { + val file = workspace.findFile(ann.uri) as? ILuaFile + if (file != null) + findAnnotators(file) + else + emptyList() + } } } @Suppress("unused") @JsonRequest("emmy/reportAPI") fun reportAPI(params: LuaReportApiParams): CompletableFuture { - ExtendApiService.loadApi(workspace.getProject(), params) + workspace.canWrite { + ExtendApiService.loadApi(workspace.getProject(), params) + } return CompletableFuture() } @@ -172,6 +176,7 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD is LuaLocalFuncDef -> { it.nameRange?.let { it1 -> notUse.add(it1) }; } + else -> { notUse.add(it.textRange) } @@ -198,13 +203,13 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD override fun resolveCompletionItem(item: CompletionItem): CompletableFuture { return computeAsync { - val data = item.data - if (data is JsonPrimitive) { - val arr = data.asString.split("|") - if (arr.size == 2) { - val file = workspace.findLuaFile(arr[0]) - if (file is ILuaFile) { - file.lock { + workspace.ready { + val data = item.data + if (data is JsonPrimitive) { + val arr = data.asString.split("|") + if (arr.size == 2) { + val file = workspace.findLuaFile(arr[0]) + if (file is ILuaFile) { val position = arr[1].toInt() file.psi?.findElementAt(position)?.let { psi -> PsiTreeUtil.getParentOfType(psi, LuaClassMember::class.java)?.let { member -> @@ -216,27 +221,27 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD } } } - } - } else if (arr.size == 3 && arr[0] == "extendApi") { - val doc = documentProvider.generateExtendDoc(arr[1], arr[2]) - if (doc != null) { - val content = MarkupContent() - content.kind = "markdown" - content.value = doc - item.documentation = Either.forRight(content) + } else if (arr.size == 3 && arr[0] == "extendApi") { + val doc = documentProvider.generateExtendDoc(arr[1], arr[2]) + if (doc != null) { + val content = MarkupContent() + content.kind = "markdown" + content.value = doc + item.documentation = Either.forRight(content) + } } } + item } - item } } override fun hover(params: HoverParams): CompletableFuture { - val file = workspace.findFile(params.textDocument.uri) return computeAsync { - var hover: Hover? = null - if (file is ILuaFile) { - file.lock { + workspace.ready { + val file = workspace.findFile(params.textDocument.uri) + var hover: Hover? = null + if (file is ILuaFile) { val pos = file.getPosition(params.position.line, params.position.character) val element = TargetElementUtil.findTarget(file.psi, pos) if (element != null) { @@ -246,90 +251,81 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD hover = Hover(listOf(Either.forLeft(doc))) } } - } - hover + hover + } } } override fun documentHighlight(params: DocumentHighlightParams): CompletableFuture?> { return computeAsync { - val list = mutableListOf() + workspace.ready { + val list = mutableListOf() - withPsiFile(params.textDocument, params.position) { file, psiFile, i -> - val target = TargetElementUtil.findTarget(psiFile, i) - if (target != null) { - val def = target.reference?.resolve() ?: target + withPsiFile(params.textDocument, params.position) { file, psiFile, i -> + val target = TargetElementUtil.findTarget(psiFile, i) + if (target != null) { + val def = target.reference?.resolve() ?: target - // self highlight - if (def.containingFile == psiFile) { - def.nameRange?.let { range -> list.add(DocumentHighlight(range.toRange(file))) } - } + // self highlight + if (def.containingFile == psiFile) { + def.nameRange?.let { range -> list.add(DocumentHighlight(range.toRange(file))) } + } - // references highlight - val search = ReferencesSearch.search(def, GlobalSearchScope.fileScope(psiFile)) - search.forEach { reference -> - list.add(DocumentHighlight(reference.getRangeInFile(file))) + // references highlight + val search = ReferencesSearch.search(def, GlobalSearchScope.fileScope(psiFile)) + search.forEach { reference -> + list.add(DocumentHighlight(reference.getRangeInFile(file))) + } } } - } - list + list + } } } -// override fun documentColor(params: DocumentColorParams): CompletableFuture> { -// return computeAsync { checker -> -// val file = workspace.findFile(params.textDocument.uri) -// val list = mutableListOf() -// if (file is ILuaFile) { -// file.lock { -// list.addAll(ColorService.renderColor(file, checker)) -// } -// } -// list -// } -// } - override fun definition(params: DefinitionParams?): CompletableFuture, MutableList>?> { return computeAsync { - val list = mutableListOf() - if (params != null) { - withPsiFile(params.textDocument, params.position) { _, psiFile, i -> - val target = TargetElementUtil.findTarget(psiFile, i) - val resolve = target?.reference?.resolve() - if (resolve != null) { - if (resolve is ExtendApiBase) { - val locationText = resolve.getLocation(); - val locationList = locationText.split('#') - if (locationList.size == 2) { - val line = locationList[1].toInt() - list.add(Location(locationList[0], Range(Position(line - 1, 0), Position(line, 0)))) - } + workspace.ready { + val list = mutableListOf() + if (params != null) { + withPsiFile(params.textDocument, params.position) { _, psiFile, i -> + val target = TargetElementUtil.findTarget(psiFile, i) + val resolve = target?.reference?.resolve() + if (resolve != null) { + if (resolve is ExtendApiBase) { + val locationText = resolve.getLocation(); + val locationList = locationText.split('#') + if (locationList.size == 2) { + val line = locationList[1].toInt() + list.add(Location(locationList[0], Range(Position(line - 1, 0), Position(line, 0)))) + } - return@withPsiFile + return@withPsiFile + } + val sourceFile = resolve.containingFile?.virtualFile as? LuaFile + val range = resolve.nameRange + if (range != null && sourceFile != null) + list.add(Location(sourceFile.uri.toString(), range.toRange(sourceFile))) + } else if (target != null) { + val luaFile = psiFile.virtualFile as LuaFile + list.add(Location(luaFile.uri.toString(), target.textRange.toRange(luaFile))) } - val sourceFile = resolve.containingFile?.virtualFile as? LuaFile - val range = resolve.nameRange - if (range != null && sourceFile != null) - list.add(Location(sourceFile.uri.toString(), range.toRange(sourceFile))) - } else if (target != null) { - val luaFile = psiFile.virtualFile as LuaFile - list.add(Location(luaFile.uri.toString(), target.textRange.toRange(luaFile))) } } + Either.forLeft(list) } - Either.forLeft(list) } } override fun codeLens(params: CodeLensParams): CompletableFuture> { - val file = workspace.findFile(params.textDocument.uri) return computeAsync { cc -> - val list = mutableListOf() - if (VSCodeSettings.showCodeLens) { - if (file is ILuaFile) { - file.lock { + workspace.ready { + val file = workspace.findFile(params.textDocument.uri) + val list = mutableListOf() + if (VSCodeSettings.showCodeLens) { + if (file is ILuaFile) { file.psi?.acceptChildren(object : LuaVisitor() { override fun visitClassMethod(o: LuaClassMethod) { cc.checkCanceled() @@ -350,21 +346,20 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD }) } } - + list } - list } } override fun resolveCodeLens(unresolved: CodeLens): CompletableFuture { return computeAsync { - val data = unresolved.data as? JsonPrimitive - val command = Command("References:0", "emmy.showReferences") - val uri = data?.asString - if (uri != null) { - val file = workspace.findFile(uri) - if (file is ILuaFile) { - file.lock { + workspace.ready { + val data = unresolved.data as? JsonPrimitive + val command = Command("References:0", "emmy.showReferences") + val uri = data?.asString + if (uri != null) { + val file = workspace.findFile(uri) + if (file is ILuaFile) { val pos = file.getPosition(unresolved.range.start.line, unresolved.range.start.character) val target = TargetElementUtil.findTarget(file.psi, pos) if (target != null) { @@ -377,61 +372,63 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD } } } - } + } + unresolved.command = command + unresolved } - unresolved.command = command - unresolved } } override fun rename(params: RenameParams): CompletableFuture { return computeAsync { - val changes = mutableListOf() - withPsiFile(params.textDocument, params.position) { _, psiFile, i -> - val target = TargetElementUtil.findTarget(psiFile, i) ?: return@withPsiFile - - val map = mutableMapOf>() - val def = target.reference?.resolve() ?: target - var refRange: Range? = null - def.nameRange?.let { range -> - val refFile = def.containingFile.virtualFile as LuaFile - val uri = refFile.uri.toString() - val list = map.getOrPut(uri) { mutableListOf() } - refRange = range.toRange(refFile) - list.add(TextEdit(refRange, params.newName)) - } + workspace.ready { + val changes = mutableListOf() + withPsiFile(params.textDocument, params.position) { _, psiFile, i -> + val target = TargetElementUtil.findTarget(psiFile, i) ?: return@withPsiFile - // references - val search = ReferencesSearch.search(def) - search.forEach { reference -> - val refFile = reference.element.containingFile.virtualFile as LuaFile - val uri = refFile.uri.toString() - val list = map.getOrPut(uri) { mutableListOf() } - val range = reference.getRangeInFile(refFile); - if (range != refRange) { - list.add(TextEdit(range, params.newName)) + val map = mutableMapOf>() + val def = target.reference?.resolve() ?: target + var refRange: Range? = null + def.nameRange?.let { range -> + val refFile = def.containingFile.virtualFile as LuaFile + val uri = refFile.uri.toString() + val list = map.getOrPut(uri) { mutableListOf() } + refRange = range.toRange(refFile) + list.add(TextEdit(refRange, params.newName)) } - } - map.forEach { (t, u) -> - val documentIdentifier = VersionedTextDocumentIdentifier() - documentIdentifier.uri = t - changes.add(TextDocumentEdit(documentIdentifier, u)) + // references + val search = ReferencesSearch.search(def) + search.forEach { reference -> + val refFile = reference.element.containingFile.virtualFile as LuaFile + val uri = refFile.uri.toString() + val list = map.getOrPut(uri) { mutableListOf() } + val range = reference.getRangeInFile(refFile); + if (range != refRange) { + list.add(TextEdit(range, params.newName)) + } + } + + map.forEach { (t, u) -> + val documentIdentifier = VersionedTextDocumentIdentifier() + documentIdentifier.uri = t + changes.add(TextDocumentEdit(documentIdentifier, u)) + } } + val edit = WorkspaceEdit(changes.map { Either.forLeft(it) }) + edit } - val edit = WorkspaceEdit(changes.map { Either.forLeft(it) }) - edit } } override fun completion(params: CompletionParams): CompletableFuture, CompletionList>> { - val file = workspace.findFile(params.textDocument.uri) return computeAsync { checker -> - val list = CompletionList() - list.items = mutableListOf() - if (file is ILuaFile) { - file.lock { + workspace.ready { + val file = workspace.findFile(params.textDocument.uri) + val list = CompletionList() + list.items = mutableListOf() + if (file is ILuaFile) { val psi = file.psi val pos = file.getPosition(params.position.line, params.position.character) val trigger = params.context.triggerCharacter @@ -451,703 +448,258 @@ class LuaTextDocumentService(private val workspace: LuaWorkspaceService) : TextD } } } + Either.forRight, CompletionList>(list) } - Either.forRight, CompletionList>(list) } } -// override fun colorPresentation(params: ColorPresentationParams): CompletableFuture> { -// return super.colorPresentation(params) -// } - override fun documentSymbol(params: DocumentSymbolParams): CompletableFuture>> { - val file = workspace.findFile(params.textDocument.uri) return computeAsync { - val list = mutableListOf>() - if (file is ILuaFile) { - file.lock { + workspace.ready { + val file = workspace.findFile(params.textDocument.uri) + val list = mutableListOf>() + if (file is ILuaFile) { val psi = file.psi if (psi is LuaPsiFile) { val symbols = getDocumentSymbols(psi, file) symbols.forEach { symbol -> list.add(Either.forRight(symbol)) } } } + list } - list } } override fun didOpen(params: DidOpenTextDocumentParams) { - val uri = params.textDocument.uri - val file = workspace.findFile(uri) - if (file == null) { - val u = URI(uri) - workspace.addFile(File(u.path), params.textDocument.text, true) - } else if (file is LuaFile) { - file.text = params.textDocument.text - } - if (file is ILuaFile) { - val diagnosticList = mutableListOf() - DiagnosticsService.inspectFile(file, diagnosticList) - this.client?.publishDiagnostics(PublishDiagnosticsParams( - uri, diagnosticList - )) + workspace.canWrite { + val uri = params.textDocument.uri + val file = workspace.findFile(uri) + if (file == null) { + val u = URI(uri) + workspace.addFile(File(u.path), params.textDocument.text, true) + } else if (file is LuaFile) { + file.text = params.textDocument.text + } + if (file is ILuaFile) { + val diagnosticList = mutableListOf() + DiagnosticsService.inspectFile(file, diagnosticList) + this.client?.publishDiagnostics(PublishDiagnosticsParams( + uri, diagnosticList + )) + } } } override fun didSave(params: DidSaveTextDocumentParams) { - val uri = params.textDocument.uri - val file = workspace.findFile(uri) - if (file is ILuaFile) { - val diagnosticList = mutableListOf() - DiagnosticsService.inspectFile(file, diagnosticList) - this.client?.publishDiagnostics( - PublishDiagnosticsParams( - uri, diagnosticList - ) - ) + workspace.canWrite { + val uri = params.textDocument.uri + val file = workspace.findFile(uri) + if (file is ILuaFile) { + val diagnosticList = mutableListOf() + DiagnosticsService.inspectFile(file, diagnosticList) + this.client?.publishDiagnostics( + PublishDiagnosticsParams( + uri, diagnosticList + ) + ) + } } } override fun signatureHelp(params: SignatureHelpParams?): CompletableFuture { return computeAsync { - var signatureHelp: SignatureHelp? = null - val list = mutableListOf() - var activeParameter = 0 - var activeSig = 0 - if (params != null) { - withPsiFile(params.textDocument, params.position) { _, psiFile, i -> - val callExpr = PsiTreeUtil.findElementOfClassAtOffset(psiFile, i, LuaCallExpr::class.java, false) - var nCommas = 0 - callExpr?.args?.firstChild?.let { firstChild -> - var child: PsiElement? = firstChild - while (child != null) { - if (child.node.elementType == LuaTypes.COMMA) { - activeParameter++ - nCommas++ + workspace.ready { + var signatureHelp: SignatureHelp? = null + val list = mutableListOf() + var activeParameter = 0 + var activeSig = 0 + if (params != null) { + withPsiFile(params.textDocument, params.position) { _, psiFile, i -> + val callExpr = PsiTreeUtil.findElementOfClassAtOffset(psiFile, i, LuaCallExpr::class.java, false) + var nCommas = 0 + callExpr?.args?.firstChild?.let { firstChild -> + var child: PsiElement? = firstChild + while (child != null) { + if (child.node.elementType == LuaTypes.COMMA) { + activeParameter++ + nCommas++ + } + child = child.nextSibling } - child = child.nextSibling } - } - callExpr?.guessParentType(SearchContext.get(psiFile.project))?.let { parentType -> - parentType.each { ty -> - var tyFunction: ITy? = ty - if(tyFunction is ITyClass){ - val context = SearchContext.get(workspace.getProject()) - tyFunction = tyFunction.getClassCallType(context) - } + callExpr?.guessParentType(SearchContext.get(psiFile.project))?.let { parentType -> + parentType.each { ty -> + var tyFunction: ITy? = ty + if (tyFunction is ITyClass) { + val context = SearchContext.get(workspace.getProject()) + tyFunction = tyFunction.getClassCallType(context) + } + + if (tyFunction is ITyFunction) { + val active = tyFunction.findPerfectSignature(callExpr, nCommas + 1) + var idx = 0 + tyFunction.process(Processor { sig -> + val information = SignatureInformation() + information.parameters = mutableListOf() + sig.params.forEach { pi -> + val pTy = pi.ty + val pTyDisplay: String = if (pTy is TyStringLiteral) { + "\"${pTy.displayName}\"" + } else { + pTy.displayName + } - if (tyFunction is ITyFunction) { - val active = tyFunction.findPerfectSignature(callExpr, nCommas + 1) - var idx = 0 - tyFunction.process(Processor { sig -> - val information = SignatureInformation() - information.parameters = mutableListOf() - sig.params.forEach { pi -> - val pTy = pi.ty - val pTyDisplay: String = if (pTy is TyStringLiteral) { - "\"${pTy.displayName}\"" - } else { - pTy.displayName + val paramInfo = + ParameterInformation("${pi.name}${if (pi.nullable) "?" else ""}:${pTyDisplay}") + information.parameters.add(paramInfo) } - val paramInfo = - ParameterInformation("${pi.name}${if (pi.nullable) "?" else ""}:${pTyDisplay}") - information.parameters.add(paramInfo) - } - - if (sig.hasVarargs()) { - val paramInfo = - ParameterInformation("...:${sig.varargTy?.displayName}") - information.parameters.add(paramInfo) - } - if(sig.document != null){ - information.documentation = Either.forRight(MarkupContent(MarkupKind.MARKDOWN, sig.document)) - } - - information.label = sig.displayName - list.add(information) - - if (sig == active) { - activeSig = idx - if (sig.hasVarargs() && activeParameter > information.parameters.size - 1) { - activeParameter = information.parameters.size - 1 + if (sig.hasVarargs()) { + val paramInfo = + ParameterInformation("...:${sig.varargTy?.displayName}") + information.parameters.add(paramInfo) + } + if (sig.document != null) { + information.documentation = Either.forRight(MarkupContent(MarkupKind.MARKDOWN, sig.document)) } - } - idx++ - true - }) - } - } - } - } - if (list.size > 0) { - signatureHelp = SignatureHelp(list, activeSig, activeParameter) - } - } - signatureHelp - } - } - override fun didClose(params: DidCloseTextDocumentParams) { - workspace.removeFileIfNeeded(params.textDocument.uri) - } + information.label = sig.displayName + list.add(information) - // @deprecated please use emmyluaCodeStyle plugin - override fun formatting(params: DocumentFormattingParams?): CompletableFuture> { - return computeAsync { - val list = mutableListOf() - val file = params?.textDocument?.let { it -> workspace.findFile(it.uri) } - - if (file is ILuaFile) { - file.psi?.let { psi -> - val formatter = FormattingFormatter(file, psi) - val keywords = setOf( - "function", "local", "end", "do", "then", "while", "repeat", "if", - "until", "for", "in", "elseif", "else", "return", "goto" - ) - - val operators = setOf( - "(", ")", "{", "}", "[", "]", // 括号 - "+", "-", "*", "/", "//", "%", //运算 - "and", "not", "or", "==", "~=", "<=", ">=", "<", ">", // 逻辑运算 - ":", ".", //调用运算符 - "~", "^", "&", "|", "<<", ">>", //位运算 - ",", ";", "=", "#", "::", ".." - ) // 杂七杂八 - - psi.acceptChildren(object : LuaVisitor() { - override fun visitComment(comment: PsiComment?) { - comment?.let { - // 判断是不是行内注释 - if (it.tokenType.toString() == "SHORT_COMMENT") { - var sibling = it.prevSibling - while (sibling != null) { - if (sibling.node.elementType.toString() != "WHITE_SPACE") { - val commentLine = file.getLine(comment.textRange.startOffset).first - val siblingLine = file.getLine(sibling.textRange.endOffset).first - if (siblingLine == commentLine) { - if (sibling is LuaLocalDef - || sibling is LuaAssignStat - || sibling is LuaExprStat - || sibling is LuaBreakStat - || sibling is LuaReturnStat - || sibling is LuaLabelStat - ) { - formatter.attachTo(sibling, it) - return - } + if (sig == active) { + activeSig = idx + if (sig.hasVarargs() && activeParameter > information.parameters.size - 1) { + activeParameter = information.parameters.size - 1 } - break; } - sibling = sibling.prevSibling - } - } - - formatter.add(it, FormattingType.Comment) - } - } - - override fun visitErrorElement(element: PsiErrorElement?) { - element?.let { - formatter.add(it, FormattingType.Error) - } - } - - override fun visitExpr(o: LuaExpr) { - formatter.add(o, FormattingType.Expr) - o.acceptChildren(this) - } - - override fun visitParenExpr(o: LuaParenExpr) { - formatter.add(o, FormattingType.ParentExpr) - o.acceptChildren(this) - } - - override fun visitCallExpr(o: LuaCallExpr) { - formatter.add(o, FormattingType.CallExpr) - o.acceptChildren(this) - } - - override fun visitIndexExpr(o: LuaIndexExpr) { - formatter.add(o, FormattingType.IndexExpr) - o.acceptChildren(this) - } - - override fun visitLiteralExpr(o: LuaLiteralExpr) { - formatter.add(o, FormattingType.LiteralExpr) - o.acceptChildren(this) - } - - override fun visitNameExpr(o: LuaNameExpr) { - formatter.add(o, FormattingType.NamedExpr) - o.acceptChildren(this) - } - - override fun visitBinaryExpr(o: LuaBinaryExpr) { - formatter.add(o, FormattingType.BinaryExpr) - o.acceptChildren(this) - } - - override fun visitUnaryExpr(o: LuaUnaryExpr) { - formatter.add(o, FormattingType.UnaryExpr) - o.acceptChildren(this) - } - - override fun visitTableExpr(o: LuaTableExpr) { - formatter.add(o, FormattingType.TableExpr) - o.acceptChildren(this) - } - - override fun visitTableFieldSep(o: LuaTableFieldSep) { - formatter.add(o, FormattingType.TableFieldSep) - } - - override fun visitTableField(o: LuaTableField) { - formatter.add(o, FormattingType.TableField) - o.acceptChildren(this) - } - - override fun visitEmptyStat(o: LuaEmptyStat) { - formatter.add(o, FormattingType.EmptyStatement) - } - - override fun visitExprStat(o: LuaExprStat) { - formatter.add(o, FormattingType.ExprStatement) - o.acceptChildren(this) - } - - override fun visitClassMethodName(o: LuaClassMethodName) { - formatter.add(o, FormattingType.Id) - } - - override fun visitBlock(o: LuaBlock) { - formatter.add(o, FormattingType.Block) - o.acceptChildren(this) - } - - override fun visitStatement(o: LuaStatement) { - formatter.add(o, FormattingType.Statement) - o.acceptChildren(this) - } - - override fun visitFuncBody(o: LuaFuncBody) { - formatter.add(o, FormattingType.FunctionBody) - o.acceptChildren(this) - } - - override fun visitBreakStat(o: LuaBreakStat) { - formatter.add(o, FormattingType.BreakStatement) - } - - override fun visitIfStat(o: LuaIfStat) { - formatter.add(o, FormattingType.IfStatement) - o.acceptChildren(this) - } - - override fun visitReturnStat(o: LuaReturnStat) { - formatter.add(o, FormattingType.ReturnStatement) - o.acceptChildren(this) - } - - override fun visitFuncDef(o: LuaFuncDef) { - formatter.add(o, FormattingType.Function) - o.acceptChildren(this) - } - - override fun visitParamNameDef(o: LuaParamNameDef) { - formatter.add(o, FormattingType.Arg) - } - - override fun visitLocalFuncDef(o: LuaLocalFuncDef) { - formatter.add(o, FormattingType.LocalFunction) - o.acceptChildren(this) - } - - override fun visitClassMethodDef(o: LuaClassMethodDef) { - formatter.add(o, FormattingType.Function) - o.acceptChildren(this) - } - - override fun visitClosureExpr(o: LuaClosureExpr) { - formatter.add(o, FormattingType.Closure) - o.acceptChildren(this) - } - - override fun visitWhileStat(o: LuaWhileStat) { - formatter.add(o, FormattingType.WhileStatement) - o.acceptChildren(this) - } - - override fun visitDoStat(o: LuaDoStat) { - formatter.add(o, FormattingType.DoBlock) - o.acceptChildren(this) - } - - override fun visitRepeatStat(o: LuaRepeatStat) { - formatter.add(o, FormattingType.RepeatStatement) - o.acceptChildren(this) - } - - override fun visitForAStat(o: LuaForAStat) { - formatter.add(o, FormattingType.ForAStatement) - o.acceptChildren(this) - } - - override fun visitForBStat(o: LuaForBStat) { - formatter.add(o, FormattingType.ForBStatement) - o.acceptChildren(this) - } - - override fun visitLocalDef(o: LuaLocalDef) { - formatter.add(o, FormattingType.LocalStatement) - o.acceptChildren(this) - } - - override fun visitAssignStat(o: LuaAssignStat) { - formatter.add(o, FormattingType.AssignStatement) - o.acceptChildren(this) - } - - override fun visitAttribute(o: LuaAttribute) { - formatter.add(o, FormattingType.Attribute) - o.acceptChildren(this) - } - - override fun visitNameList(o: LuaNameList) { - formatter.add(o, FormattingType.NameDefList) - o.acceptChildren(this) - } - - override fun visitNameDef(o: LuaNameDef) { - formatter.add(o, FormattingType.NameDef) - } - - override fun visitArgs(o: LuaArgs) { - formatter.add(o, FormattingType.CallArgs) - o.acceptChildren(this) - } - - override fun visitSingleArg(o: LuaSingleArg) { - formatter.add(o, FormattingType.SingleArg) - o.acceptChildren(this) - } - - override fun visitExprList(o: LuaExprList) { - formatter.add(o, FormattingType.ExprList) - o.acceptChildren(this) - } - - override fun visitBinaryOp(o: LuaBinaryOp) { - formatter.add(o, FormattingType.BinaryOperator) - o.acceptChildren(this) - } - - override fun visitUnaryOp(o: LuaUnaryOp) { - formatter.add(o, FormattingType.UnaryOperator) - o.acceptChildren(this) - } - - override fun visitGotoStat(o: LuaGotoStat) { - formatter.add(o, FormattingType.GotoStatement) - o.acceptChildren(this) - } - - override fun visitLabelStat(o: LuaLabelStat) { - formatter.add(o, FormattingType.LabelStatement) - o.acceptChildren(this) - } - - override fun visitShebangLine(o: LuaShebangLine) { - formatter.add(o, FormattingType.Comment) - } - - override fun visitElement(element: PsiElement?) { - element?.let { - when (element.node?.elementType.toString()) { - in keywords -> { - formatter.add(element, FormattingType.KeyWorld) - } - in operators -> { - formatter.add(element, FormattingType.Operator) - } - "..." -> { - formatter.add(element, FormattingType.Id) - } - "ID" -> { - formatter.add(element, FormattingType.Id) - } - else -> { - // ignore - } + idx++ + true + }) } } } - }) - - - val lines = file.getLine(psi.textRange.endOffset) - list.add( - TextEdit( - Range(Position(0, 0), Position(lines.first, lines.second)), - formatter.getFormattingResult() - ) - ) + } + if (list.size > 0) { + signatureHelp = SignatureHelp(list, activeSig, activeParameter) + } } + signatureHelp } - - list } } - override fun didChange(params: DidChangeTextDocumentParams) { - val file = workspace.findFile(params.textDocument.uri) - if (file is ILuaFile) { - file.didChange(params) + override fun didClose(params: DidCloseTextDocumentParams) { + workspace.canWrite { + workspace.removeFileIfNeeded(params.textDocument.uri) } } - override fun references(params: ReferenceParams): CompletableFuture> { - return computeAsync { - val list = mutableListOf() - withPsiFile(params.textDocument, params.position) { _, psiFile, pos -> - val element = TargetElementUtil.findTarget(psiFile, pos) - if (element != null) { - val target = element.reference?.resolve() ?: element - val query = ReferencesSearch.search(target) - query.forEach { ref -> - val luaFile = ref.element.containingFile.virtualFile as LuaFile - list.add(Location(luaFile.uri.toString(), ref.getRangeInFile(luaFile))) - } - } + override fun didChange(params: DidChangeTextDocumentParams) { + workspace.canWrite { + val file = workspace.findFile(params.textDocument.uri) + if (file is ILuaFile) { + file.didChange(params) } - list } } - override fun foldingRange(params: FoldingRangeRequestParams?): CompletableFuture> { + override fun references(params: ReferenceParams): CompletableFuture> { return computeAsync { - val file = params?.textDocument?.let { it -> workspace.findFile(it.uri) } - val foldingRanges = mutableListOf() - // 用于region - var regionStartLine = -1 - // 用于require - var requireStartLine = -1 - var requireLastLine = -1 - - if (file is ILuaFile) { - file.lock { - file.psi?.acceptChildren(object : LuaRecursiveVisitor() { - override fun visitComment(comment: PsiComment?) { - comment?.let { - // 在require 语句中不支持--region - if (it.tokenType.toString() == "REGION") { - regionStartLine = file.getLine(it.textRange.startOffset).first - } else if (it.tokenType.toString() == "ENDREGION") { - if (regionStartLine != -1) { - val endLine = file.getLine(it.textRange.startOffset).first - val foldRange = FoldingRange(regionStartLine, endLine) - foldRange.kind = "region" - foldingRanges.add(foldRange) - regionStartLine = -1 - } - } - } - } - - override fun visitIfStat(o: LuaIfStat) { - val parent = this - var keywordLine = -1 - o.acceptChildren(object : LuaVisitor() { - override fun visitBlock(o: LuaBlock) { - o.acceptChildren(parent) - } - - override fun visitElement(element: PsiElement?) { - element?.let { - if (element.text == "if") { - keywordLine = file.getLine(element.textOffset).first - } else if (element.text == "else" || element.text == "end" || element.text == "elseif") { - val endLine = file.getLine(element.textOffset).first - 1 - if (endLine > keywordLine && keywordLine != -1) { - foldingRanges.add(FoldingRange(keywordLine, endLine)) - } - keywordLine = endLine + 1 - } - } - } - - }) - } - - override fun visitElement(element: PsiElement) { - if (element is LuaFuncDef - || element is LuaClassMethodDef - || element is LuaLocalFuncDef - || element is LuaClosureExpr - || element is LuaWhileStat - || element is LuaRepeatStat - || element is LuaDoStat - || element is LuaForAStat - || element is LuaForBStat - || element is LuaTableExpr - ) { - var startLine = -1 - // 过滤注释行 - if (element.firstChild is LuaComment) { - var child: PsiElement? = element.firstChild - while (child != null) { - if (child.node.elementType == LuaTypes.FUNCTION - || child.node.elementType == LuaTypes.REPEAT - || child.node.elementType == LuaTypes.DO - || child.node.elementType == LuaTypes.TABLE_FIELD - || child.node.elementType == LuaTypes.FOR - ) { - startLine = file.getLine(child.textRange.startOffset).first - break - } - child = child.nextSibling; - } - - } else { - startLine = file.getLine(element.textRange.startOffset).first - } - - // 去掉end行 - val endLine = file.getLine(element.textRange.endOffset).first - 1 - if (endLine > startLine && startLine != -1) { - val foldRange = FoldingRange(startLine, endLine) - foldingRanges.add(foldRange) - element.acceptChildren(this) - return - } - } - - var callExpr = element - if (element is LuaStatement) { - element.acceptChildren(object : LuaRecursiveVisitor() { - override fun visitCallExpr(o: LuaCallExpr) { - callExpr = o - } - }) - } - - if (callExpr is LuaCallExpr) { - if (callExpr.firstChild.text == "require") { - val lines = file.getLine(callExpr.textOffset) - if (requireStartLine == -1) { - requireStartLine = lines.first - } - requireLastLine = lines.first - return - } - } - - if (requireStartLine != -1) { - val sameLines = file.getLine(callExpr.textOffset) - if (sameLines.first > requireLastLine) { - val foldRange = FoldingRange(requireStartLine, requireLastLine) - foldRange.kind = "imports" - foldingRanges.add(foldRange) - requireStartLine = -1 - requireLastLine = -1 - } - } - - element.acceptChildren(this) + workspace.ready { + val list = mutableListOf() + withPsiFile(params.textDocument, params.position) { _, psiFile, pos -> + val element = TargetElementUtil.findTarget(psiFile, pos) + if (element != null) { + val target = element.reference?.resolve() ?: element + val query = ReferencesSearch.search(target) + query.forEach { ref -> + val luaFile = ref.element.containingFile.virtualFile as LuaFile + list.add(Location(luaFile.uri.toString(), ref.getRangeInFile(luaFile))) } - }) - - if (requireStartLine != -1) { - val foldRange = FoldingRange(requireStartLine, requireLastLine) - foldRange.kind = "imports" - foldingRanges.add(foldRange) } } + list } - foldingRanges } } -// override fun semanticTokensFull(params: SemanticTokensParams?): CompletableFuture { -// return super.semanticTokensFull(params) -// } - override fun inlayHint(params: InlayHintParams): CompletableFuture> { - val file = workspace.findFile(params.textDocument.uri) return computeAsync { - var list: MutableList = mutableListOf() - if (file is LuaFile) { - file.lock { + workspace.ready { + val file = workspace.findFile(params.textDocument.uri) + var list: MutableList = mutableListOf() + if (file is LuaFile) { // 认为所有local名称定义一开始都是未使用的 list = InlayHintService.getInlayHint(file) } + list } - list } } override fun diagnostic(params: DocumentDiagnosticParams): CompletableFuture { - val file = workspace.findFile(params.textDocument.uri) - return if (file is ILuaFile) { - val report = workspace.diagnoseFile(file, params.previousResultId, null) - CompletableFuture.completedFuture(report) - } else { - val report = DocumentDiagnosticReport(RelatedUnchangedDocumentDiagnosticReport()) - CompletableFuture.completedFuture(report) + return computeAsync { + workspace.ready { + val file = workspace.findFile(params.textDocument.uri) + if (file is ILuaFile) { + workspace.diagnoseFile(file, params.previousResultId, null) + } else { + DocumentDiagnosticReport(RelatedUnchangedDocumentDiagnosticReport()) + } + } } } override fun resolveInlayHint(unresolved: InlayHint): CompletableFuture { return computeAsync { - if (unresolved.data != null && unresolved.data is JsonPrimitive) { - val data = (unresolved.data as JsonPrimitive).asString - val texts = data.split("#") - val labelParts = mutableListOf() - if (texts.size == 2) { - val className = texts[0] - val fieldName = texts[1] - val context = SearchContext.get(workspace.getProject()) - val resolveList = mutableListOf() - LuaClassMemberIndex.process(className, fieldName, context, Processor { - resolveList.add(PsiElementResolveResult(it)) - false - }) + workspace.ready { + if (unresolved.data != null && unresolved.data is JsonPrimitive) { + val data = (unresolved.data as JsonPrimitive).asString + val texts = data.split("#") + val labelParts = mutableListOf() + if (texts.size == 2) { + val className = texts[0] + val fieldName = texts[1] + val context = SearchContext.get(workspace.getProject()) + val resolveList = mutableListOf() + LuaClassMemberIndex.process(className, fieldName, context, Processor { + resolveList.add(PsiElementResolveResult(it)) + false + }) - val resolve = resolveList.firstOrNull()?.element - if (resolve != null) { - val sourceFile = resolve.containingFile?.virtualFile as? LuaFile - val range = resolve.nameRange - if (range != null && sourceFile != null) { - val labelPart = InlayHintLabelPart(unresolved.label.left) - labelPart.location = Location(sourceFile.uri.toString(), range.toRange(sourceFile)) - labelParts.add(labelPart) + val resolve = resolveList.firstOrNull()?.element + if (resolve != null) { + val sourceFile = resolve.containingFile?.virtualFile as? LuaFile + val range = resolve.nameRange + if (range != null && sourceFile != null) { + val labelPart = InlayHintLabelPart(unresolved.label.left) + labelPart.location = Location(sourceFile.uri.toString(), range.toRange(sourceFile)) + labelParts.add(labelPart) + } } + } + unresolved.label = Either.forRight(labelParts) } - - unresolved.label = Either.forRight(labelParts) + unresolved } - unresolved } } private fun withPsiFile( - textDocument: TextDocumentIdentifier, - position: Position, - code: (ILuaFile, LuaPsiFile, Int) -> Unit + textDocument: TextDocumentIdentifier, + position: Position, + code: (ILuaFile, LuaPsiFile, Int) -> Unit ) { val file = workspace.findFile(textDocument.uri) if (file is ILuaFile) { - file.lock { - val psi = file.psi - if (psi is LuaPsiFile) { - val pos = file.getPosition(position.line, position.character) - code(file, psi, pos) - } + val psi = file.psi + if (psi is LuaPsiFile) { + val pos = file.getPosition(position.line, position.character) + code(file, psi, pos) } } } diff --git a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaWorkspaceService.kt b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaWorkspaceService.kt index 576c885..95d43e9 100644 --- a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaWorkspaceService.kt +++ b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/LuaWorkspaceService.kt @@ -31,6 +31,8 @@ import java.io.File import java.net.URI import java.util.concurrent.CompletableFuture import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.read +import kotlin.concurrent.write /** * tangzx @@ -44,7 +46,7 @@ class LuaWorkspaceService : WorkspaceService, IWorkspace { private val project: Project = WProject() private val fileManager = FileManager(project) private val fileScopeProvider = WorkspaceRootFileScopeProvider() - private var initWorkspace = true + private val rwl = ReentrantReadWriteLock() inner class WProject : UserDataHolderBase(), Project { override fun process(processor: Processor) { @@ -65,6 +67,14 @@ class LuaWorkspaceService : WorkspaceService, IWorkspace { fileManager.addProvider(fileScopeProvider) } + fun ready(code: () -> R): R { + return rwl.read(code) + } + + fun canWrite(code: () -> Unit) { + rwl.write(code) + } + override fun didChangeWatchedFiles(params: DidChangeWatchedFilesParams) { for (change in params.changes) { when (change.type) { @@ -86,8 +96,7 @@ class LuaWorkspaceService : WorkspaceService, IWorkspace { override fun didChangeConfiguration(params: DidChangeConfigurationParams) { val settings = params.settings as? JsonObject ?: return val ret = VSCodeSettings.update(settings) - if (ret.associationChanged || initWorkspace) { - initWorkspace = false + if (ret.associationChanged) { loadWorkspace() refreshWorkspace() } @@ -159,58 +168,6 @@ class LuaWorkspaceService : WorkspaceService, IWorkspace { } } -// override fun diagnostic(params: WorkspaceDiagnosticParams): CompletableFuture { -// for (prev in params.previousResultIds) { -// val file = findFile(prev.uri) -// if (file is LuaFile) { -// file.workspaceDiagnosticResultId = prev.value -// } -// } -// -// val files = mutableListOf() -// project.process { -// val file = it.virtualFile -// if (file is LuaFile) { -// files.add(file) -// } -// true -// } -// -// return computeAsync { checker -> -// for (luaFile in files) { -// luaFile.lock { -// val documentReport = diagnoseFile(luaFile, luaFile.workspaceDiagnosticResultId, checker) -// if (documentReport.isRelatedFullDocumentDiagnosticReport) { -// val workspaceItemReport = WorkspaceFullDocumentDiagnosticReport( -// documentReport.relatedFullDocumentDiagnosticReport.items, -// luaFile.uri.toString(), -// null -// ) -// -// workspaceItemReport.resultId = documentReport.relatedFullDocumentDiagnosticReport.resultId -// val report = WorkspaceDiagnosticReportPartialResult( -// listOf(WorkspaceDocumentDiagnosticReport(workspaceItemReport)) -// ) -// client?.notifyProgress(ProgressParams(params.partialResultToken, Either.forRight(report))) -// } else if (documentReport.isRelatedUnchangedDocumentDiagnosticReport) { -// val workspaceItemReport = WorkspaceUnchangedDocumentDiagnosticReport( -// documentReport.relatedUnchangedDocumentDiagnosticReport.resultId, -// luaFile.uri.toString(), -// null -// ) -// val report = WorkspaceDiagnosticReportPartialResult( -// listOf(WorkspaceDocumentDiagnosticReport(workspaceItemReport)) -// ) -// client?.notifyProgress(ProgressParams(params.partialResultToken, Either.forRight(report))) -// } -// } -// } -// -// val empty = WorkspaceDiagnosticReport(emptyList()) -// empty -// } -// } - private fun getSchemeFolder(path: FileURI, autoCreate: Boolean): IFolder? { var folder: IFolder? = schemeMap[path.scheme] if (folder == null && autoCreate) { @@ -243,7 +200,6 @@ class LuaWorkspaceService : WorkspaceService, IWorkspace { val pair = findOrCreate(fileURI, true) val folder = pair.first!! -// if (pair.second) rootList.add(folder) return folder } @@ -330,32 +286,34 @@ class LuaWorkspaceService : WorkspaceService, IWorkspace { } private fun loadWorkspace(monitor: IProgressMonitor) { - try { - monitor.start(); - monitor.setProgress("load workspace folders", 0f) - val collections = fileManager.findAllFiles() - var totalFileCount = 0f - var processedCount = 0f - collections.forEach { totalFileCount += it.files.size } - for (collection in collections) { - addRoot(collection.root) - for (uri in collection.files) { - processedCount++ - val file = uri.toFile() - if (file != null) { - monitor.setProgress( - "indexing ${processedCount.toInt()} / ${totalFileCount.toInt()} (${file.name})", - processedCount / totalFileCount - ) + rwl.write { + try { + monitor.start(); + monitor.setProgress("load workspace folders", 0f) + val collections = fileManager.findAllFiles() + var totalFileCount = 0f + var processedCount = 0f + collections.forEach { totalFileCount += it.files.size } + for (collection in collections) { + addRoot(collection.root) + for (uri in collection.files) { + processedCount++ + val file = uri.toFile() + if (file != null) { + monitor.setProgress( + "indexing ${processedCount.toInt()} / ${totalFileCount.toInt()} (${file.name})", + processedCount / totalFileCount + ) + } + addFile(uri, null) } - addFile(uri, null) } + } catch (e: Exception) { + monitor.reportError("workspace parse error: $e") } - } catch (e: Exception) { - monitor.reportError("workspace parse error: $e") - } - monitor.done() + monitor.done() + } } override fun findFile(uri: String): IVirtualFile? { diff --git a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/api/impl/LuaFile.kt b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/api/impl/LuaFile.kt index 49c89c1..31136de 100644 --- a/EmmyLua-LS/src/main/kotlin/com/tang/vscode/api/impl/LuaFile.kt +++ b/EmmyLua-LS/src/main/kotlin/com/tang/vscode/api/impl/LuaFile.kt @@ -38,40 +38,39 @@ class LuaFile(override val uri: FileURI) : VirtualFileBase(uri), ILuaFile, Virtu private var _lines = mutableListOf() private var _myPsi: LuaPsiFile? = null private var _words: List? = null - private var _rwl = ReentrantReadWriteLock() private var _isOpen = false override fun didChange(params: DidChangeTextDocumentParams) { - _rwl.write { - if (params.contentChanges.isEmpty()) - return - - var sb = _text.toString() - var offset = 0 - params.contentChanges.forEach { - when { - // for TextDocumentSyncKind.Full - it.range == null -> sb = it.text - // incremental updating - it.range.start.line >= _lines.size -> { - sb += it.text - _lines.add(Line(it.range.start.line, it.range.start.character, it.range.end.character)) - } - else -> { - val sline = _lines[it.range.start.line] - val eline = _lines[it.range.end.line] - val spos = sline.startOffset + it.range.start.character - val epos = eline.startOffset + it.range.end.character - sb = sb.replaceRange(spos, epos, it.text) - - val textSize = it.text.length - offset += textSize - it.rangeLength - } + if (params.contentChanges.isEmpty()) + return + + var sb = _text.toString() + var offset = 0 + params.contentChanges.forEach { + when { + // for TextDocumentSyncKind.Full + it.range == null -> sb = it.text + // incremental updating + it.range.start.line >= _lines.size -> { + sb += it.text + _lines.add(Line(it.range.start.line, it.range.start.character, it.range.end.character)) + } + + else -> { + val sline = _lines[it.range.start.line] + val eline = _lines[it.range.end.line] + val spos = sline.startOffset + it.range.start.character + val epos = eline.startOffset + it.range.end.character + sb = sb.replaceRange(spos, epos, it.text) + + val textSize = it.text.length + offset += textSize - it.rangeLength } } - _text = sb - onChanged() } + _text = sb + onChanged() + } override fun getText(): CharSequence { @@ -83,11 +82,9 @@ class LuaFile(override val uri: FileURI) : VirtualFileBase(uri), ILuaFile, Virtu } fun setText(str: CharSequence) { - _rwl.write { - _text = str - _isOpen = true - onChanged() - } + _text = str + _isOpen = true + onChanged() } private fun updateLines() { @@ -126,9 +123,9 @@ class LuaFile(override val uri: FileURI) : VirtualFileBase(uri), ILuaFile, Virtu unindex() val parser = LuaParser() val builder = PsiBuilderFactory.getInstance().createBuilder( - LuaParserDefinition(), - FlexAdapter(_LuaLexer(LuaLanguageLevel.LUA54)), - text + LuaParserDefinition(), + FlexAdapter(_LuaLexer(LuaLanguageLevel.LUA54)), + text ) val node = parser.parse(LuaParserDefinition.FILE, builder) val psi = node.psi @@ -184,9 +181,7 @@ class LuaFile(override val uri: FileURI) : VirtualFileBase(uri), ILuaFile, Virtu } override fun lock(code: () -> Unit) { - _rwl.read { - code() - } + code() } fun diagnostic(diagnostics: MutableList, checker: CancelChecker?) { @@ -196,18 +191,6 @@ class LuaFile(override val uri: FileURI) : VirtualFileBase(uri), ILuaFile, Virtu override val psi: PsiFile? get() = _myPsi - var opened: Boolean - get() { - _rwl.read { - return _isOpen - } - } - set(value) { - _rwl.write { - _isOpen = value - } - } - override fun getPsiFile() = _myPsi override fun unindex() { @@ -221,10 +204,10 @@ class LuaFile(override val uri: FileURI) : VirtualFileBase(uri), ILuaFile, Virtu override fun processWords(processor: (w: Word) -> Boolean) { if (_words == null) { val scanner = DefaultWordsScanner( - LuaLexer(), - TokenSet.EMPTY, - TokenSet.EMPTY, - TokenSet.EMPTY + LuaLexer(), + TokenSet.EMPTY, + TokenSet.EMPTY, + TokenSet.EMPTY ) val list = mutableListOf() scanner.processWords(this._text) {