Skip to content

Commit 3096613

Browse files
authored
fix(amazonq): add back inline completion code files - part 1 (#7974)
## Problem Cherry pick files from https://github.com/aws/aws-toolkit-vscode/pull/7480/files ## Solution --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 3c0a34b commit 3096613

20 files changed

+4363
-1
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as vscode from 'vscode'
7+
import { vsCodeState, ConfigurationEntry } from '../models/model'
8+
import { resetIntelliSenseState } from '../util/globalStateUtil'
9+
import { DefaultCodeWhispererClient } from '../client/codewhisperer'
10+
import { RecommendationHandler } from '../service/recommendationHandler'
11+
import { session } from '../util/codeWhispererSession'
12+
import { RecommendationService } from '../service/recommendationService'
13+
14+
/**
15+
* This function is for manual trigger CodeWhisperer
16+
*/
17+
18+
export async function invokeRecommendation(
19+
editor: vscode.TextEditor,
20+
client: DefaultCodeWhispererClient,
21+
config: ConfigurationEntry
22+
) {
23+
if (!editor || !config.isManualTriggerEnabled) {
24+
return
25+
}
26+
27+
/**
28+
* Skip when output channel gains focus and invoke
29+
*/
30+
if (editor.document.languageId === 'Log') {
31+
return
32+
}
33+
/**
34+
* When using intelliSense, if invocation position changed, reject previous active recommendations
35+
*/
36+
if (vsCodeState.isIntelliSenseActive && editor.selection.active !== session.startPos) {
37+
resetIntelliSenseState(
38+
config.isManualTriggerEnabled,
39+
config.isAutomatedTriggerEnabled,
40+
RecommendationHandler.instance.isValidResponse()
41+
)
42+
}
43+
44+
await RecommendationService.instance.generateRecommendation(client, editor, 'OnDemand', config, undefined)
45+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as vscode from 'vscode'
7+
import { vsCodeState, OnRecommendationAcceptanceEntry } from '../models/model'
8+
import { runtimeLanguageContext } from '../util/runtimeLanguageContext'
9+
import { CodeWhispererTracker } from '../tracker/codewhispererTracker'
10+
import { CodeWhispererCodeCoverageTracker } from '../tracker/codewhispererCodeCoverageTracker'
11+
import { getLogger } from '../../shared/logger/logger'
12+
import { handleExtraBrackets } from '../util/closingBracketUtil'
13+
import { RecommendationHandler } from '../service/recommendationHandler'
14+
import { ReferenceLogViewProvider } from '../service/referenceLogViewProvider'
15+
import { ReferenceHoverProvider } from '../service/referenceHoverProvider'
16+
import path from 'path'
17+
18+
/**
19+
* This function is called when user accepts a intelliSense suggestion or an inline suggestion
20+
*/
21+
export async function onAcceptance(acceptanceEntry: OnRecommendationAcceptanceEntry) {
22+
RecommendationHandler.instance.cancelPaginatedRequest()
23+
/**
24+
* Format document
25+
*/
26+
if (acceptanceEntry.editor) {
27+
const languageContext = runtimeLanguageContext.getLanguageContext(
28+
acceptanceEntry.editor.document.languageId,
29+
path.extname(acceptanceEntry.editor.document.fileName)
30+
)
31+
const start = acceptanceEntry.range.start
32+
const end = acceptanceEntry.range.end
33+
34+
// codewhisperer will be doing editing while formatting.
35+
// formatting should not trigger consoals auto trigger
36+
vsCodeState.isCodeWhispererEditing = true
37+
/**
38+
* Mitigation to right context handling mainly for auto closing bracket use case
39+
*/
40+
try {
41+
await handleExtraBrackets(acceptanceEntry.editor, end, start)
42+
} catch (error) {
43+
getLogger().error(`${error} in handleAutoClosingBrackets`)
44+
}
45+
// move cursor to end of suggestion before doing code format
46+
// after formatting, the end position will still be editor.selection.active
47+
acceptanceEntry.editor.selection = new vscode.Selection(end, end)
48+
49+
vsCodeState.isCodeWhispererEditing = false
50+
CodeWhispererTracker.getTracker().enqueue({
51+
time: new Date(),
52+
fileUrl: acceptanceEntry.editor.document.uri,
53+
originalString: acceptanceEntry.editor.document.getText(new vscode.Range(start, end)),
54+
startPosition: start,
55+
endPosition: end,
56+
requestId: acceptanceEntry.requestId,
57+
sessionId: acceptanceEntry.sessionId,
58+
index: acceptanceEntry.acceptIndex,
59+
triggerType: acceptanceEntry.triggerType,
60+
completionType: acceptanceEntry.completionType,
61+
language: languageContext.language,
62+
})
63+
const insertedCoderange = new vscode.Range(start, end)
64+
CodeWhispererCodeCoverageTracker.getTracker(languageContext.language)?.countAcceptedTokens(
65+
insertedCoderange,
66+
acceptanceEntry.editor.document.getText(insertedCoderange),
67+
acceptanceEntry.editor.document.fileName
68+
)
69+
if (acceptanceEntry.references !== undefined) {
70+
const referenceLog = ReferenceLogViewProvider.getReferenceLog(
71+
acceptanceEntry.recommendation,
72+
acceptanceEntry.references,
73+
acceptanceEntry.editor
74+
)
75+
ReferenceLogViewProvider.instance.addReferenceLog(referenceLog)
76+
ReferenceHoverProvider.instance.addCodeReferences(
77+
acceptanceEntry.recommendation,
78+
acceptanceEntry.references
79+
)
80+
}
81+
}
82+
83+
// at the end of recommendation acceptance, report user decisions and clear recommendations.
84+
RecommendationHandler.instance.reportUserDecisions(acceptanceEntry.acceptIndex)
85+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as vscode from 'vscode'
7+
import * as CodeWhispererConstants from '../models/constants'
8+
import { vsCodeState, OnRecommendationAcceptanceEntry } from '../models/model'
9+
import { runtimeLanguageContext } from '../util/runtimeLanguageContext'
10+
import { CodeWhispererTracker } from '../tracker/codewhispererTracker'
11+
import { CodeWhispererCodeCoverageTracker } from '../tracker/codewhispererCodeCoverageTracker'
12+
import { getLogger } from '../../shared/logger/logger'
13+
import { RecommendationHandler } from '../service/recommendationHandler'
14+
import { sleep } from '../../shared/utilities/timeoutUtils'
15+
import { handleExtraBrackets } from '../util/closingBracketUtil'
16+
import { Commands } from '../../shared/vscode/commands2'
17+
import { isInlineCompletionEnabled } from '../util/commonUtil'
18+
import { ExtContext } from '../../shared/extensions'
19+
import { onAcceptance } from './onAcceptance'
20+
import * as codewhispererClient from '../client/codewhisperer'
21+
import {
22+
CodewhispererCompletionType,
23+
CodewhispererLanguage,
24+
CodewhispererTriggerType,
25+
} from '../../shared/telemetry/telemetry.gen'
26+
import { ReferenceLogViewProvider } from '../service/referenceLogViewProvider'
27+
import { ReferenceHoverProvider } from '../service/referenceHoverProvider'
28+
import { ImportAdderProvider } from '../service/importAdderProvider'
29+
import { session } from '../util/codeWhispererSession'
30+
import path from 'path'
31+
import { RecommendationService } from '../service/recommendationService'
32+
import { Container } from '../service/serviceContainer'
33+
import { telemetry } from '../../shared/telemetry/telemetry'
34+
import { TelemetryHelper } from '../util/telemetryHelper'
35+
import { UserWrittenCodeTracker } from '../tracker/userWrittenCodeTracker'
36+
37+
export const acceptSuggestion = Commands.declare(
38+
'aws.amazonq.accept',
39+
(context: ExtContext) =>
40+
async (
41+
range: vscode.Range,
42+
effectiveRange: vscode.Range,
43+
acceptIndex: number,
44+
recommendation: string,
45+
requestId: string,
46+
sessionId: string,
47+
triggerType: CodewhispererTriggerType,
48+
completionType: CodewhispererCompletionType,
49+
language: CodewhispererLanguage,
50+
references: codewhispererClient.References
51+
) => {
52+
telemetry.record({
53+
traceId: TelemetryHelper.instance.traceId,
54+
})
55+
56+
RecommendationService.instance.incrementAcceptedCount()
57+
const editor = vscode.window.activeTextEditor
58+
await Container.instance.lineAnnotationController.refresh(editor, 'codewhisperer')
59+
const onAcceptanceFunc = isInlineCompletionEnabled() ? onInlineAcceptance : onAcceptance
60+
await onAcceptanceFunc({
61+
editor,
62+
range,
63+
effectiveRange,
64+
acceptIndex,
65+
recommendation,
66+
requestId,
67+
sessionId,
68+
triggerType,
69+
completionType,
70+
language,
71+
references,
72+
})
73+
}
74+
)
75+
/**
76+
* This function is called when user accepts a intelliSense suggestion or an inline suggestion
77+
*/
78+
export async function onInlineAcceptance(acceptanceEntry: OnRecommendationAcceptanceEntry) {
79+
RecommendationHandler.instance.cancelPaginatedRequest()
80+
RecommendationHandler.instance.disposeInlineCompletion()
81+
82+
if (acceptanceEntry.editor) {
83+
await sleep(CodeWhispererConstants.vsCodeCursorUpdateDelay)
84+
const languageContext = runtimeLanguageContext.getLanguageContext(
85+
acceptanceEntry.editor.document.languageId,
86+
path.extname(acceptanceEntry.editor.document.fileName)
87+
)
88+
const start = acceptanceEntry.range.start
89+
const end = acceptanceEntry.editor.selection.active
90+
91+
vsCodeState.isCodeWhispererEditing = true
92+
/**
93+
* Mitigation to right context handling mainly for auto closing bracket use case
94+
*/
95+
try {
96+
// Do not handle extra bracket if there is a right context merge
97+
if (acceptanceEntry.recommendation === session.recommendations[acceptanceEntry.acceptIndex].content) {
98+
await handleExtraBrackets(acceptanceEntry.editor, end, acceptanceEntry.effectiveRange.start)
99+
}
100+
await ImportAdderProvider.instance.onAcceptRecommendation(
101+
acceptanceEntry.editor,
102+
session.recommendations[acceptanceEntry.acceptIndex],
103+
start.line
104+
)
105+
} catch (error) {
106+
getLogger().error(`${error} in handling extra brackets or imports`)
107+
} finally {
108+
vsCodeState.isCodeWhispererEditing = false
109+
}
110+
111+
CodeWhispererTracker.getTracker().enqueue({
112+
time: new Date(),
113+
fileUrl: acceptanceEntry.editor.document.uri,
114+
originalString: acceptanceEntry.editor.document.getText(new vscode.Range(start, end)),
115+
startPosition: start,
116+
endPosition: end,
117+
requestId: acceptanceEntry.requestId,
118+
sessionId: acceptanceEntry.sessionId,
119+
index: acceptanceEntry.acceptIndex,
120+
triggerType: acceptanceEntry.triggerType,
121+
completionType: acceptanceEntry.completionType,
122+
language: languageContext.language,
123+
})
124+
const insertedCoderange = new vscode.Range(start, end)
125+
CodeWhispererCodeCoverageTracker.getTracker(languageContext.language)?.countAcceptedTokens(
126+
insertedCoderange,
127+
acceptanceEntry.editor.document.getText(insertedCoderange),
128+
acceptanceEntry.editor.document.fileName
129+
)
130+
UserWrittenCodeTracker.instance.onQFinishesEdits()
131+
if (acceptanceEntry.references !== undefined) {
132+
const referenceLog = ReferenceLogViewProvider.getReferenceLog(
133+
acceptanceEntry.recommendation,
134+
acceptanceEntry.references,
135+
acceptanceEntry.editor
136+
)
137+
ReferenceLogViewProvider.instance.addReferenceLog(referenceLog)
138+
ReferenceHoverProvider.instance.addCodeReferences(
139+
acceptanceEntry.recommendation,
140+
acceptanceEntry.references
141+
)
142+
}
143+
144+
RecommendationHandler.instance.reportUserDecisions(acceptanceEntry.acceptIndex)
145+
}
146+
}

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,16 @@ export const runningSecurityScan = 'Reviewing project for code issues...'
138138

139139
export const runningFileScan = 'Reviewing current file for code issues...'
140140

141+
export const noSuggestions = 'No suggestions from Amazon Q'
142+
141143
export const noInlineSuggestionsMsg = 'No suggestions from Amazon Q'
142144

143145
export const licenseFilter = 'Amazon Q suggestions were filtered due to reference settings'
144146

147+
/**
148+
* the interval of the background thread invocation, which is triggered by the timer
149+
*/
150+
export const defaultCheckPeriodMillis = 1000 * 60 * 5
145151
/**
146152
* Key bindings JSON file path
147153
*/

0 commit comments

Comments
 (0)