Skip to content

Commit d4f7dda

Browse files
authored
Merge branch 'aws:master' into master
2 parents 54be0b3 + 003941e commit d4f7dda

File tree

13 files changed

+110
-49
lines changed

13 files changed

+110
-49
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "/review: Diagnostics in the problems panel are mapped to the wrong code"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "/review: Code fix automatically scrolls into view after generation."
4+
}

packages/amazonq/test/unit/codewhisperer/service/diagnosticsProvider.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
removeDiagnostic,
1313
disposeSecurityDiagnostic,
1414
SecurityDiagnostic,
15+
createSecurityDiagnostic,
16+
codewhispererDiagnosticSourceLabel,
1517
} from 'aws-core-vscode/codewhisperer'
1618
import { createCodeScanIssue, createMockDocument, createTextDocumentChangeEvent } from 'aws-core-vscode/test'
1719

@@ -83,4 +85,16 @@ describe('diagnosticsProvider', function () {
8385
assert.strictEqual(actual[1].range.start.line, 5)
8486
assert.strictEqual(actual[1].range.end.line, 6)
8587
})
88+
89+
it('should create securityDiagnostic from codeScanIssue', function () {
90+
const codeScanIssue = createCodeScanIssue()
91+
const securityDiagnostic = createSecurityDiagnostic(codeScanIssue)
92+
assert.strictEqual(securityDiagnostic.findingId, codeScanIssue.findingId)
93+
assert.strictEqual(securityDiagnostic.message, codeScanIssue.title)
94+
assert.strictEqual(securityDiagnostic.range.start.line, codeScanIssue.startLine)
95+
assert.strictEqual(securityDiagnostic.range.end.line, codeScanIssue.endLine)
96+
assert.strictEqual(securityDiagnostic.severity, vscode.DiagnosticSeverity.Warning)
97+
assert.strictEqual(securityDiagnostic.source, codewhispererDiagnosticSourceLabel)
98+
assert.strictEqual(securityDiagnostic.code, codeScanIssue.ruleId)
99+
})
86100
})

packages/core/package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"AWS.configuration.description.suppressPrompts": "Prompts which ask for confirmation. Checking an item suppresses the prompt.",
2121
"AWS.configuration.enableCodeLenses": "Enable SAM hints in source code and template.yaml files",
2222
"AWS.configuration.description.resources.enabledResources": "AWS resources to display in the 'Resources' portion of the explorer.",
23-
"AWS.configuration.description.experiments": "Try experimental features and give feedback. Note that experimental features may be removed at any time.\n * `jsonResourceModification` - Enables basic create, update, and delete support for cloud resources via the JSON Resources explorer component.\n * `samSyncCode` - Adds an additional code-only option when synchronizing SAM applications. Code-only synchronizations are faster but can cause drift in the CloudFormation stack. Does nothing when using the legacy SAM deploy feature.\n * `iamPolicyChecks` - Enables IAM Policy Checks feature, allowing users to validate IAM policies against IAM policy grammar, AWS best practices, and specified security standards.",
23+
"AWS.configuration.description.experiments": "Try experimental features and give feedback. Note that experimental features may be removed at any time.\n * `jsonResourceModification` - Enables basic create, update, and delete support for cloud resources via the JSON Resources explorer component.\n * `ec2RemoteConnect` - Allows interfacing with EC2 instances with options to start, stop, and establish remote connections. Remote connections are done over SSM and can be through a terminal or a remote VSCode window.",
2424
"AWS.stepFunctions.asl.format.enable.desc": "Enables the default formatter used with Amazon States Language files",
2525
"AWS.stepFunctions.asl.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).",
2626
"AWS.configuration.description.awssam.debug.api": "API Gateway configuration",

packages/core/src/awsexplorer/regionNode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ import { DefaultSchemaClient } from '../shared/clients/schemaClient'
2929
import { getEcsRootNode } from '../awsService/ecs/model'
3030
import { compareTreeItems, TreeShim } from '../shared/treeview/utils'
3131
import { Ec2ParentNode } from '../awsService/ec2/explorer/ec2ParentNode'
32-
import { DevSettings } from '../shared/settings'
3332
import { Ec2Client } from '../shared/clients/ec2Client'
3433
import { isCloud9 } from '../shared/extensionUtilities'
34+
import { Experiments } from '../shared/settings'
3535

