Skip to content

Commit 70dfeb4

Browse files
authored
Merge pull request #543 from fwcd/improve-exclusions
Model script exclusion via `SourceExclusions` and skip files entirely instead of placing them temporarily on the source path
2 parents a18cd78 + bf9800e commit 70dfeb4

File tree

7 files changed

+58
-44
lines changed

7 files changed

+58
-44
lines changed

server/src/main/kotlin/org/javacs/kt/CompilerClassPath.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,20 +157,20 @@ class CompilerClassPath(
157157

158158
private fun isBuildScript(file: Path): Boolean = file.fileName.toString().let { it == "pom.xml" || it == "build.gradle" || it == "build.gradle.kts" }
159159

160+
private fun findJavaSourceFiles(root: Path): Set<Path> {
161+
val sourceMatcher = FileSystems.getDefault().getPathMatcher("glob:*.java")
162+
return SourceExclusions(listOf(root), scriptsConfig)
163+
.walkIncluded()
164+
.filter { sourceMatcher.matches(it.fileName) }
165+
.toSet()
166+
}
167+
160168
override fun close() {
161169
compiler.close()
162170
outputDirectory.delete()
163171
}
164172
}
165173

166-
private fun findJavaSourceFiles(root: Path): Set<Path> {
167-
val sourceMatcher = FileSystems.getDefault().getPathMatcher("glob:*.java")
168-
return SourceExclusions(root)
169-
.walkIncluded()
170-
.filter { sourceMatcher.matches(it.fileName) }
171-
.toSet()
172-
}
173-
174174
private fun logAdded(sources: Collection<Path>, name: String) {
175175
when {
176176
sources.isEmpty() -> return

server/src/main/kotlin/org/javacs/kt/Configuration.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,6 @@ public data class DiagnosticsConfiguration(
3030
var debounceTime: Long = 250L
3131
)
3232

33-
public data class ScriptsConfiguration(
34-
/** Whether .kts scripts are handled. */
35-
var enabled: Boolean = false,
36-
/** Whether .gradle.kts scripts are handled. Only considered if scripts are enabled in general. */
37-
var buildScriptsEnabled: Boolean = false
38-
)
39-
4033
public data class JVMConfiguration(
4134
/** Which JVM target the Kotlin compiler uses. See Compiler.jvmTargetFrom for possible values. */
4235
var target: String = "default"

server/src/main/kotlin/org/javacs/kt/KotlinTextDocumentService.kt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,13 @@ class KotlinTextDocumentService(
7474
ALWAYS, AFTER_DOT, NEVER
7575
}
7676

77-
private fun recover(position: TextDocumentPositionParams, recompile: Recompile): Pair<CompiledFile, Int> {
77+
private fun recover(position: TextDocumentPositionParams, recompile: Recompile): Pair<CompiledFile, Int>? {
7878
return recover(position.textDocument.uri, position.position, recompile)
7979
}
8080

81-
private fun recover(uriString: String, position: Position, recompile: Recompile): Pair<CompiledFile, Int> {
81+
private fun recover(uriString: String, position: Position, recompile: Recompile): Pair<CompiledFile, Int>? {
8282
val uri = parseURI(uriString)
83+
if (!sf.isIncluded(uri)) return null
8384
val content = sp.content(uri)
8485
val offset = offset(content, position.line, position.character)
8586
val shouldRecompile = when (recompile) {
@@ -92,26 +93,26 @@ class KotlinTextDocumentService(
9293
}
9394

9495
override fun codeAction(params: CodeActionParams): CompletableFuture<List<Either<Command, CodeAction>>> = async.compute {
95-
val (file, _) = recover(params.textDocument.uri, params.range.start, Recompile.NEVER)
96+
val (file, _) = recover(params.textDocument.uri, params.range.start, Recompile.NEVER) ?: return@compute emptyList()
9697
codeActions(file, sp.index, params.range, params.context)
9798
}
9899

99100
override fun inlayHint(params: InlayHintParams): CompletableFuture<List<InlayHint>> = async.compute {
100-
val (file, _) = recover(params.textDocument.uri, params.range.start, Recompile.ALWAYS)
101+
val (file, _) = recover(params.textDocument.uri, params.range.start, Recompile.ALWAYS) ?: return@compute emptyList()
101102
provideHints(file, config.inlayHints)
102103
}
103104

104105
override fun hover(position: HoverParams): CompletableFuture<Hover?> = async.compute {
105106
reportTime {
106107
LOG.info("Hovering at {}", describePosition(position))
107108

108-
val (file, cursor) = recover(position, Recompile.NEVER)
109+
val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute null
109110
hoverAt(file, cursor) ?: noResult("No hover found at ${describePosition(position)}", null)
110111
}
111112
}
112113

113114
override fun documentHighlight(position: DocumentHighlightParams): CompletableFuture<List<DocumentHighlight>> = async.compute {
114-
val (file, cursor) = recover(position.textDocument.uri, position.position, Recompile.NEVER)
115+
val (file, cursor) = recover(position.textDocument.uri, position.position, Recompile.NEVER) ?: return@compute emptyList()
115116
documentHighlightsAt(file, cursor)
116117
}
117118

@@ -123,7 +124,7 @@ class KotlinTextDocumentService(
123124
reportTime {
124125
LOG.info("Go-to-definition at {}", describePosition(position))
125126

126-
val (file, cursor) = recover(position, Recompile.NEVER)
127+
val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute Either.forLeft(emptyList())
127128
goToDefinition(file, cursor, uriContentProvider.classContentProvider, tempDirectory, config.externalSources, cp)
128129
?.let(::listOf)
129130
?.let { Either.forLeft<List<Location>, List<LocationLink>>(it) }
@@ -144,19 +145,19 @@ class KotlinTextDocumentService(
144145
}
145146

146147
override fun rename(params: RenameParams) = async.compute {
147-
val (file, cursor) = recover(params, Recompile.NEVER)
148+
val (file, cursor) = recover(params, Recompile.NEVER) ?: return@compute null
148149
renameSymbol(file, cursor, sp, params.newName)
149150
}
150151

151-
override fun completion(position: CompletionParams) = async.compute {
152+
override fun completion(position: CompletionParams): CompletableFuture<Either<List<CompletionItem>, CompletionList>> = async.compute {
152153
reportTime {
153154
LOG.info("Completing at {}", describePosition(position))
154155

155-
val (file, cursor) = recover(position, Recompile.NEVER) // TODO: Investigate when to recompile
156+
val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute Either.forRight(CompletionList()) // TODO: Investigate when to recompile
156157
val completions = completions(file, cursor, sp.index, config.completion)
157158
LOG.info("Found {} items", completions.items.size)
158159

159-
Either.forRight<List<CompletionItem>, CompletionList>(completions)
160+
Either.forRight(completions)
160161
}
161162
}
162163

@@ -195,7 +196,7 @@ class KotlinTextDocumentService(
195196
reportTime {
196197
LOG.info("Signature help at {}", describePosition(position))
197198

198-
val (file, cursor) = recover(position, Recompile.NEVER)
199+
val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute null
199200
fetchSignatureHelpAt(file, cursor) ?: noResult("No function call around ${describePosition(position)}", null)
200201
}
201202
}

server/src/main/kotlin/org/javacs/kt/SourceFiles.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,15 @@ class SourceFiles(
6969
private val scriptsConfig: ScriptsConfiguration
7070
) {
7171
private val workspaceRoots = mutableSetOf<Path>()
72-
private var exclusions = SourceExclusions(workspaceRoots)
72+
private var exclusions = SourceExclusions(workspaceRoots, scriptsConfig)
7373
private val files = NotifySourcePath(sp)
7474
private val open = mutableSetOf<URI>()
7575

7676
fun open(uri: URI, content: String, version: Int) {
77-
files[uri] = SourceVersion(content, version, languageOf(uri), isTemporary = !exclusions.isURIIncluded(uri))
78-
open.add(uri)
77+
if (exclusions.isURIIncluded(uri)) {
78+
files[uri] = SourceVersion(content, version, languageOf(uri), isTemporary = false)
79+
open.add(uri)
80+
}
7981
}
8082

8183
fun close(uri: URI) {
@@ -177,23 +179,21 @@ class SourceFiles(
177179
}
178180

179181
private fun findSourceFiles(root: Path): Set<URI> {
180-
val glob = if (scriptsConfig.enabled) "*.{kt,kts}" else "*.kt"
181-
val sourceMatcher = FileSystems.getDefault().getPathMatcher("glob:$glob")
182-
return SourceExclusions(root)
182+
val sourceMatcher = FileSystems.getDefault().getPathMatcher("glob:*.{kt,kts}")
183+
return SourceExclusions(listOf(root), scriptsConfig)
183184
.walkIncluded()
184-
.filter {
185-
sourceMatcher.matches(it.fileName)
186-
&& (scriptsConfig.buildScriptsEnabled || !it.endsWith(".gradle.kts"))
187-
}
185+
.filter { sourceMatcher.matches(it.fileName) }
188186
.map(Path::toUri)
189187
.toSet()
190188
}
191189

192190
private fun updateExclusions() {
193-
exclusions = SourceExclusions(workspaceRoots)
191+
exclusions = SourceExclusions(workspaceRoots, scriptsConfig)
194192
}
195193

196194
fun isOpen(uri: URI): Boolean = (uri in open)
195+
196+
fun isIncluded(uri: URI): Boolean = exclusions.isURIIncluded(uri)
197197
}
198198

199199
private fun patch(sourceText: String, change: TextDocumentContentChangeEvent): String {

server/src/test/kotlin/org/javacs/kt/ScriptTest.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@ import org.hamcrest.Matchers.hasItem
44
import org.junit.Assert.assertThat
55
import org.junit.Test
66

7-
class ScriptTest : LanguageServerTestFixture("script") {
7+
class ScriptTest : LanguageServerTestFixture("script", Configuration().apply {
8+
scripts.enabled = true
9+
}) {
810
@Test fun `open script`() {
911
open("ExampleScript.kts")
1012
}
1113
}
1214

13-
class EditFunctionTest : SingleFileTestFixture("script", "FunctionScript.kts") {
15+
class EditFunctionTest : SingleFileTestFixture("script", "FunctionScript.kts", Configuration().apply {
16+
scripts.enabled = true
17+
}) {
1418
@Test fun `edit a function in a script`() {
1519
replace("FunctionScript.kts", 3, 18, "2", "f")
1620

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.javacs.kt
2+
3+
public data class ScriptsConfiguration(
4+
/** Whether .kts scripts are handled. */
5+
var enabled: Boolean = false,
6+
/** Whether .gradle.kts scripts are handled. Only considered if scripts are enabled in general. */
7+
var buildScriptsEnabled: Boolean = false
8+
)

shared/src/main/kotlin/org/javacs/kt/SourceExclusions.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,18 @@ import java.nio.file.Paths
99

1010
// TODO: Read exclusions from gitignore/settings.json/... instead of
1111
// hardcoding them
12-
class SourceExclusions(private val workspaceRoots: Collection<Path>) {
13-
private val excludedPatterns = listOf(".*", "bazel-*", "bin", "build", "node_modules", "target").map { FileSystems.getDefault().getPathMatcher("glob:$it") }
14-
15-
constructor(workspaceRoot: Path) : this(listOf(workspaceRoot)) {}
12+
class SourceExclusions(
13+
private val workspaceRoots: Collection<Path>,
14+
private val scriptsConfig: ScriptsConfiguration
15+
) {
16+
private val excludedPatterns = (listOf(
17+
".*", "bazel-*", "bin", "build", "node_modules", "target"
18+
) + when {
19+
!scriptsConfig.enabled -> listOf("*.kts")
20+
!scriptsConfig.buildScriptsEnabled -> listOf("*.gradle.kts")
21+
else -> emptyList()
22+
})
23+
.map { FileSystems.getDefault().getPathMatcher("glob:$it") }
1624

1725
/** Finds all non-excluded files recursively. */
1826
fun walkIncluded(): Sequence<Path> = workspaceRoots.asSequence().flatMap { root ->

0 commit comments

Comments
 (0)