From 328ff93b1a730d4b0fdfe270303e6aa327f037cc Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Sat, 2 Dec 2023 23:52:26 +0530 Subject: [PATCH] fix(lsp/java): avoid crash during Java source code analysis This issue was reported in #1279 (https://github.com/AndroidIDEOfficial/AndroidIDE/issues/1279\#issuecomment-1826706454). --- .idea/compiler.xml | 2 +- .idea/kotlinc.xml | 2 +- .../lsp/java/providers/DiagnosticsProvider.kt | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 2e1f4ab95..c0791d981 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -18,7 +18,7 @@ - + diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index f8467b458..ae3f30ae1 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/DiagnosticsProvider.kt b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/DiagnosticsProvider.kt index eb556d014..616058da3 100644 --- a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/DiagnosticsProvider.kt +++ b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/DiagnosticsProvider.kt @@ -43,6 +43,7 @@ import java.util.regex.Pattern import jdkx.lang.model.element.Element import jdkx.tools.Diagnostic import jdkx.tools.JavaFileObject +import java.lang.IndexOutOfBoundsException /** * Finds errors and warnings from a compilation task. @@ -98,7 +99,7 @@ object DiagnosticsProvider { val scanner = DiagnosticVisitor(task.task) scanner.scan(root, notThrown) for (unusedEl in scanner.notUsed()) { - result.add(warnUnused(task, unusedEl)) + warnUnused(task, unusedEl)?.also { result.add(it) } } for (location in notThrown.keys) { @@ -169,7 +170,7 @@ object DiagnosticsProvider { ) } - private fun warnUnused(task: CompileTask, unusedEl: Element): DiagnosticItem { + private fun warnUnused(task: CompileTask, unusedEl: Element): DiagnosticItem? { val trees = Trees.instance(task.task) val path = trees.getPath(unusedEl) ?: throw RuntimeException("$unusedEl has no path") val root = path.compilationUnit @@ -177,24 +178,34 @@ object DiagnosticsProvider { val pos = trees.sourcePositions var start = pos.getStartPosition(root, leaf).toInt() var end = pos.getEndPosition(root, leaf).toInt() + if (leaf is VariableTree) { val offset = pos.getEndPosition(root, leaf.type).toInt() if (offset != -1) { start = offset } } + val file = Paths.get(root.sourceFile.toUri()) val contents = FileManager.getDocumentContents(file) var name = unusedEl.simpleName if (name.contentEquals("")) { name = unusedEl.enclosingElement.simpleName } - val region = contents.subSequence(start, end) + + val region = try { + contents.subSequence(start, end) + } catch (err: IndexOutOfBoundsException) { + // might happen if the file contents were changed after the file was compiled for analysis + return null + } + val matcher = Pattern.compile("\\b$name\\b").matcher(region) if (matcher.find()) { start += matcher.start() end = start + name.length } + val message = String.format("'%s' is not used", name) val code: DiagnosticCode val severity: DiagnosticSeverity @@ -232,6 +243,7 @@ object DiagnosticsProvider { severity = DiagnosticSeverity.INFO } } + return asDiagnosticItem(severity, code.id, message, start.toLong(), end.toLong(), root) }