Skip to content

Commit 88b9113

Browse files
committed
chore: merge branch 'master' into feat/shortcut
2 parents d5208bc + 2fb0926 commit 88b9113

31 files changed

+1373
-75
lines changed

package-lock.json

Lines changed: 9 additions & 9 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": "Let Enter invoke auto completion more consistently"
4+
}
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": "Use documentChangeEvent as auto trigger condition"
4+
}

packages/amazonq/src/app/inline/EditRendering/imageRenderer.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ export async function showEdits(
2929
const { svgImage, startLine, newCode, origionalCodeHighlightRange } =
3030
await svgGenerationService.generateDiffSvg(currentFile, item.insertText as string)
3131

32+
// TODO: To investigate why it fails and patch [generateDiffSvg]
33+
if (newCode.length === 0) {
34+
getLogger('nextEditPrediction').warn('not able to apply provided edit suggestion, skip rendering')
35+
return
36+
}
37+
3238
if (svgImage) {
3339
// display the SVG image
3440
await displaySvgDecoration(

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,12 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
241241
return []
242242
}
243243

244+
const isAutoTrigger = context.triggerKind === InlineCompletionTriggerKind.Automatic
245+
if (isAutoTrigger && !CodeSuggestionsState.instance.isSuggestionsEnabled()) {
246+
// return early when suggestions are disabled with auto trigger
247+
return []
248+
}
249+
244250
// yield event loop to let the document listen catch updates
245251
await sleep(1)
246252
// prevent user deletion invoking auto trigger
@@ -254,12 +260,6 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
254260
try {
255261
const t0 = performance.now()
256262
vsCodeState.isRecommendationsActive = true
257-
const isAutoTrigger = context.triggerKind === InlineCompletionTriggerKind.Automatic
258-
if (isAutoTrigger && !CodeSuggestionsState.instance.isSuggestionsEnabled()) {
259-
// return early when suggestions are disabled with auto trigger
260-
return []
261-
}
262-
263263
// handling previous session
264264
const prevSession = this.sessionManager.getActiveSession()
265265
const prevSessionId = prevSession?.sessionId
@@ -335,7 +335,8 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
335335
context,
336336
token,
337337
isAutoTrigger,
338-
getAllRecommendationsOptions
338+
getAllRecommendationsOptions,
339+
this.documentEventListener.getLastDocumentChangeEvent(document.uri.fsPath)?.event
339340
)
340341
// get active item from session for displaying
341342
const items = this.sessionManager.getActiveRecommendation()
@@ -433,7 +434,6 @@ ${itemLog}
433434
}
434435
item.range = new Range(cursorPosition, cursorPosition)
435436
itemsMatchingTypeahead.push(item)
436-
ImportAdderProvider.instance.onShowRecommendation(document, cursorPosition.line, item)
437437
}
438438
}
439439

@@ -457,6 +457,7 @@ ${itemLog}
457457
return []
458458
}
459459

