Skip to content

Commit be45ebf

Browse files
authored
Fix JavaLambdaHandlerResolver and disable run-markers in tests/injected text (#2727)
1 parent 8c77f3e commit be45ebf

File tree

7 files changed

+213
-3
lines changed

7 files changed

+213
-3
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "Fix Java Lambda run marker issues and disable runmarker processing in tests and language-injected text fragments"
4+
}

jetbrains-core/src/software/aws/toolkits/jetbrains/services/lambda/execution/template/YamlLambdaRunLineMarkerContributor.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.intellij.psi.PsiElement
1010
import org.jetbrains.yaml.psi.YAMLKeyValue
1111
import software.aws.toolkits.jetbrains.services.cloudformation.Function
1212
import software.aws.toolkits.jetbrains.services.cloudformation.yaml.YamlCloudFormationTemplate
13+
import software.aws.toolkits.jetbrains.utils.isTestOrInjectedText
1314

1415
class YamlLambdaRunLineMarkerContributor : RunLineMarkerContributor() {
1516

@@ -19,6 +20,10 @@ class YamlLambdaRunLineMarkerContributor : RunLineMarkerContributor() {
1920
return null
2021
}
2122

23+
if (element.isTestOrInjectedText()) {
24+
return null
25+
}
26+
2227
val parent = element.parent as? YAMLKeyValue ?: return null
2328

2429
return if (parent.key == element && YamlCloudFormationTemplate.convertPsiToResource(parent) as? Function != null) {

jetbrains-core/src/software/aws/toolkits/jetbrains/services/lambda/java/JavaLambdaHandlerResolver.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,20 @@ class JavaLambdaHandlerResolver : LambdaHandlerResolver {
3939
classes.filterIsInstance<NavigatablePsiElement>().toTypedArray()
4040
} else {
4141
val handlerMethod = classes.asSequence()
42-
.map { it.findMethodsByName(methodName, true) }
42+
.map { psiClass ->
43+
psiClass.findMethodsByName(methodName, true)
44+
.filter { it.body != null } // Filter out interfaces
45+
.filter {
46+
val file = it.containingFile.virtualFile
47+
48+
return@filter if (psiClass.implementsLambdaHandlerInterface(file)) {
49+
true
50+
} else {
51+
it.isValidHandler(psiClass, file)
52+
}
53+
}
54+
}
4355
.flatMap { it.asSequence() }
44-
.filter { it.body != null } // Filter out interfaces
4556
.pickMostSpecificHandler()
4657
handlerMethod?.let {
4758
arrayOf(it)
@@ -207,7 +218,7 @@ class JavaLambdaHandlerResolver : LambdaHandlerResolver {
207218
PsiType.getTypeByName(
208219
classFullName,
209220
project,
210-
GlobalSearchScope.projectScope(project)
221+
GlobalSearchScope.allScope(project)
211222
).isAssignableFrom(this.type)
212223

213224
private companion object {

jetbrains-core/src/software/aws/toolkits/jetbrains/services/lambda/upload/LambdaLineMarker.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import software.aws.toolkits.jetbrains.services.lambda.LambdaHandlerResolver
2323
import software.aws.toolkits.jetbrains.services.lambda.RuntimeGroup
2424
import software.aws.toolkits.jetbrains.services.lambda.runtimeGroup
2525
import software.aws.toolkits.jetbrains.settings.LambdaSettings
26+
import software.aws.toolkits.jetbrains.utils.isTestOrInjectedText
2627
import software.aws.toolkits.resources.message
2728
import javax.swing.Icon
2829

@@ -39,6 +40,11 @@ class LambdaLineMarker : LineMarkerProviderDescriptor() {
3940
}
4041

4142
val runtimeGroup = element.language.runtimeGroup ?: return null
43+
44+
if (element.isTestOrInjectedText()) {
45+
return null
46+
}
47+
4248
val handlerResolver = LambdaHandlerResolver.getInstanceOrNull(runtimeGroup) ?: return null
4349
val handler = handlerResolver.determineHandler(element) ?: return null
4450

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.utils
5+
6+
import com.intellij.injected.editor.VirtualFileWindow
7+
import com.intellij.openapi.roots.ProjectRootManager
8+
import com.intellij.psi.PsiElement
9+
10+
fun PsiElement.isTestOrInjectedText(): Boolean {
11+
val project = this.project
12+
val virtualFile = this.containingFile.virtualFile
13+
if (virtualFile is VirtualFileWindow) {
14+
return true
15+
}
16+
17+
if (ProjectRootManager.getInstance(project).fileIndex.isInTestSourceContent(virtualFile)) {
18+
return true
19+
}
20+
21+
return false
22+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.lambda.execution.template
5+
6+
import com.intellij.testFramework.runInEdtAndWait
7+
import org.assertj.core.api.Assertions.assertThat
8+
import org.jetbrains.yaml.psi.YAMLFile
9+
import org.junit.Rule
10+
import org.junit.Test
11+
import software.aws.toolkits.jetbrains.services.lambda.sam.findByLocation
12+
import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRule
13+
14+
class YamlLambdaRunLineMarkerContributorTest {
15+
@Rule
16+
@JvmField
17+
val projectRule = JavaCodeInsightTestFixtureRule()
18+
19+
val sut = YamlLambdaRunLineMarkerContributor()
20+
21+
@Test
22+
fun `finds AWS-Lambda-Function`() {
23+
runInEdtAndWait {
24+
val psiFile = projectRule.fixture.configureByText(
25+
"template.yaml",
26+
// language=YAML
27+
"""
28+
Resources:
29+
Function:
30+
Type: AWS::Lambda::Function
31+
Properties:
32+
Code: foo.zip
33+
Handler: foobar.App::handleRequest
34+
Runtime: java8
35+
""".trimIndent()
36+
) as YAMLFile
37+
val psiElement = psiFile.findByLocation("Resources.Function")?.key ?: throw RuntimeException("Can't find function")
38+
39+
assertThat(sut.getInfo(psiElement)).isNotNull
40+
}
41+
}
42+
43+
@Test
44+
fun `finds AWS-Serverless-Function`() {
45+
runInEdtAndWait {
46+
val psiFile = projectRule.fixture.configureByText(
47+
"template.yaml",
48+
// language=YAML
49+
"""
50+
Resources:
51+
Function:
52+
Type: AWS::Serverless::Function
53+
Properties:
54+
Code: foo.zip
55+
Handler: foobar.App::handleRequest
56+
Runtime: java8
57+
""".trimIndent()
58+
) as YAMLFile
59+
val psiElement = psiFile.findByLocation("Resources.Function")?.key ?: throw RuntimeException("Can't find function")
60+
61+
assertThat(sut.getInfo(psiElement)).isNotNull
62+
}
63+
}
64+
}

jetbrains-core/tst/software/aws/toolkits/jetbrains/services/lambda/java/JavaLambdaHandlerResolverTest.kt

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,104 @@ class JavaLambdaHandlerResolverTest {
248248
}
249249
}
250250

251+
@Test
252+
fun `resolves handlers with 2 parameters`() {
253+
val fixture = projectRule.fixture
254+
255+
fixture.openClass(
256+
"""
257+
package com.example;
258+
259+
import com.amazonaws.services.lambda.runtime.Context;
260+
import java.io.InputStream;
261+
import java.io.OutputStream;
262+
263+
public class LambdaHandler {
264+
public static void streamsOnly(InputStream input, OutputStream output) { }
265+
266+
public static void contextAndAnything(Object input, Context context) { }
267+
268+
public static void doesNotResolve(Object input, OutputStream outputStream) { }
269+
270+
public static void doesNotResolve2(InputStream input, Object outputStream) { }
271+
}
272+
"""
273+
)
274+
275+
runInEdtAndWait {
276+
val isHandlerValid: (String) -> Boolean = { handler -> Lambda.isHandlerValid(fixture.project, Runtime.JAVA11, handler) }
277+
278+
assertThat(isHandlerValid("com.example.LambdaHandler::streamsOnly")).isTrue
279+
assertThat(isHandlerValid("com.example.LambdaHandler::contextAndAnything")).isTrue
280+
assertThat(isHandlerValid("com.example.LambdaHandler::doesNotResolve")).isFalse
281+
assertThat(isHandlerValid("com.example.LambdaHandler::doesNotResolve2")).isFalse
282+
}
283+
}
284+
285+
@Test
286+
fun `resolves handlers with 1 parameter`() {
287+
val fixture = projectRule.fixture
288+
289+
fixture.openClass(
290+
"""
291+
package com.example;
292+
293+
import com.amazonaws.services.lambda.runtime.Context;
294+
import java.io.InputStream;
295+
296+
public class LambdaHandler {
297+
public static void works(InputStream input) { }
298+
299+
public static void alsoWorks(Object input) { }
300+
301+
public static void alsoAlsoWorks(Context context) { }
302+
}
303+
"""
304+
)
305+
306+
runInEdtAndWait {
307+
val isHandlerValid: (String) -> Boolean = { handler -> Lambda.isHandlerValid(fixture.project, Runtime.JAVA11, handler) }
308+
309+
assertThat(isHandlerValid("com.example.LambdaHandler::works")).isTrue
310+
assertThat(isHandlerValid("com.example.LambdaHandler::alsoWorks")).isTrue
311+
assertThat(isHandlerValid("com.example.LambdaHandler::alsoAlsoWorks")).isTrue
312+
}
313+
}
314+
315+
@Test
316+
fun `resolves handlers with 3 parameters`() {
317+
val fixture = projectRule.fixture
318+
319+
fixture.openClass(
320+
"""
321+
package com.example;
322+
323+
import com.amazonaws.services.lambda.runtime.Context;
324+
import java.io.InputStream;
325+
import java.io.OutputStream;
326+
327+
public class LambdaHandler {
328+
public static void works(InputStream input, OutputStream output, Context context) { }
329+
330+
public static void doesntWork(Object input, OutputStream output, Context context) { }
331+
332+
public static void doesntWork2(InputStream input, Object output, Context context) { }
333+
334+
public static void doesntWork3(InputStream input, OutputStream output, Object context) { }
335+
}
336+
"""
337+
)
338+
339+
runInEdtAndWait {
340+
val isHandlerValid: (String) -> Boolean = { handler -> Lambda.isHandlerValid(fixture.project, Runtime.JAVA11, handler) }
341+
342+
assertThat(isHandlerValid("com.example.LambdaHandler::works")).isTrue
343+
assertThat(isHandlerValid("com.example.LambdaHandler::doesntWork")).isFalse
344+
assertThat(isHandlerValid("com.example.LambdaHandler::doesntWork2")).isFalse
345+
assertThat(isHandlerValid("com.example.LambdaHandler::doesntWork3")).isFalse
346+
}
347+
}
348+
251349
@Test
252350
fun testMultipleMethodsInSameClassParameterLength() {
253351
val fixture = projectRule.fixture

0 commit comments

Comments
 (0)