3636
interface ServiceNode {
3737
allRegions?: boolean
@@ -65,7 +65,7 @@ const serviceCandidates: ServiceNode[] = [
6565
},
6666
{
6767
serviceId: 'ec2',
68-
when: () => DevSettings.instance.isDevMode(),
68+
when: () => Experiments.instance.isExperimentEnabled('ec2RemoteConnect'),
6969
createFn: (regionCode: string, partitionId: string) =>
7070
new Ec2ParentNode(regionCode, partitionId, new Ec2Client(regionCode)),
7171
},

packages/core/src/codewhisperer/service/diagnosticsProvider.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,7 @@ export function createSecurityDiagnostic(securityIssue: CodeScanIssue) {
7474
vscode.DiagnosticSeverity.Warning
7575
)
7676
securityDiagnostic.source = codewhispererDiagnosticSourceLabel
77-
// const detectorUrl = securityIssue.recommendation.url
78-
securityDiagnostic.code = securityIssue.findingId
79-
// securityDiagnostic.code = detectorUrl
80-
// ? {
81-
// value: securityIssue.detectorId,
82-
// target: vscode.Uri.parse(detectorUrl),
83-
// }
84-
// : securityIssue.detectorId
77+
securityDiagnostic.code = securityIssue.ruleId
8578
securityDiagnostic.findingId = securityIssue.findingId
8679
return securityDiagnostic
8780
}

