Skip to content

Commit 112adb3

Browse files
authored
Merge pull request #7336 from Hweinstock/feature/flare-mega2
feat(amazonq): inline suggestions are served by language server.
2 parents 344bdb6 + 275b6ca commit 112adb3

File tree

103 files changed

+2630
-10660
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+2630
-10660
lines changed

package-lock.json

Lines changed: 181 additions & 77 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
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": "Support chat in AL2 aarch64"
4+
}

packages/amazonq/src/app/chat/activation.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,14 @@
66
import * as vscode from 'vscode'
77
import { ExtensionContext } from 'vscode'
88
import { telemetry } from 'aws-core-vscode/telemetry'
9-
import { AuthUtil, CodeWhispererSettings } from 'aws-core-vscode/codewhisperer'
10-
import { Commands, placeholder, funcUtil } from 'aws-core-vscode/shared'
9+
import { AuthUtil } from 'aws-core-vscode/codewhisperer'
10+
import { Commands, placeholder } from 'aws-core-vscode/shared'
1111
import * as amazonq from 'aws-core-vscode/amazonq'
1212

1313
export async function activate(context: ExtensionContext) {
1414
const appInitContext = amazonq.DefaultAmazonQAppInitContext.instance
1515
await amazonq.TryChatCodeLensProvider.register(appInitContext.onDidChangeAmazonQVisibility.event)
1616

17-
const setupLsp = funcUtil.debounce(async () => {
18-
void amazonq.LspController.instance.trySetupLsp(context, {
19-
startUrl: AuthUtil.instance.connection?.startUrl,
20-
maxIndexSize: CodeWhispererSettings.instance.getMaxIndexSize(),
21-
isVectorIndexEnabled: false,
22-
})
23-
}, 5000)
24-
2517
context.subscriptions.push(
2618
amazonq.focusAmazonQChatWalkthrough.register(),
2719
amazonq.walkthroughInlineSuggestionsExample.register(),
@@ -37,7 +29,6 @@ export async function activate(context: ExtensionContext) {
3729
void vscode.env.openExternal(vscode.Uri.parse(amazonq.amazonQHelpUrl))
3830
})
3931

40-
void setupLsp()
4132
void setupAuthNotification()
4233
}
4334

packages/amazonq/src/app/inline/activation.ts

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,26 @@
66
import vscode from 'vscode'
77
import {
88
AuthUtil,
9-
CodeSuggestionsState,
10-
CodeWhispererCodeCoverageTracker,
119
CodeWhispererConstants,
12-
CodeWhispererSettings,
13-
ConfigurationEntry,
14-
DefaultCodeWhispererClient,
15-
invokeRecommendation,
1610
isInlineCompletionEnabled,
17-
KeyStrokeHandler,
18-
RecommendationHandler,
1911
runtimeLanguageContext,
2012
TelemetryHelper,
2113
UserWrittenCodeTracker,
2214
vsCodeState,
2315
} from 'aws-core-vscode/codewhisperer'
24-
import { Commands, getLogger, globals, sleep } from 'aws-core-vscode/shared'
16+
import { globals, sleep } from 'aws-core-vscode/shared'
2517

