Skip to content

Commit

Permalink
Prevent name clashes between a function in class and a function call …
Browse files Browse the repository at this point in the history
…in current scope. (#1850)

* Prevent name clashes between an function in class and a function call in current scope.

* update changelog;

* Improves after review;
  • Loading branch information
ivk1800 committed Mar 4, 2024
1 parent 54fc91b commit c9c94cf
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Change Log

## Unreleased

* Fix: Prevent name clashes between a function in class and a function call in current scope (#1850).
* Fix: Fix extension function imports (#1814).
* Fix: Omit implicit modifiers on FileSpec.scriptBuilder (#1813).
* Fix: Fix trailing newline in PropertySpec (#1827).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,11 +464,14 @@ internal class CodeWriter constructor(
val simpleName = imports[memberName.canonicalName]?.alias ?: memberName.simpleName
// Match an imported member.
val importedMember = importedMembers[simpleName]
if (importedMember == memberName) {
val found = importedMember == memberName
if (found && !isMethodNameUsedInCurrentContext(simpleName)) {
return simpleName
} else if (importedMember != null && memberName.enclosingClassName != null) {
val enclosingClassName = lookupName(memberName.enclosingClassName)
return "$enclosingClassName.$simpleName"
} else if (found) {
return simpleName
}

// If the member is in the same package, we're done.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,68 @@ class MemberNameTest {
)
}

@Test fun importedMemberClassFunctionNameDontClashForParameterValue() {
fun createBuildFunc(params: List<String>): FunSpec {
val tacoClassname = ClassName.bestGuess("com.squareup.tacos.Taco")
val bodyCodeBlock = CodeBlock.builder()
.add("return %T", tacoClassname)
.apply {
val paramsBlock = params.map { paramName ->
val paramValue = ClassName(
packageName = "com.squareup",
simpleNames = listOf("Fridge"),
).member("meat")
CodeBlock.of("$paramName = %L", CodeBlock.of("%M { }", paramValue))
}
.map { block -> CodeBlock.of("%L", block) }
.joinToCode(prefix = "(", suffix = ")")
add(paramsBlock)
}
.build()
return FunSpec.builder("build")
.returns(tacoClassname)
.addCode(bodyCodeBlock)
.build()
}

val spec = FileSpec.builder("com.squareup.tacos", "Tacos")
.addType(
TypeSpec.classBuilder("DeliciousTaco")
.addFunction(createBuildFunc(listOf("deliciousMeat")))
.addFunction(FunSpec.builder("deliciousMeat").build())
.build(),
)
.addType(
TypeSpec.classBuilder("TastelessTaco")
.addFunction(createBuildFunc(listOf("meat")))
.addFunction(FunSpec.builder("meat").build())
.build(),
)
val source = spec.build()
assertThat(source.toString()).isEqualTo(
"""
|package com.squareup.tacos
|
|import com.squareup.Fridge.meat
|
|public class DeliciousTaco {
| public fun build(): Taco = Taco(deliciousMeat = meat { })
|
| public fun deliciousMeat() {
| }
|}
|
|public class TastelessTaco {
| public fun build(): Taco = Taco(meat = com.squareup.Fridge.meat { })
|
| public fun meat() {
| }
|}
|
""".trimMargin(),
)
}

@Test fun memberNameAliases() {
val createSquareTaco = MemberName("com.squareup.tacos", "createTaco")
val createTwitterTaco = MemberName("com.twitter.tacos", "createTaco")
Expand Down

0 comments on commit c9c94cf

Please sign in to comment.