packages/core/src/codewhisperer/views/securityIssue/securityIssueWebview.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ import { ExtContext } from '../../../shared/extensions'
2424
export class SecurityIssueWebview extends VueWebview {
2525
public static readonly sourcePath: string = 'src/codewhisperer/views/securityIssue/vue/index.js'
2626
public readonly id = 'aws.codeWhisperer.securityIssue'
27+
public readonly onChangeIssue = new vscode.EventEmitter<CodeScanIssue | undefined>()
28+
public readonly onChangeFilePath = new vscode.EventEmitter<string | undefined>()
29+
public readonly onChangeGenerateFixLoading = new vscode.EventEmitter<boolean>()
30+
public readonly onChangeGenerateFixError = new vscode.EventEmitter<boolean>()
2731

2832
private issue: CodeScanIssue | undefined
2933
private filePath: string | undefined
@@ -40,10 +44,12 @@ export class SecurityIssueWebview extends VueWebview {
4044

4145
public setIssue(issue: CodeScanIssue) {
4246
this.issue = issue
47+
this.onChangeIssue.fire(issue)
4348
}
4449

4550
public setFilePath(filePath: string) {
4651
this.filePath = filePath
52+
this.onChangeFilePath.fire(filePath)
4753
}
4854

4955
public applyFix() {
@@ -90,6 +96,7 @@ export class SecurityIssueWebview extends VueWebview {
9096

9197
public setIsGenerateFixLoading(isGenerateFixLoading: boolean) {
9298
this.isGenerateFixLoading = isGenerateFixLoading
99+
this.onChangeGenerateFixLoading.fire(isGenerateFixLoading)
93100
}
94101

95102
public getIsGenerateFixError() {
@@ -98,6 +105,7 @@ export class SecurityIssueWebview extends VueWebview {
98105

99106
public setIsGenerateFixError(isGenerateFixError: boolean) {
100107
this.isGenerateFixError = isGenerateFixError
108+
this.onChangeGenerateFixError.fire(isGenerateFixError)
101109
}
102110

103111
public generateFix() {
@@ -189,12 +197,7 @@ const Panel = VueWebview.compilePanel(SecurityIssueWebview)
189197
let activePanel: InstanceType<typeof Panel> | undefined
190198

191199
export async function showSecurityIssueWebview(ctx: vscode.ExtensionContext, issue: CodeScanIssue, filePath: string) {
192-
const previousPanel = activePanel
193-
const previousId = previousPanel?.server?.getIssue()?.findingId
194-
if (previousPanel && previousId) {
195-
previousPanel.server.closeWebview(previousId)
196-
}
197-
activePanel = new Panel(ctx)
200+
activePanel ??= new Panel(ctx)
198201
activePanel.server.setIssue(issue)
199202
activePanel.server.setFilePath(filePath)
200203
activePanel.server.setIsGenerateFixLoading(false)

packages/core/src/codewhisperer/views/securityIssue/vue/root.vue

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@
4747
</div>
4848
</div>
4949

50-
<div v-if="isFixAvailable || isGenerateFixLoading || isGenerateFixError || isFixDescriptionAvailable">
50+
<div
51+
v-if="isFixAvailable || isGenerateFixLoading || isGenerateFixError || isFixDescriptionAvailable"
52+
ref="codeFixSection"
53+
>
5154
<hr />
5255

5356
<h3>Suggested code fix preview</h3>
@@ -57,7 +60,7 @@
5760
</pre>
5861
<div class="code-block">
5962
<span v-if="isFixAvailable" v-html="suggestedFixHtml"></span>
60-
<div v-if="isFixAvailable" class="code-diff-actions">
63+
<div v-if="isFixAvailable" class="code-diff-actions" ref="codeFixAction">
6164
<button class="code-diff-action-button" @click="copyFixedCode">
6265
<span class="icon icon-md icon-vscode-copy"></span> Copy
6366
</button>
@@ -201,6 +204,7 @@ export default defineComponent({
201204
},
202205
created() {
203206
this.getData()
207+
this.setupEventListeners()
204208
},
205209
beforeMount() {
206210
this.getData()
@@ -223,6 +227,32 @@ export default defineComponent({
223227
const fixedCode = await client.getFixedCode()
224228
this.updateFixedCode(fixedCode)
225229
},
230+
setupEventListeners() {
231+
client.onChangeIssue(async (issue) => {
232+
if (issue) {
233+
this.updateFromIssue(issue)
234+
}
235+
const fixedCode = await client.getFixedCode()
236+
this.updateFixedCode(fixedCode)
237+
this.scrollTo('codeFixActions')
238+
})
239+
client.onChangeFilePath(async (filePath) => {
240+
const relativePath = await client.getRelativePath()
241+
this.updateRelativePath(relativePath)
242+
243+
const languageId = await client.getLanguageId()
244+
if (languageId) {
245+
this.updateLanguageId(languageId)
246+
}
247+
})
248+
client.onChangeGenerateFixLoading((isGenerateFixLoading) => {
249+
this.isGenerateFixLoading = isGenerateFixLoading
250+
this.scrollTo('codeFixSection')
251+
})
252+
client.onChangeGenerateFixError((isGenerateFixError) => {
253+
this.isGenerateFixError = isGenerateFixError
254+
})
255+
},
226256
updateRelativePath(relativePath: string) {
227257
this.relativePath = relativePath
228258
},
@@ -339,6 +369,9 @@ ${this.fixedCode}
339369
}
340370
return doc.body.innerHTML
341371
},
372+
scrollTo(refName: string) {
373+
this.$nextTick(() => this.$refs?.[refName]?.scrollIntoView({ behavior: 'smooth' }))
374+
},
342375
},
343376
computed: {
344377
severityImage() {

packages/core/src/shared/settings-toolkit.gen.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ export const toolkitSettings = {
4141
"ssoCacheError": {}
4242
},
4343
"aws.experiments": {
44-
"jsonResourceModification": {}
44+
"jsonResourceModification": {},
45+
"ec2RemoteConnect": {}
4546
},
4647
"aws.resources.enabledResources": {},
4748
"aws.lambda.recentlyUploaded": {},

packages/core/src/shared/settings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -726,12 +726,12 @@ export class Experiments extends Settings.define(
726726
'aws.experiments',
727727
toRecord(keys(experiments), () => Boolean)
728728
) {
729-
public async isExperimentEnabled(name: ExperimentName): Promise<boolean> {
729+
public isExperimentEnabled(name: ExperimentName): boolean {
730730
try {
731731
return this._getOrThrow(name, false)
732732
} catch (error) {
733733
this._log(`experiment check for ${name} failed: %s`, error)
734-
await this.reset()
734+
this.reset().catch((e) => getLogger().error(`failed to reset experiment settings: %O`, e))
735735

736736
return false
737737
}

0 commit comments

Comments
 (0)