2618
export async function activate() {
27-
const codewhispererSettings = CodeWhispererSettings.instance
28-
const client = new DefaultCodeWhispererClient()
29-
3019
if (isInlineCompletionEnabled()) {
3120
await setSubscriptionsforInlineCompletion()
3221
await AuthUtil.instance.setVscodeContextProps()
3322
}
3423

35-
function getAutoTriggerStatus(): boolean {
36-
return CodeSuggestionsState.instance.isSuggestionsEnabled()
37-
}
38-
39-
async function getConfigEntry(): Promise<ConfigurationEntry> {
40-
const isShowMethodsEnabled: boolean =
41-
vscode.workspace.getConfiguration('editor').get('suggest.showMethods') || false
42-
const isAutomatedTriggerEnabled: boolean = getAutoTriggerStatus()
43-
const isManualTriggerEnabled: boolean = true
44-
const isSuggestionsWithCodeReferencesEnabled = codewhispererSettings.isSuggestionsWithCodeReferencesEnabled()
45-
46-
// TODO:remove isManualTriggerEnabled
47-
return {
48-
isShowMethodsEnabled,
49-
isManualTriggerEnabled,
50-
isAutomatedTriggerEnabled,
51-
isSuggestionsWithCodeReferencesEnabled,
52-
}
53-
}
54-
5524
async function setSubscriptionsforInlineCompletion() {
56-
RecommendationHandler.instance.subscribeSuggestionCommands()
57-
5825
/**
5926
* Automated trigger
6027
*/
6128
globals.context.subscriptions.push(
62-
vscode.window.onDidChangeActiveTextEditor(async (editor) => {
63-
await RecommendationHandler.instance.onEditorChange()
64-
}),
65-
vscode.window.onDidChangeWindowState(async (e) => {
66-
await RecommendationHandler.instance.onFocusChange()
67-
}),
68-
vscode.window.onDidChangeTextEditorSelection(async (e) => {
69-
await RecommendationHandler.instance.onCursorChange(e)
70-
}),
7129
vscode.workspace.onDidChangeTextDocument(async (e) => {
7230
const editor = vscode.window.activeTextEditor
7331
if (!editor) {
@@ -80,7 +38,6 @@ export async function activate() {
8038
return
8139
}
8240

83-
CodeWhispererCodeCoverageTracker.getTracker(e.document.languageId)?.countTotalTokens(e)
8441
UserWrittenCodeTracker.instance.onTextDocumentChange(e)
8542
/**
8643
* Handle this keystroke event only when
@@ -105,19 +62,6 @@ export async function activate() {
10562
* Then this event can be processed by our code.
10663
*/
10764
await sleep(CodeWhispererConstants.vsCodeCursorUpdateDelay)
108-
if (!RecommendationHandler.instance.isSuggestionVisible()) {
109-
await KeyStrokeHandler.instance.processKeyStroke(e, editor, client, await getConfigEntry())
110-
}
111-
}),
112-
// manual trigger
113-
Commands.register({ id: 'aws.amazonq.invokeInlineCompletion', autoconnect: true }, async () => {
114-
invokeRecommendation(
115-
vscode.window.activeTextEditor as vscode.TextEditor,
116-
client,
117-
await getConfigEntry()
118-
).catch((e) => {
119-
getLogger().error('invokeRecommendation failed: %s', (e as Error).message)
120-
})
12165
})
12266
)
12367
}

packages/amazonq/src/app/inline/completion.ts

Lines changed: 106 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ import {
88
InlineCompletionContext,
99
InlineCompletionItem,
1010
InlineCompletionItemProvider,
11-
InlineCompletionList,
1211
Position,
1312
TextDocument,
1413
commands,
1514
languages,
1615
Disposable,
1716
window,
1817
TextEditor,
18+
InlineCompletionTriggerKind,
19+
Range,
1920
} from 'vscode'
2021
import { LanguageClient } from 'vscode-languageclient'
2122
import {
@@ -27,37 +28,63 @@ import { RecommendationService } from './recommendationService'
2728
import {
2829
CodeWhispererConstants,
2930
ReferenceHoverProvider,
30-
ReferenceInlineProvider,
3131
ReferenceLogViewProvider,
3232
ImportAdderProvider,
33+
CodeSuggestionsState,
34+
vsCodeState,
35+
inlineCompletionsDebounceDelay,
36+
noInlineSuggestionsMsg,
37+
ReferenceInlineProvider,
3338
} from 'aws-core-vscode/codewhisperer'
39+
import { InlineGeneratingMessage } from './inlineGeneratingMessage'
40+
import { LineTracker } from './stateTracker/lineTracker'
41+
import { InlineTutorialAnnotation } from './tutorials/inlineTutorialAnnotation'
42+
import { TelemetryHelper } from './telemetryHelper'
43+
import { getLogger } from 'aws-core-vscode/shared'
44+
import { debounce, messageUtils } from 'aws-core-vscode/utils'
3445

3546
export class InlineCompletionManager implements Disposable {
3647
private disposable: Disposable
3748
private inlineCompletionProvider: AmazonQInlineCompletionItemProvider
3849
private languageClient: LanguageClient
3950
private sessionManager: SessionManager
4051
private recommendationService: RecommendationService
52+
private lineTracker: LineTracker
53+
private incomingGeneratingMessage: InlineGeneratingMessage
54+
private inlineTutorialAnnotation: InlineTutorialAnnotation
4155
private readonly logSessionResultMessageName = 'aws/logInlineCompletionSessionResults'
4256

43-
constructor(languageClient: LanguageClient) {
57+
constructor(
58+
languageClient: LanguageClient,
59+
sessionManager: SessionManager,
60+
lineTracker: LineTracker,
61+
inlineTutorialAnnotation: InlineTutorialAnnotation
62+
) {
4463
this.languageClient = languageClient
45-
this.sessionManager = new SessionManager()
46-
this.recommendationService = new RecommendationService(this.sessionManager)
64+
this.sessionManager = sessionManager
65+
this.lineTracker = lineTracker
66+
this.incomingGeneratingMessage = new InlineGeneratingMessage(this.lineTracker)
67+
this.recommendationService = new RecommendationService(this.sessionManager, this.incomingGeneratingMessage)
68+
this.inlineTutorialAnnotation = inlineTutorialAnnotation
4769
this.inlineCompletionProvider = new AmazonQInlineCompletionItemProvider(
4870
languageClient,
4971
this.recommendationService,
50-
this.sessionManager
72+
this.sessionManager,
73+
this.inlineTutorialAnnotation
5174
)
5275
this.disposable = languages.registerInlineCompletionItemProvider(
5376
CodeWhispererConstants.platformLanguageIds,
5477
this.inlineCompletionProvider
5578
)
79+
80+
this.lineTracker.ready()
5681
}
5782

5883
public dispose(): void {
5984
if (this.disposable) {
6085
this.disposable.dispose()
86+
this.incomingGeneratingMessage.dispose()
87+
this.lineTracker.dispose()
6188
}
6289
}
6390

@@ -97,10 +124,21 @@ export class InlineCompletionManager implements Disposable {
97124
)
98125
ReferenceLogViewProvider.instance.addReferenceLog(referenceLog)
99126
ReferenceHoverProvider.instance.addCodeReferences(item.insertText as string, item.references)
127+
128+
// Show codelense for 5 seconds.
129+
ReferenceInlineProvider.instance.setInlineReference(
130+
startLine,
131+
item.insertText as string,
132+
item.references
133+
)
134+
setTimeout(() => {
135+
ReferenceInlineProvider.instance.removeInlineReference()
136+
}, 5000)
100137
}
101138
if (item.mostRelevantMissingImports?.length) {
102139
await ImportAdderProvider.instance.onAcceptRecommendation(editor, item, startLine)
103140
}
141+
this.sessionManager.incrementSuggestionCount()
104142
}
105143
commands.registerCommand('aws.amazonq.acceptInline', onInlineAcceptance)
106144

@@ -130,38 +168,6 @@ export class InlineCompletionManager implements Disposable {
130168
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
131169
}
132170
commands.registerCommand('aws.amazonq.rejectCodeSuggestion', onInlineRejection)
133-
134-
/*
135-
We have to overwrite the prev. and next. commands because the inlineCompletionProvider only contained the current item
136-
To show prev. and next. recommendation we need to re-register a new provider with the previous or next item
137-
*/
138-
139-
const swapProviderAndShow = async () => {
140-
await commands.executeCommand('editor.action.inlineSuggest.hide')
141-
this.disposable.dispose()
142-
this.disposable = languages.registerInlineCompletionItemProvider(
143-
CodeWhispererConstants.platformLanguageIds,
144-
new AmazonQInlineCompletionItemProvider(
145-
this.languageClient,
146-
this.recommendationService,
147-
this.sessionManager,
148-
false
149-
)
150-
)
151-
await commands.executeCommand('editor.action.inlineSuggest.trigger')
152-
}
153-
154-
const prevCommandHandler = async () => {
155-
this.sessionManager.decrementActiveIndex()
156-
await swapProviderAndShow()
157-
}
158-
commands.registerCommand('editor.action.inlineSuggest.showPrevious', prevCommandHandler)
159-
160-
const nextCommandHandler = async () => {
161-
this.sessionManager.incrementActiveIndex()
162-
await swapProviderAndShow()
163-
}
164-
commands.registerCommand('editor.action.inlineSuggest.showNext', nextCommandHandler)
165171
}
166172
}
167173

@@ -170,52 +176,82 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
170176
private readonly languageClient: LanguageClient,
171177
private readonly recommendationService: RecommendationService,
172178
private readonly sessionManager: SessionManager,
173-
private readonly isNewSession: boolean = true
179+
private readonly inlineTutorialAnnotation: InlineTutorialAnnotation
174180
) {}
175181

