Skip to content

Commit 390f5ef

Browse files
authored
Merge pull request #399 from themkat/rename_decl_site
Rename variable from declaration site
2 parents 1e48712 + a57d8a8 commit 390f5ef

File tree

5 files changed

+72
-16
lines changed

5 files changed

+72
-16
lines changed

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import org.javacs.kt.compiler.CompilationKind
66
import org.javacs.kt.position.changedRegion
77
import org.javacs.kt.position.location
88
import org.javacs.kt.position.position
9+
import org.javacs.kt.position.range
910
import org.javacs.kt.util.findParent
1011
import org.javacs.kt.util.nullResult
1112
import org.javacs.kt.util.toPath
@@ -175,10 +176,15 @@ class CompiledFile(
175176
}
176177

177178

179+
/**
180+
* Find the declaration of the element at the cursor.
181+
*/
182+
fun findDeclaration(cursor: Int): Pair<KtNamedDeclaration, Location>? = findDeclarationReference(cursor) ?: findDeclarationCursorSite(cursor)
183+
178184
/**
179185
* Find the declaration of the element at the cursor. Only works if the element at the cursor is a reference.
180186
*/
181-
fun findDeclaration(cursor: Int): Pair<KtNamedDeclaration, Location>? {
187+
private fun findDeclarationReference(cursor: Int): Pair<KtNamedDeclaration, Location>? {
182188
val (_, target) = referenceAtPoint(cursor) ?: return null
183189
val psi = target.findPsi()
184190

@@ -193,6 +199,22 @@ class CompiledFile(
193199
}
194200
}
195201

202+
/**
203+
* Find the declaration of the element at the cursor.
204+
* Works even in cases where the element at the cursor might not be a reference, so works for declaration sites.
205+
*/
206+
private fun findDeclarationCursorSite(cursor: Int): Pair<KtNamedDeclaration, Location>? {
207+
// current symbol might be a declaration. This function is used as a fallback when
208+
// findDeclaration fails
209+
val declaration = elementAtPoint(cursor)?.findParent<KtNamedDeclaration>()
210+
211+
return declaration?.let {
212+
Pair(it,
213+
Location(it.containingFile.name,
214+
range(content, it.nameIdentifier?.textRange ?: return null)))
215+
}
216+
}
217+
196218
/**
197219
* Find the lexical-scope surrounding `cursor`.
198220
* This may be out-of-date if the user is typing quickly.

server/src/main/kotlin/org/javacs/kt/highlight/DocumentHighlight.kt

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.psi.KtNamedDeclaration
1212

1313
fun documentHighlightsAt(file: CompiledFile, cursor: Int): List<DocumentHighlight> {
1414
val (declaration, declarationLocation) = file.findDeclaration(cursor)
15-
?: file.findDeclarationCursorSite(cursor)
1615
?: return emptyList()
1716
val references = findReferencesToDeclarationInFile(declaration, file)
1817

@@ -23,18 +22,4 @@ fun documentHighlightsAt(file: CompiledFile, cursor: Int): List<DocumentHighligh
2322
} + references.map { DocumentHighlight(it, DocumentHighlightKind.Text) }
2423
}
2524

26-
private fun CompiledFile.findDeclarationCursorSite(cursor: Int): Pair<KtNamedDeclaration, Location>? {
27-
// current symbol might be a declaration. This function is used as a fallback when
28-
// findDeclaration fails
29-
val declaration = elementAtPoint(cursor)?.findParent<KtNamedDeclaration>()
30-
31-
return declaration?.let {
32-
// in this scenario we know that the declaration will be at the cursor site, so uri is not
33-
// important
34-
Pair(it,
35-
Location("",
36-
range(content, it.nameIdentifier?.textRange ?: return null)))
37-
}
38-
}
39-
4025
private fun KtNamedDeclaration.isInFile(file: KtFile) = this.containingFile == file

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,43 @@ class RenameDefinitionTest : SingleFileTestFixture("rename", "SomeOtherClass.kt"
4343
assertThat(changes[0].left.edits[0].range.end, equalTo(Position(2, 20)))
4444
}
4545
}
46+
47+
class RenameDeclarationSiteTest : SingleFileTestFixture("rename", "DeclSite.kt") {
48+
49+
@Test
50+
fun `should rename variable from usage site`() {
51+
val usageFile = workspaceRoot.resolve("UsageSite.kt").toString()
52+
val edits = languageServer.textDocumentService.rename(renameParams(usageFile, 4, 13, "newvarname")).get()!!
53+
val changes = edits.documentChanges
54+
55+
assertThat(changes.size, equalTo(2))
56+
57+
val firstChange = changes[0].left
58+
assertThat(firstChange.textDocument.uri, containsString("DeclSite.kt"))
59+
assertThat(firstChange.edits[0].newText, equalTo("newvarname"))
60+
assertThat(firstChange.edits[0].range, equalTo(range(3, 5, 3, 10)))
61+
62+
val secondChange = changes[1].left
63+
assertThat(secondChange.textDocument.uri, containsString("UsageSite.kt"))
64+
assertThat(secondChange.edits[0].newText, equalTo("newvarname"))
65+
assertThat(secondChange.edits[0].range, equalTo(range(4, 13, 4, 18)))
66+
}
67+
68+
@Test
69+
fun `should rename variable from declaration site`() {
70+
val edits = languageServer.textDocumentService.rename(renameParams(file, 3, 6, "newvarname")).get()!!
71+
val changes = edits.documentChanges
72+
73+
assertThat(changes.size, equalTo(2))
74+
75+
val firstChange = changes[0].left
76+
assertThat(firstChange.textDocument.uri, containsString("DeclSite.kt"))
77+
assertThat(firstChange.edits[0].newText, equalTo("newvarname"))
78+
assertThat(firstChange.edits[0].range, equalTo(range(3, 5, 3, 10)))
79+
80+
val secondChange = changes[1].left
81+
assertThat(secondChange.textDocument.uri, containsString("UsageSite.kt"))
82+
assertThat(secondChange.edits[0].newText, equalTo("newvarname"))
83+
assertThat(secondChange.edits[0].range, equalTo(range(4, 13, 4, 18)))
84+
}
85+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package declsite
2+
3+
val myvar = 2
4+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package declsite
2+
3+
fun myfunc() {
4+
println(myvar)
5+
}

0 commit comments

Comments
 (0)