Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompt/node/documentContext.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type * as vscode from 'vscode';
7
import { TextDocumentSnapshot } from '../../../platform/editing/common/textDocumentSnapshot';
8
import { ILanguage, getLanguage } from '../../../util/common/languages';
9
import { findLast } from '../../../util/vs/base/common/arraysFind';
10
import { Mutable } from '../../../util/vs/base/common/types';
11
import { ChatRequestEditorData, ChatRequestNotebookData, Range, Selection } from '../../../vscodeTypes';
12
import { CopilotInteractiveEditorResponse } from '../../inlineChat/node/promptCraftingTypes';
13
import { Turn } from '../common/conversation';
14
15
export interface IDocumentContext {
16
readonly document: TextDocumentSnapshot;
17
readonly fileIndentInfo: vscode.FormattingOptions | undefined;
18
readonly language: ILanguage;
19
readonly wholeRange: vscode.Range;
20
readonly selection: vscode.Selection;
21
}
22
23
export namespace IDocumentContext {
24
export function fromEditor(editor: vscode.TextEditor, wholeRange?: vscode.Range): IDocumentContext {
25
const { options, document, selection, visibleRanges } = editor;
26
const docSnapshot = TextDocumentSnapshot.create(document);
27
const fileIndentInfo = {
28
insertSpaces: options.insertSpaces as boolean,
29
tabSize: options.tabSize as number,
30
};
31
const language = getLanguage(docSnapshot);
32
if (!wholeRange) {
33
if (visibleRanges.length === 1) {
34
wholeRange = visibleRanges[0];
35
} else if (visibleRanges.length > 1) {
36
wholeRange = visibleRanges[0].union(visibleRanges[visibleRanges.length - 1]);
37
} else {
38
wholeRange = selection;
39
}
40
}
41
return {
42
document: docSnapshot, fileIndentInfo, language, selection, wholeRange
43
};
44
45
}
46
47
export function fromTextDocument(document: vscode.TextDocument, selection: vscode.Selection, wholeRange?: vscode.Range): IDocumentContext {
48
const docSnapshot = TextDocumentSnapshot.create(document);
49
const language = getLanguage(docSnapshot);
50
if (!wholeRange) {
51
wholeRange = selection;
52
}
53
return {
54
document: docSnapshot, fileIndentInfo: undefined, language, selection, wholeRange
55
};
56
}
57
58
export function inferDocumentContext(request: vscode.ChatRequest, activeEditor: vscode.TextEditor | undefined, previousTurns: Turn[]): IDocumentContext | undefined {
59
60
let result: Mutable<IDocumentContext> | undefined;
61
62
if (request.location2 instanceof ChatRequestEditorData) {
63
const { document, wholeRange, selection } = request.location2;
64
const docSnapshot = TextDocumentSnapshot.create(document);
65
result = {
66
document: docSnapshot,
67
language: getLanguage(document),
68
wholeRange,
69
selection,
70
fileIndentInfo: undefined
71
};
72
73
} else if (request.location2 instanceof ChatRequestNotebookData) {
74
const { cell } = request.location2;
75
const cellSnapshot = TextDocumentSnapshot.create(cell);
76
result = {
77
document: cellSnapshot,
78
language: getLanguage(cell),
79
wholeRange: new Range(0, 0, 0, 0),
80
selection: new Selection(0, 0, 0, 0),
81
fileIndentInfo: undefined
82
};
83
84
} else if (activeEditor) {
85
result = IDocumentContext.fromEditor(activeEditor);
86
}
87
88
if (result) {
89
const lastTurnWithInlineResponse = findLast(previousTurns, turn => Boolean(turn.getMetadata(CopilotInteractiveEditorResponse)));
90
const data = lastTurnWithInlineResponse?.getMetadata(CopilotInteractiveEditorResponse);
91
if (data && data.store && data.store.lastDocumentContent === result.document.getText()) {
92
result.wholeRange = data.store.lastWholeRange;
93
}
94
}
95
96
// DEFAULT - use the active editor's indent settings if none are set yet and if the editor and context document match
97
if (activeEditor && activeEditor?.document.uri.toString() === result?.document.uri.toString() && !result.fileIndentInfo) {
98
result.fileIndentInfo = {
99
insertSpaces: activeEditor.options.insertSpaces as boolean,
100
tabSize: activeEditor.options.tabSize as number,
101
};
102
}
103
104
return result;
105
}
106
}
107
108