176-
async provideInlineCompletionItems(
182+
provideInlineCompletionItems = debounce(
183+
this._provideInlineCompletionItems.bind(this),
184+
inlineCompletionsDebounceDelay,
185+
true
186+
)
187+
188+
private async _provideInlineCompletionItems(
177189
document: TextDocument,
178190
position: Position,
179191
context: InlineCompletionContext,
180192
token: CancellationToken
181-
): Promise<InlineCompletionItem[] | InlineCompletionList> {
182-
if (this.isNewSession) {
183-
// make service requests if it's a new session
193+
): Promise<InlineCompletionItem[]> {
194+
try {
195+
vsCodeState.isRecommendationsActive = true
196+
const isAutoTrigger = context.triggerKind === InlineCompletionTriggerKind.Automatic
197+
if (isAutoTrigger && !CodeSuggestionsState.instance.isSuggestionsEnabled()) {
198+
// return early when suggestions are disabled with auto trigger
199+
return []
200+
}
201+
202+
// tell the tutorial that completions has been triggered
203+
await this.inlineTutorialAnnotation.triggered(context.triggerKind)
204+
TelemetryHelper.instance.setInvokeSuggestionStartTime()
205+
TelemetryHelper.instance.setTriggerType(context.triggerKind)
206+
184207
await this.recommendationService.getAllRecommendations(
185208
this.languageClient,
186209
document,
187210
position,
188211
context,
189212
token
190213
)
191-
}
192-
// get active item from session for displaying
193-
const items = this.sessionManager.getActiveRecommendation()
194-
const session = this.sessionManager.getActiveSession()
195-
if (!session || !items.length) {
196-
return []
197-
}
198-
const editor = window.activeTextEditor
199-
for (const item of items) {
200-
item.command = {
201-
command: 'aws.amazonq.acceptInline',
202-
title: 'On acceptance',
203-
arguments: [
204-
session.sessionId,
205-
item,
206-
editor,
207-
session.requestStartTime,
208-
position.line,
209-
session.firstCompletionDisplayLatency,
210-
],
214+
// get active item from session for displaying
215+
const items = this.sessionManager.getActiveRecommendation()
216+
const session = this.sessionManager.getActiveSession()
217+
const editor = window.activeTextEditor
218+
219+
// Show message to user when manual invoke fails to produce results.
220+
if (items.length === 0 && context.triggerKind === InlineCompletionTriggerKind.Invoke) {
221+
void messageUtils.showTimedMessage(noInlineSuggestionsMsg, 2000)
211222
}
212-
ReferenceInlineProvider.instance.setInlineReference(
213-
position.line,
214-
item.insertText as string,
215-
item.references
216-
)
217-
ImportAdderProvider.instance.onShowRecommendation(document, position.line, item)
223+
224+
if (!session || !items.length || !editor) {
225+
getLogger().debug(
226+
`Failed to produce inline suggestion results. Received ${items.length} items from service`
227+
)
228+
return []
229+
}
230+
231+
const cursorPosition = document.validatePosition(position)
232+
for (const item of items) {
233+
item.command = {
234+
command: 'aws.amazonq.acceptInline',
235+
title: 'On acceptance',
236+
arguments: [
237+
session.sessionId,
238+
item,
239+
editor,
240+
session.requestStartTime,
241+
cursorPosition.line,
242+
session.firstCompletionDisplayLatency,
243+
],
244+
}
245+
item.range = new Range(cursorPosition, cursorPosition)
246+
item.insertText = typeof item.insertText === 'string' ? item.insertText : item.insertText.value
247+
ImportAdderProvider.instance.onShowRecommendation(document, cursorPosition.line, item)
248+
}
249+
return items as InlineCompletionItem[]
250+
} catch (e) {
251+
getLogger('amazonqLsp').error('Failed to provide completion items: %O', e)
252+
return []
253+
} finally {
254+
vsCodeState.isRecommendationsActive = false
218255
}
219-
return items as InlineCompletionItem[]
220256
}
221257
}

0 commit comments

Comments
 (0)