Skip to content

Commit f368353

Browse files
authored
Configuration codelenses in source files don't draw if a config exists (#1123)
If an in-source file already has a launch.json entry that matches the root and handler that a CodeLens would produce, we no longer draw the CodeLens. This is similar to the behavior for CodeLenses in template files.
1 parent 76399c9 commit f368353

File tree

5 files changed

+249
-43
lines changed

5 files changed

+249
-43
lines changed

src/shared/codelens/codeLensUtils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6+
import * as path from 'path'
67
import * as vscode from 'vscode'
78

89
import { CloudFormation } from '../cloudformation/cloudformation'
@@ -18,6 +19,7 @@ import { ExtContext } from '../extensions'
1819
import { recordLambdaInvokeLocal, Result, Runtime } from '../telemetry/telemetry'
1920
import { nodeJsRuntimes, RuntimeFamily } from '../../lambda/models/samLambdaRuntime'
2021
import { CODE_TARGET_TYPE } from '../sam/debugger/awsSamDebugConfiguration'
22+
import { getReferencedHandlerPaths, LaunchConfiguration } from '../debug/launchConfiguration'
2123

2224
export type Language = 'python' | 'javascript' | 'csharp'
2325

@@ -46,6 +48,7 @@ export async function makeCodeLenses({
4648
}
4749

4850
const lenses: vscode.CodeLens[] = []
51+
const existingConfigs = getReferencedHandlerPaths(new LaunchConfiguration(document.uri))
4952
for (const handler of handlers) {
5053
// handler.range is a RangeOrCharOffset union type. Extract vscode.Range.
5154
const range =
@@ -63,7 +66,9 @@ export async function makeCodeLenses({
6366
rootUri: handler.manifestUri,
6467
runtimeFamily,
6568
}
66-
lenses.push(makeAddCodeSamDebugCodeLens(baseParams))
69+
if (!existingConfigs.has(path.join(path.dirname(baseParams.rootUri.fsPath), baseParams.handlerName))) {
70+
lenses.push(makeAddCodeSamDebugCodeLens(baseParams))
71+
}
6772
} catch (err) {
6873
getLogger().error(
6974
`Could not generate 'configure' code lens for handler '${handler.handlerName}'`,

src/shared/codelens/samTemplateCodeLensProvider.ts

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,10 @@
66
import * as _ from 'lodash'
77
import * as vscode from 'vscode'
88
import { TemplateFunctionResource, TemplateSymbolResolver } from '../cloudformation/templateSymbolResolver'
9-
import { LaunchConfiguration } from '../debug/launchConfiguration'
10-
import {
11-
isTemplateTargetProperties,
12-
TemplateTargetProperties,
13-
TEMPLATE_TARGET_TYPE,
14-
} from '../sam/debugger/awsSamDebugConfiguration'
9+
import { getReferencedTemplateResources, LaunchConfiguration } from '../debug/launchConfiguration'
10+
import { TEMPLATE_TARGET_TYPE } from '../sam/debugger/awsSamDebugConfiguration'
1511
import { AddSamDebugConfigurationInput } from '../sam/debugger/commands/addSamDebugConfiguration'
1612
import { localize } from '../utilities/vsCodeUtils'
17-
import * as pathutils from '../utilities/pathUtils'
1813

1914
/**
2015
* Provides Code Lenses for generating debug configurations for SAM templates.
@@ -31,7 +26,7 @@ export class SamTemplateCodeLensProvider implements vscode.CodeLensProvider {
3126
return []
3227
}
3328

34-
const existingDebuggedResources = getExistingDebuggedResources(document.uri, launchConfig)
29+
const existingDebuggedResources = getReferencedTemplateResources(launchConfig)
3530

3631
return _(functionResources)
3732
.reject(functionResource => existingDebuggedResources.has(functionResource.name))
@@ -52,21 +47,3 @@ export class SamTemplateCodeLensProvider implements vscode.CodeLensProvider {
5247
})
5348
}
5449
}
55-
56-
function getExistingDebuggedResources(templateUri: vscode.Uri, launchConfig: LaunchConfiguration): Set<string> {
57-
const existingSamDebugTargets = getExistingSamDebugTargets(launchConfig)
58-
const folder = vscode.workspace.getWorkspaceFolder(templateUri)
59-
60-
return _(existingSamDebugTargets)
61-
.filter(target => pathutils.areEqual(folder?.uri.fsPath, target.samTemplatePath, templateUri.fsPath))
62-
.map(target => target.samTemplateResource)
63-
.thru(array => new Set(array))
64-
.value()
65-
}
66-
67-
function getExistingSamDebugTargets(launchConfig: LaunchConfiguration): TemplateTargetProperties[] {
68-
return _(launchConfig.getSamDebugConfigurations())
69-
.map(samConfig => samConfig.invokeTarget)
70-
.filter(isTemplateTargetProperties)
71-
.value()
72-
}

src/shared/debug/launchConfiguration.ts

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@
44
*/
55

66
import * as _ from 'lodash'
7+
import * as path from 'path'
78
import * as vscode from 'vscode'
9+
import { CloudFormationTemplateRegistry } from '../cloudformation/templateRegistry'
810
import {
911
AwsSamDebuggerConfiguration,
10-
isAwsSamDebugConfiguration,
12+
CodeTargetProperties,
1113
ensureRelativePaths,
14+
isAwsSamDebugConfiguration,
15+
isCodeTargetProperties,
16+
isTemplateTargetProperties,
17+
TemplateTargetProperties,
1218
} from '../sam/debugger/awsSamDebugConfiguration'
1319
import {
1420
AwsSamDebugConfigurationValidator,
1521
DefaultAwsSamDebugConfigurationValidator,
1622
} from '../sam/debugger/awsSamDebugConfigurationValidator'
17-
import { CloudFormationTemplateRegistry } from '../cloudformation/templateRegistry'
23+
import * as pathutils from '../utilities/pathUtils'
24+
import { tryGetAbsolutePath } from '../utilities/workspaceUtils'
1825

1926
/**
2027
* Reads and writes DebugConfigurations.
@@ -28,17 +35,20 @@ export interface DebugConfigurationSource {
2835
* Wraps read and write operations on launch.json.
2936
*/
3037
export class LaunchConfiguration {
38+
public readonly workspaceFolder: vscode.WorkspaceFolder | undefined
3139
/**
3240
* Creates a Launch Configuration scoped to the given resource.
3341
*/
3442
public constructor(
35-
resource: vscode.Uri,
36-
private readonly configSource: DebugConfigurationSource = new DefaultDebugConfigSource(resource),
43+
public readonly scopedResource: vscode.Uri,
44+
private readonly configSource: DebugConfigurationSource = new DefaultDebugConfigSource(scopedResource),
3745
private readonly samValidator: AwsSamDebugConfigurationValidator = new DefaultAwsSamDebugConfigurationValidator(
3846
CloudFormationTemplateRegistry.getRegistry(),
39-
vscode.workspace.getWorkspaceFolder(resource)
47+
vscode.workspace.getWorkspaceFolder(scopedResource)
4048
)
41-
) {}
49+
) {
50+
this.workspaceFolder = vscode.workspace.getWorkspaceFolder(scopedResource)
51+
}
4252

4353
public getDebugConfigurations(): vscode.DebugConfiguration[] {
4454
return _(this.configSource.getDebugConfigurations())
@@ -84,3 +94,60 @@ class DefaultDebugConfigSource implements DebugConfigurationSource {
8494
await this.launch.update('configurations', value)
8595
}
8696
}
97+
98+
function getSamTemplateTargets(launchConfig: LaunchConfiguration): TemplateTargetProperties[] {
99+
return _(launchConfig.getSamDebugConfigurations())
100+
.map(samConfig => samConfig.invokeTarget)
101+
.filter(isTemplateTargetProperties)
102+
.value()
103+
}
104+
105+
function getSamCodeTargets(launchConfig: LaunchConfiguration): CodeTargetProperties[] {
106+
return _(launchConfig.getSamDebugConfigurations())
107+
.map(samConfig => samConfig.invokeTarget)
108+
.filter(isCodeTargetProperties)
109+
.value()
110+
}
111+
112+
/**
113+
* Returns a Set containing the samTemplateResources from the launch.json file that the launch config is scoped to.
114+
* @param launchConfig Launch config to check
115+
*/
116+
export function getReferencedTemplateResources(launchConfig: LaunchConfiguration): Set<string> {
117+
const existingSamTemplateTargets = getSamTemplateTargets(launchConfig)
118+
const folder = launchConfig.workspaceFolder
119+
120+
return _(existingSamTemplateTargets)
121+
.filter(target =>
122+
pathutils.areEqual(folder?.uri.fsPath, target.samTemplatePath, launchConfig.scopedResource.fsPath)
123+
)
124+
.map(target => target.samTemplateResource)
125+
.thru(array => new Set(array))
126+
.value()
127+
}
128+
129+
/**
130+
* Returns a Set containing the full path for all `code`-type `aws-sam` debug configs in a launch.json file.
131+
* The full path represents `path.join(workspaceFolder, projectRoot, lambdaHandler)`
132+
* (without workspaceFolder if the projectRoot is relative).
133+
* @param launchConfig Launch config to check
134+
*/
135+
export function getReferencedHandlerPaths(launchConfig: LaunchConfiguration): Set<string> {
136+
const existingSamCodeTargets = getSamCodeTargets(launchConfig)
137+
138+
return _(existingSamCodeTargets)
139+
.map(target => {
140+
if (path.isAbsolute(target.projectRoot)) {
141+
return pathutils.normalize(path.join(target.projectRoot, target.lambdaHandler))
142+
}
143+
return pathutils.normalize(
144+
path.join(
145+
tryGetAbsolutePath(launchConfig.workspaceFolder, ''),
146+
target.projectRoot,
147+
target.lambdaHandler
148+
)
149+
)
150+
})
151+
.thru(array => new Set(array))
152+
.value()
153+
}

src/test/shared/codelens/samTemplateCodeLensProvider.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ describe('SamTemplateCodeLensProvider', async () => {
6565
mockLaunchConfig = mock()
6666

6767
when(mockDocument.uri).thenReturn(templateUri)
68+
when(mockLaunchConfig.scopedResource).thenReturn(templateUri)
69+
when(mockLaunchConfig.workspaceFolder).thenReturn({
70+
uri: templateUri,
71+
name: 'notAWorkspaceFolder',
72+
index: 1,
73+
})
6874
when(mockLaunchConfig.getSamDebugConfigurations()).thenReturn(debugConfigurations)
6975
})
7076

0 commit comments

Comments
 (0)