460+
this.sessionManager.updateCodeReferenceAndImports()
460461
// suggestions returned here will be displayed on screen
461462
return itemsMatchingTypeahead as InlineCompletionItem[]
462463
} catch (e) {

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ export class DocumentEventListener {
2121
this.lastDocumentChangeEventMap.clear()
2222
}
2323
this.lastDocumentChangeEventMap.set(e.document.uri.fsPath, { event: e, timestamp: performance.now() })
24+
// The VS Code provideInlineCompletionCallback may not trigger when Enter is pressed, especially in Python files
25+
// manually make this trigger. In case of duplicate, the provideInlineCompletionCallback is already debounced
26+
if (this.isEnter(e) && vscode.window.activeTextEditor) {
27+
void vscode.commands.executeCommand('editor.action.inlineSuggest.trigger')
28+
}
2429
}
2530
})
2631
}
@@ -47,4 +52,18 @@ export class DocumentEventListener {
4752
this.documentChangeListener.dispose()
4853
}
4954
}
55+
56+
private isEnter(e: vscode.TextDocumentChangeEvent): boolean {
57+
if (e.contentChanges.length !== 1) {
58+
return false
59+
}
60+
const str = e.contentChanges[0].text
61+
if (str.length === 0) {
62+
return false
63+
}
64+
return (
65+
(str.startsWith('\r\n') && str.substring(2).trim() === '') ||
66+
(str[0] === '\n' && str.substring(1).trim() === '')
67+
)
68+
}
5069
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5+
import * as vscode from 'vscode'
56
import {
67
InlineCompletionListWithReferences,
78
InlineCompletionWithReferencesParams,
89
inlineCompletionWithReferencesRequestType,
10+
TextDocumentContentChangeEvent,
911
} from '@aws/language-server-runtimes/protocol'
1012
import { CancellationToken, InlineCompletionContext, Position, TextDocument } from 'vscode'
1113
import { LanguageClient } from 'vscode-languageclient'
@@ -40,17 +42,28 @@ export class RecommendationService {
4042
context: InlineCompletionContext,
4143
token: CancellationToken,
4244
isAutoTrigger: boolean,
43-
options: GetAllRecommendationsOptions = { emitTelemetry: true, showUi: true }
45+
options: GetAllRecommendationsOptions = { emitTelemetry: true, showUi: true },
46+
documentChangeEvent?: vscode.TextDocumentChangeEvent
4447
) {
4548
// Record that a regular request is being made
4649
this.cursorUpdateRecorder?.recordCompletionRequest()
50+
const documentChangeParams = documentChangeEvent
51+
? {
52+
textDocument: {
53+
uri: document.uri.toString(),
54+
version: document.version,
55+
},
56+
contentChanges: documentChangeEvent.contentChanges.map((x) => x as TextDocumentContentChangeEvent),
57+
}
58+
: undefined
4759

4860
let request: InlineCompletionWithReferencesParams = {
4961
textDocument: {
5062
uri: document.uri.toString(),
5163
},
5264
position,
5365
context,
66+
documentChangeParams: documentChangeParams,
5467
}
5568
if (options.editsStreakToken) {
5669
request = { ...request, partialResultToken: options.editsStreakToken }

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

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
*/
55
import * as vscode from 'vscode'
66
import { InlineCompletionItemWithReferences } from '@aws/language-server-runtimes-types'
7-
import { FileDiagnostic, getDiagnosticsOfCurrentFile } from 'aws-core-vscode/codewhisperer'
7+
import {
8+
FileDiagnostic,
9+
getDiagnosticsOfCurrentFile,
10+
ImportAdderProvider,
11+
ReferenceInlineProvider,
12+
} from 'aws-core-vscode/codewhisperer'
813

914
// TODO: add more needed data to the session interface
1015
export interface CodeWhispererSession {
@@ -25,7 +30,7 @@ export class SessionManager {
2530
private activeSession?: CodeWhispererSession
2631
private _acceptedSuggestionCount: number = 0
2732
private _refreshedSessions = new Set<string>()
28-
33+
private _currentSuggestionIndex = 0
2934
constructor() {}
3035

3136
public startSession(
@@ -45,6 +50,7 @@ export class SessionManager {
4550
firstCompletionDisplayLatency,
4651
diagnosticsBeforeAccept,
4752
}
53+
this._currentSuggestionIndex = 0
4854
}
4955

5056
public closeSession() {
@@ -86,6 +92,8 @@ export class SessionManager {
8692

8793
public clear() {
8894
this.activeSession = undefined
95+
this._currentSuggestionIndex = 0
96+
this.clearReferenceInlineHintsAndImportHints()
8997
}
9098

9199
// re-render the session ghost text to display paginated responses once per completed session
@@ -103,4 +111,60 @@ export class SessionManager {
103111
this._refreshedSessions.add(this.activeSession.sessionId)
104112
}
105113
}
114+
115+
public onNextSuggestion() {
116+
if (this.activeSession?.suggestions && this.activeSession?.suggestions.length > 0) {
117+
this._currentSuggestionIndex = (this._currentSuggestionIndex + 1) % this.activeSession.suggestions.length
118+
this.updateCodeReferenceAndImports()
119+
}
120+
}
121+
122+
public onPrevSuggestion() {
123+
if (this.activeSession?.suggestions && this.activeSession.suggestions.length > 0) {
124+
this._currentSuggestionIndex =
125+
(this._currentSuggestionIndex - 1 + this.activeSession.suggestions.length) %
126+
this.activeSession.suggestions.length
127+
this.updateCodeReferenceAndImports()
128+
}
129+
}
130+
131+
private clearReferenceInlineHintsAndImportHints() {
132+
ReferenceInlineProvider.instance.removeInlineReference()
133+
ImportAdderProvider.instance.clear()
134+
}
135+
136+
// Ideally use this API handleDidShowCompletionItem
137+
// https://github.com/microsoft/vscode/blob/main/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts#L83
138+
updateCodeReferenceAndImports() {
139+
try {
140+
this.clearReferenceInlineHintsAndImportHints()
141+
if (
142+
this.activeSession?.suggestions &&
143+
this.activeSession.suggestions[this._currentSuggestionIndex] &&
144+
this.activeSession.suggestions.length > 0
145+
) {
146+
const reference = this.activeSession.suggestions[this._currentSuggestionIndex].references
147+
const insertText = this.activeSession.suggestions[this._currentSuggestionIndex].insertText
148+
if (reference && reference.length > 0) {
149+
const insertTextStr =
150+
typeof insertText === 'string' ? insertText : (insertText.value ?? String(insertText))
151+
152+
ReferenceInlineProvider.instance.setInlineReference(
153+
this.activeSession.startPosition.line,
154+
insertTextStr,
155+
reference
156+
)
157+
}
158+
if (vscode.window.activeTextEditor) {
159+
ImportAdderProvider.instance.onShowRecommendation(
160+
vscode.window.activeTextEditor.document,
161+
this.activeSession.startPosition.line,
162+
this.activeSession.suggestions[this._currentSuggestionIndex]
163+
)
164+
}
165+
}
166+
} catch {
167+
// do nothing as this is not critical path
168+
}
169+
}
106170
}

packages/amazonq/src/extension.ts

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

6-
import { Auth, AuthUtils, CredentialsStore, LoginManager, initializeAuth } from 'aws-core-vscode/auth'
6+
import { AuthUtils, CredentialsStore, LoginManager, initializeAuth } from 'aws-core-vscode/auth'
77
import { activate as activateCodeWhisperer, shutdown as shutdownCodeWhisperer } from 'aws-core-vscode/codewhisperer'
88
import { makeEndpointsProvider, registerGenericCommands } from 'aws-core-vscode'
99
import { CommonAuthWebview } from 'aws-core-vscode/login'
@@ -44,8 +44,8 @@ import * as vscode from 'vscode'
4444
import { registerCommands } from './commands'
4545
import { focusAmazonQPanel } from 'aws-core-vscode/codewhispererChat'
4646
import { activate as activateAmazonqLsp } from './lsp/activation'
47-
import { activate as activateInlineCompletion } from './app/inline/activation'
4847
import { hasGlibcPatch } from './lsp/client'
48+
import { RotatingLogChannel } from './lsp/rotatingLogChannel'
4949

5050
export const amazonQContextPrefix = 'amazonq'
5151

@@ -104,7 +104,12 @@ export async function activateAmazonQCommon(context: vscode.ExtensionContext, is
104104
globals.manifestPaths.endpoints = context.asAbsolutePath(join('resources', 'endpoints.json'))
105105
globals.regionProvider = RegionProvider.fromEndpointsProvider(makeEndpointsProvider())
106106

107-
const qLogChannel = vscode.window.createOutputChannel('Amazon Q Logs', { log: true })
107+
// Create rotating log channel for all Amazon Q logs
108+
const qLogChannel = new RotatingLogChannel(
109+
'Amazon Q Logs',
110+
context,
111+
vscode.window.createOutputChannel('Amazon Q Logs', { log: true })
112+
)
108113
await activateLogger(context, amazonQContextPrefix, qLogChannel)
109114
globals.logOutputChannel = qLogChannel
110115
globals.loginManager = new LoginManager(globals.awsContext, new CredentialsStore())
@@ -113,6 +118,8 @@ export async function activateAmazonQCommon(context: vscode.ExtensionContext, is
113118
getLogger().error('fs.init: invalid env vars found: %O', homeDirLogs)
114119
}
115120

121+
getLogger().info('Rotating logger has been setup')
122+
116123
await activateTelemetry(context, globals.awsContext, Settings.instance, 'Amazon Q For VS Code')
117124

118125
await initializeAuth(globals.loginManager)
@@ -126,17 +133,11 @@ export async function activateAmazonQCommon(context: vscode.ExtensionContext, is
126133

127134
// This contains every lsp agnostic things (auth, security scan, code scan)
128135
await activateCodeWhisperer(extContext as ExtContext)
129-
if (
130-
(Experiments.instance.get('amazonqLSP', true) || Auth.instance.isInternalAmazonUser()) &&
131-
(!isAmazonLinux2() || hasGlibcPatch())
132-
) {
133-
// start the Amazon Q LSP for internal users first
134-
// for AL2, start LSP if glibc patch is found
136+
137+
if (!isAmazonLinux2() || hasGlibcPatch()) {
138+
// Activate Amazon Q LSP for everyone unless they're using AL2 without the glibc patch
135139
await activateAmazonqLsp(context)
136140
}
137-
if (!Experiments.instance.get('amazonqLSPInline', true)) {
138-
await activateInlineCompletion()
139-
}
140141

141142
// Generic extension commands
142143
registerGenericCommands(context, amazonQContextPrefix)

0 commit comments

Comments
 (0)