mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-28 12:33:35 +01:00
chat: better problems integration (#241276)
chat: allow referencing and dragging in diagnostics - There is a new proposal which adds `ChatReferenceDiagnostic` as a prompt reference type - You can now pick "Problems..." as part of the chat attachment context - You can drag and drop files and individual diagnostics from the Problems view into chat. Previously trying to do this would just attach the file.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.98.0",
|
||||
"distro": "b37092a45bb95e5098cefcf6809fa6973cfd2538",
|
||||
"distro": "18d6e62cad16da70804e341893ae344d5cdcc6ee",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ResourceMap } from '../../../base/common/map.js';
|
||||
import { parse } from '../../../base/common/marshalling.js';
|
||||
import { Schemas } from '../../../base/common/network.js';
|
||||
import { isNative, isWeb } from '../../../base/common/platform.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { URI, UriComponents } from '../../../base/common/uri.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { IDialogService } from '../../dialogs/common/dialogs.js';
|
||||
import { IBaseTextResourceEditorInput, ITextEditorSelection } from '../../editor/common/editor.js';
|
||||
@@ -23,6 +23,7 @@ import { ByteSize, IFileService } from '../../files/common/files.js';
|
||||
import { IInstantiationService, ServicesAccessor } from '../../instantiation/common/instantiation.js';
|
||||
import { extractSelection } from '../../opener/common/opener.js';
|
||||
import { Registry } from '../../registry/common/platform.js';
|
||||
import { IMarker } from '../../markers/common/markers.js';
|
||||
|
||||
|
||||
//#region Editor / Resources DND
|
||||
@@ -30,7 +31,8 @@ import { Registry } from '../../registry/common/platform.js';
|
||||
export const CodeDataTransfers = {
|
||||
EDITORS: 'CodeEditors',
|
||||
FILES: 'CodeFiles',
|
||||
SYMBOLS: 'application/vnd.code.symbols'
|
||||
SYMBOLS: 'application/vnd.code.symbols',
|
||||
MARKERS: 'application/vnd.code.diagnostics',
|
||||
};
|
||||
|
||||
export interface IDraggedResourceEditorInput extends IBaseTextResourceEditorInput {
|
||||
@@ -414,8 +416,12 @@ export interface DocumentSymbolTransferData {
|
||||
kind: number;
|
||||
}
|
||||
|
||||
export function extractSymbolDropData(e: DragEvent): DocumentSymbolTransferData[] {
|
||||
const rawSymbolsData = e.dataTransfer?.getData(CodeDataTransfers.SYMBOLS);
|
||||
function setDataAsJSON(e: DragEvent, kind: string, data: unknown) {
|
||||
e.dataTransfer?.setData(kind, JSON.stringify(data));
|
||||
}
|
||||
|
||||
function getDataAsJSON<T>(e: DragEvent, kind: string, defaultValue: T): T {
|
||||
const rawSymbolsData = e.dataTransfer?.getData(kind);
|
||||
if (rawSymbolsData) {
|
||||
try {
|
||||
return JSON.parse(rawSymbolsData);
|
||||
@@ -424,11 +430,25 @@ export function extractSymbolDropData(e: DragEvent): DocumentSymbolTransferData[
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
export function extractSymbolDropData(e: DragEvent): DocumentSymbolTransferData[] {
|
||||
return getDataAsJSON(e, CodeDataTransfers.SYMBOLS, []);
|
||||
}
|
||||
|
||||
export function fillInSymbolsDragData(symbolsData: readonly DocumentSymbolTransferData[], e: DragEvent): void {
|
||||
e.dataTransfer?.setData(CodeDataTransfers.SYMBOLS, JSON.stringify(symbolsData));
|
||||
setDataAsJSON(e, CodeDataTransfers.SYMBOLS, symbolsData);
|
||||
}
|
||||
|
||||
export type MarkerTransferData = IMarker | { uri: UriComponents };
|
||||
|
||||
export function extractMarkerDropData(e: DragEvent): MarkerTransferData[] | undefined {
|
||||
return getDataAsJSON(e, CodeDataTransfers.MARKERS, undefined);
|
||||
}
|
||||
|
||||
export function fillInMarkersDragData(markerData: MarkerTransferData[], e: DragEvent): void {
|
||||
setDataAsJSON(e, CodeDataTransfers.MARKERS, markerData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,9 @@ const _allApiProposals = {
|
||||
chatReferenceBinaryData: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatReferenceBinaryData.d.ts',
|
||||
},
|
||||
chatReferenceDiagnostic: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatReferenceDiagnostic.d.ts',
|
||||
},
|
||||
chatTab: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatTab.d.ts',
|
||||
},
|
||||
|
||||
@@ -64,6 +64,15 @@ export namespace MarkerSeverity {
|
||||
return _displayStrings[a] || '';
|
||||
}
|
||||
|
||||
const _displayStringsPlural: { [value: number]: string } = Object.create(null);
|
||||
_displayStringsPlural[MarkerSeverity.Error] = localize('sev.errors', "Errors");
|
||||
_displayStringsPlural[MarkerSeverity.Warning] = localize('sev.warnings', "Warnings");
|
||||
_displayStringsPlural[MarkerSeverity.Info] = localize('sev.infos', "Infos");
|
||||
|
||||
export function toStringPlural(a: MarkerSeverity): string {
|
||||
return _displayStringsPlural[a] || '';
|
||||
}
|
||||
|
||||
export function fromSeverity(severity: Severity): MarkerSeverity {
|
||||
switch (severity) {
|
||||
case Severity.Error: return MarkerSeverity.Error;
|
||||
|
||||
@@ -211,7 +211,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostUriOpeners = rpcProtocol.set(ExtHostContext.ExtHostUriOpeners, new ExtHostUriOpeners(rpcProtocol));
|
||||
const extHostProfileContentHandlers = rpcProtocol.set(ExtHostContext.ExtHostProfileContentHandlers, new ExtHostProfileContentHandlers(rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostInteractive, new ExtHostInteractive(rpcProtocol, extHostNotebook, extHostDocumentsAndEditors, extHostCommands, extHostLogService));
|
||||
const extHostChatAgents2 = rpcProtocol.set(ExtHostContext.ExtHostChatAgents2, new ExtHostChatAgents2(rpcProtocol, extHostLogService, extHostCommands, extHostDocuments, extHostLanguageModels));
|
||||
const extHostChatAgents2 = rpcProtocol.set(ExtHostContext.ExtHostChatAgents2, new ExtHostChatAgents2(rpcProtocol, extHostLogService, extHostCommands, extHostDocuments, extHostLanguageModels, extHostDiagnostics));
|
||||
const extHostLanguageModelTools = rpcProtocol.set(ExtHostContext.ExtHostLanguageModelTools, new ExtHostLanguageModelTools(rpcProtocol));
|
||||
const extHostAiRelatedInformation = rpcProtocol.set(ExtHostContext.ExtHostAiRelatedInformation, new ExtHostRelatedInformation(rpcProtocol));
|
||||
const extHostAiEmbeddingVector = rpcProtocol.set(ExtHostContext.ExtHostAiEmbeddingVector, new ExtHostAiEmbeddingVector(rpcProtocol));
|
||||
@@ -1544,6 +1544,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
ChatResultFeedbackKind: extHostTypes.ChatResultFeedbackKind,
|
||||
ChatVariableLevel: extHostTypes.ChatVariableLevel,
|
||||
ChatCompletionItem: extHostTypes.ChatCompletionItem,
|
||||
ChatReferenceDiagnostic: extHostTypes.ChatReferenceDiagnostic,
|
||||
CallHierarchyIncomingCall: extHostTypes.CallHierarchyIncomingCall,
|
||||
CallHierarchyItem: extHostTypes.CallHierarchyItem,
|
||||
CallHierarchyOutgoingCall: extHostTypes.CallHierarchyOutgoingCall,
|
||||
|
||||
@@ -32,6 +32,7 @@ import * as typeConvert from './extHostTypeConverters.js';
|
||||
import * as extHostTypes from './extHostTypes.js';
|
||||
import { isChatViewTitleActionContext } from '../../contrib/chat/common/chatActions.js';
|
||||
import { IChatRelatedFile, IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js';
|
||||
import { ExtHostDiagnostics } from './extHostDiagnostics.js';
|
||||
|
||||
class ChatAgentResponseStream {
|
||||
|
||||
@@ -324,7 +325,8 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _commands: ExtHostCommands,
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _languageModels: ExtHostLanguageModels
|
||||
private readonly _languageModels: ExtHostLanguageModels,
|
||||
private readonly _diagnostics: ExtHostDiagnostics,
|
||||
) {
|
||||
super();
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadChatAgents2);
|
||||
@@ -402,7 +404,7 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
|
||||
const { request, location, history } = await this._createRequest(requestDto, context, detector.extension);
|
||||
|
||||
const model = await this.getModelForRequest(request, detector.extension);
|
||||
const extRequest = typeConvert.ChatAgentRequest.to(request, location, model, isProposedApiEnabled(detector.extension, 'chatReadonlyPromptReference'));
|
||||
const extRequest = typeConvert.ChatAgentRequest.to(request, location, model, isProposedApiEnabled(detector.extension, 'chatReadonlyPromptReference'), this.getDiagnosticsWhenEnabled(detector.extension));
|
||||
|
||||
return detector.provider.provideParticipantDetection(
|
||||
extRequest,
|
||||
@@ -486,7 +488,7 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
|
||||
stream = new ChatAgentResponseStream(agent.extension, request, this._proxy, this._commands.converter, sessionDisposables);
|
||||
|
||||
const model = await this.getModelForRequest(request, agent.extension);
|
||||
const extRequest = typeConvert.ChatAgentRequest.to(request, location, model, isProposedApiEnabled(agent.extension, 'chatReadonlyPromptReference'));
|
||||
const extRequest = typeConvert.ChatAgentRequest.to(request, location, model, isProposedApiEnabled(agent.extension, 'chatReadonlyPromptReference'), this.getDiagnosticsWhenEnabled(agent.extension));
|
||||
inFlightRequest = { requestId: requestDto.requestId, extRequest };
|
||||
this._inFlightRequests.add(inFlightRequest);
|
||||
|
||||
@@ -538,6 +540,13 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
|
||||
}
|
||||
}
|
||||
|
||||
private getDiagnosticsWhenEnabled(extension: Readonly<IRelaxedExtensionDescription>) {
|
||||
if (!isProposedApiEnabled(extension, 'chatReferenceDiagnostic')) {
|
||||
return [];
|
||||
}
|
||||
return this._diagnostics.getDiagnostics();
|
||||
}
|
||||
|
||||
private async prepareHistoryTurns(extension: Readonly<IRelaxedExtensionDescription>, agentId: string, context: { history: IChatAgentHistoryEntryDto[] }): Promise<(vscode.ChatRequestTurn | vscode.ChatResponseTurn)[]> {
|
||||
const res: (vscode.ChatRequestTurn | vscode.ChatResponseTurn)[] = [];
|
||||
|
||||
@@ -551,7 +560,7 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
|
||||
const hasReadonlyProposal = isProposedApiEnabled(extension, 'chatReadonlyPromptReference');
|
||||
const varsWithoutTools = h.request.variables.variables
|
||||
.filter(v => !v.isTool)
|
||||
.map(v => typeConvert.ChatPromptReference.to(v, hasReadonlyProposal));
|
||||
.map(v => typeConvert.ChatPromptReference.to(v, hasReadonlyProposal, this.getDiagnosticsWhenEnabled(extension)));
|
||||
const toolReferences = h.request.variables.variables
|
||||
.filter(v => v.isTool)
|
||||
.map(typeConvert.ChatLanguageModelToolReference.to);
|
||||
|
||||
@@ -2761,7 +2761,7 @@ export namespace ChatResponsePart {
|
||||
}
|
||||
|
||||
export namespace ChatAgentRequest {
|
||||
export function to(request: IChatAgentRequest, location2: vscode.ChatRequestEditorData | vscode.ChatRequestNotebookData | undefined, model: vscode.LanguageModelChat, hasReadonlyProposal: boolean): vscode.ChatRequest {
|
||||
export function to(request: IChatAgentRequest, location2: vscode.ChatRequestEditorData | vscode.ChatRequestNotebookData | undefined, model: vscode.LanguageModelChat, hasReadonlyProposal: boolean, diagnostics: readonly [vscode.Uri, readonly vscode.Diagnostic[]][]): vscode.ChatRequest {
|
||||
const toolReferences = request.variables.variables.filter(v => v.isTool);
|
||||
const variableReferences = request.variables.variables.filter(v => !v.isTool);
|
||||
return {
|
||||
@@ -2770,7 +2770,7 @@ export namespace ChatAgentRequest {
|
||||
attempt: request.attempt ?? 0,
|
||||
enableCommandDetection: request.enableCommandDetection ?? true,
|
||||
isParticipantDetected: request.isParticipantDetected ?? false,
|
||||
references: variableReferences.map(v => ChatPromptReference.to(v, hasReadonlyProposal)),
|
||||
references: variableReferences.map(v => ChatPromptReference.to(v, hasReadonlyProposal, diagnostics)),
|
||||
toolReferences: toolReferences.map(ChatLanguageModelToolReference.to),
|
||||
location: ChatLocation.to(request.location),
|
||||
acceptedConfirmationData: request.acceptedConfirmationData,
|
||||
@@ -2814,19 +2814,48 @@ export namespace ChatLocation {
|
||||
}
|
||||
|
||||
export namespace ChatPromptReference {
|
||||
export function to(variable: IChatRequestVariableEntry, hasReadonlyProposal: boolean): vscode.ChatPromptReference {
|
||||
const value = variable.value;
|
||||
export function to(variable: IChatRequestVariableEntry, hasReadonlyProposal: boolean, diagnostics: readonly [vscode.Uri, readonly vscode.Diagnostic[]][]): vscode.ChatPromptReference {
|
||||
let value: vscode.ChatPromptReference['value'] = variable.value;
|
||||
if (!value) {
|
||||
throw new Error('Invalid value reference');
|
||||
}
|
||||
|
||||
if (isUriComponents(value)) {
|
||||
value = URI.revive(value);
|
||||
} else if (value && typeof value === 'object' && 'uri' in value && 'range' in value && isUriComponents(value.uri)) {
|
||||
value = Location.to(revive(value));
|
||||
} else if (variable.isImage) {
|
||||
value = new types.ChatReferenceBinaryData(
|
||||
variable.mimeType ?? 'image/png',
|
||||
() => Promise.resolve(new Uint8Array(Object.values(variable.value as number[]))),
|
||||
variable.references && URI.isUri(variable.references[0].reference) ? variable.references[0].reference : undefined
|
||||
);
|
||||
} else if (variable.kind === 'diagnostic') {
|
||||
const filterSeverity = variable.filterSeverity && DiagnosticSeverity.to(variable.filterSeverity);
|
||||
const filterUri = variable.filterUri && URI.revive(variable.filterUri).toString();
|
||||
value = new types.ChatReferenceDiagnostic(diagnostics.map(([uri, d]): [vscode.Uri, vscode.Diagnostic[]] => {
|
||||
if (variable.filterUri && uri.toString() !== filterUri) {
|
||||
return [uri, []];
|
||||
}
|
||||
|
||||
return [uri, d.filter(d => {
|
||||
if (filterSeverity && d.severity > filterSeverity) {
|
||||
return false;
|
||||
}
|
||||
if (variable.filterRange && !editorRange.Range.areIntersectingOrTouching(variable.filterRange, Range.from(d.range))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})];
|
||||
}).filter(([, d]) => d.length > 0));
|
||||
}
|
||||
|
||||
return {
|
||||
id: variable.id,
|
||||
name: variable.name,
|
||||
range: variable.range && [variable.range.start, variable.range.endExclusive],
|
||||
value: isUriComponents(value) ? URI.revive(value) :
|
||||
value && typeof value === 'object' && 'uri' in value && 'range' in value && isUriComponents(value.uri) ?
|
||||
Location.to(revive(value)) : variable.isImage ? new types.ChatReferenceBinaryData(variable.mimeType ?? 'image/png', () => Promise.resolve(new Uint8Array(Object.values(value))), variable.references && URI.isUri(variable.references[0].reference) ? variable.references[0].reference : undefined) : value,
|
||||
value,
|
||||
modelDescription: variable.modelDescription,
|
||||
isReadonly: hasReadonlyProposal ? variable.isMarkedReadonly : undefined,
|
||||
};
|
||||
|
||||
@@ -4716,6 +4716,10 @@ export class ChatReferenceBinaryData implements vscode.ChatReferenceBinaryData {
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatReferenceDiagnostic implements vscode.ChatReferenceDiagnostic {
|
||||
constructor(public readonly diagnostics: [vscode.Uri, vscode.Diagnostic[]][]) { }
|
||||
}
|
||||
|
||||
export enum LanguageModelChatMessageRole {
|
||||
User = 1,
|
||||
Assistant = 2,
|
||||
|
||||
@@ -646,18 +646,24 @@ export class ResourceListDnDHandler<T> implements IListDragAndDrop<T> {
|
||||
|
||||
onDragStart(data: IDragAndDropData, originalEvent: DragEvent): void {
|
||||
const resources: URI[] = [];
|
||||
for (const element of (data as ElementsDragAndDropData<T>).elements) {
|
||||
const elements = (data as ElementsDragAndDropData<T>).elements;
|
||||
for (const element of elements) {
|
||||
const resource = this.toResource(element);
|
||||
if (resource) {
|
||||
resources.push(resource);
|
||||
}
|
||||
}
|
||||
this.onWillDragElements(elements, originalEvent);
|
||||
if (resources.length) {
|
||||
// Apply some datatransfer types to allow for dragging the element outside of the application
|
||||
this.instantiationService.invokeFunction(accessor => fillEditorsDragData(accessor, resources, originalEvent));
|
||||
}
|
||||
}
|
||||
|
||||
protected onWillDragElements(elements: readonly T[], originalEvent: DragEvent): void {
|
||||
// noop
|
||||
}
|
||||
|
||||
onDragOver(data: IDragAndDropData, targetElement: T, targetIndex: number, targetSector: ListViewTargetSector | undefined, originalEvent: DragEvent): boolean | ITreeDragOverReaction {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -49,14 +49,14 @@ import { SearchContext } from '../../../search/common/constants.js';
|
||||
import { ChatAgentLocation, IChatAgentService } from '../../common/chatAgents.js';
|
||||
import { ChatContextKeys } from '../../common/chatContextKeys.js';
|
||||
import { IChatEditingService } from '../../common/chatEditingService.js';
|
||||
import { IChatRequestVariableEntry } from '../../common/chatModel.js';
|
||||
import { IChatRequestVariableEntry, IDiagnosticVariableEntryFilterData } from '../../common/chatModel.js';
|
||||
import { ChatRequestAgentPart } from '../../common/chatParserTypes.js';
|
||||
import { IChatVariablesService } from '../../common/chatVariables.js';
|
||||
import { ILanguageModelToolsService } from '../../common/languageModelToolsService.js';
|
||||
import { IChatWidget, IChatWidgetService, IQuickChatService, showChatView, showEditsView } from '../chat.js';
|
||||
import { imageToHash, isImage } from '../chatPasteProviders.js';
|
||||
import { isQuickChat } from '../chatWidget.js';
|
||||
import { createFolderQuickPick } from '../contrib/chatDynamicVariables.js';
|
||||
import { createFolderQuickPick, createMarkersQuickPick } from '../contrib/chatDynamicVariables.js';
|
||||
import { convertBufferToScreenshotVariable, ScreenshotVariableId } from '../contrib/screenshot.js';
|
||||
import { resizeImage } from '../imageUtils.js';
|
||||
import { CHAT_CATEGORY } from './chatActions.js';
|
||||
@@ -75,7 +75,7 @@ export function registerChatContextActions() {
|
||||
*/
|
||||
type IAttachmentQuickPickItem = ICommandVariableQuickPickItem | IQuickAccessQuickPickItem | IToolQuickPickItem |
|
||||
IImageQuickPickItem | IOpenEditorsQuickPickItem | ISearchResultsQuickPickItem |
|
||||
IScreenShotQuickPickItem | IRelatedFilesQuickPickItem | IPromptInstructionsQuickPickItem | IFolderQuickPickItem;
|
||||
IScreenShotQuickPickItem | IRelatedFilesQuickPickItem | IPromptInstructionsQuickPickItem | IFolderQuickPickItem | IDiagnosticsQuickPickItem;
|
||||
|
||||
/**
|
||||
* These are the types that we can get out of the quick pick
|
||||
@@ -103,6 +103,12 @@ function isIFolderSearchResultQuickPickItem(obj: unknown): obj is IFolderResultQ
|
||||
&& (obj as IFolderResultQuickPickItem).kind === 'folder-search-result');
|
||||
}
|
||||
|
||||
function isIDiagnosticsQuickPickItemWithFilter(obj: unknown): obj is IDiagnosticsQuickPickItemWithFilter {
|
||||
return (
|
||||
typeof obj === 'object'
|
||||
&& (obj as IDiagnosticsQuickPickItemWithFilter).kind === 'diagnostic-filter');
|
||||
}
|
||||
|
||||
function isIQuickPickItemWithResource(obj: unknown): obj is IQuickPickItemWithResource {
|
||||
return (
|
||||
typeof obj === 'object'
|
||||
@@ -210,6 +216,19 @@ interface IScreenShotQuickPickItem extends IQuickPickItem {
|
||||
icon?: ThemeIcon;
|
||||
}
|
||||
|
||||
interface IDiagnosticsQuickPickItem extends IQuickPickItem {
|
||||
kind: 'diagnostic';
|
||||
id: string;
|
||||
icon?: ThemeIcon;
|
||||
}
|
||||
|
||||
interface IDiagnosticsQuickPickItemWithFilter extends IQuickPickItem {
|
||||
kind: 'diagnostic-filter';
|
||||
id: string;
|
||||
filter: IDiagnosticVariableEntryFilterData;
|
||||
icon?: ThemeIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick pick item for prompt instructions attachment.
|
||||
*/
|
||||
@@ -499,6 +518,14 @@ export class AttachContextAction extends Action2 {
|
||||
isFile: false,
|
||||
isDirectory: true,
|
||||
});
|
||||
} else if (isIDiagnosticsQuickPickItemWithFilter(pick)) {
|
||||
toAttach.push({
|
||||
id: pick.id,
|
||||
name: pick.label,
|
||||
value: pick.filter,
|
||||
kind: 'diagnostic',
|
||||
...pick.filter,
|
||||
});
|
||||
} else if (isIQuickPickItemWithResource(pick) && pick.resource) {
|
||||
if (/\.(png|jpg|jpeg|bmp|gif|tiff)$/i.test(pick.resource.path)) {
|
||||
// checks if the file is an image
|
||||
@@ -750,6 +777,13 @@ export class AttachContextAction extends Action2 {
|
||||
id: 'folder',
|
||||
});
|
||||
|
||||
quickPickItems.push({
|
||||
kind: 'diagnostic',
|
||||
label: localize('chatContext.diagnstic', 'Problem...'),
|
||||
iconClass: ThemeIcon.asClassName(Codicon.error),
|
||||
id: 'diagnostic'
|
||||
});
|
||||
|
||||
if (widget.location === ChatAgentLocation.Notebook) {
|
||||
quickPickItems.push({
|
||||
kind: 'command',
|
||||
@@ -824,16 +858,33 @@ export class AttachContextAction extends Action2 {
|
||||
}), clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, fileService, textModelService, instantiationService, '', context?.placeholder);
|
||||
}
|
||||
|
||||
private async _showDiagnosticsPick(instantiationService: IInstantiationService): Promise<IDiagnosticsQuickPickItemWithFilter | undefined> {
|
||||
const filter = await instantiationService.invokeFunction(accessor => createMarkersQuickPick(accessor));
|
||||
if (!filter) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
kind: 'diagnostic-filter',
|
||||
id: IDiagnosticVariableEntryFilterData.id(filter),
|
||||
label: IDiagnosticVariableEntryFilterData.label(filter),
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
private _show(quickInputService: IQuickInputService, commandService: ICommandService, widget: IChatWidget, quickChatService: IQuickChatService, quickPickItems: (IChatContextQuickPickItem | QuickPickItem)[] | undefined, clipboardService: IClipboardService, editorService: IEditorService, labelService: ILabelService, viewsService: IViewsService, chatEditingService: IChatEditingService | undefined, hostService: IHostService, fileService: IFileService, textModelService: ITextModelService, instantiationService: IInstantiationService, query: string = '', placeholder?: string) {
|
||||
const providerOptions: AnythingQuickAccessProviderRunOptions = {
|
||||
handleAccept: async (item: IChatContextQuickPickItem, isBackgroundAccept: boolean) => {
|
||||
handleAccept: async (inputItem: IChatContextQuickPickItem, isBackgroundAccept: boolean) => {
|
||||
let item: IChatContextQuickPickItem | undefined = inputItem;
|
||||
if ('kind' in item && item.kind === 'folder') {
|
||||
const folderItem = await this._showFolders(instantiationService);
|
||||
if (!folderItem) {
|
||||
this._show(quickInputService, commandService, widget, quickChatService, quickPickItems, clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, fileService, textModelService, instantiationService, '', placeholder);
|
||||
return;
|
||||
}
|
||||
item = folderItem;
|
||||
item = await this._showFolders(instantiationService);
|
||||
} else if ('kind' in item && item.kind === 'diagnostic') {
|
||||
item = await this._showDiagnosticsPick(instantiationService);
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
this._show(quickInputService, commandService, widget, quickChatService, quickPickItems, clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, fileService, textModelService, instantiationService, '', placeholder);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('prefix' in item) {
|
||||
|
||||
@@ -11,21 +11,23 @@ import { Codicon } from '../../../../base/common/codicons.js';
|
||||
import { IDisposable } from '../../../../base/common/lifecycle.js';
|
||||
import { Mimes } from '../../../../base/common/mime.js';
|
||||
import { basename, joinPath } from '../../../../base/common/resources.js';
|
||||
import { Mutable } from '../../../../base/common/types.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { IRange } from '../../../../editor/common/core/range.js';
|
||||
import { SymbolKinds } from '../../../../editor/common/languages.js';
|
||||
import { ITextModelService } from '../../../../editor/common/services/resolverService.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js';
|
||||
import { CodeDataTransfers, containsDragType, DocumentSymbolTransferData, extractEditorsDropData, extractSymbolDropData, IDraggedResourceEditorInput } from '../../../../platform/dnd/browser/dnd.js';
|
||||
import { CodeDataTransfers, containsDragType, DocumentSymbolTransferData, extractEditorsDropData, extractMarkerDropData, extractSymbolDropData, IDraggedResourceEditorInput, MarkerTransferData } from '../../../../platform/dnd/browser/dnd.js';
|
||||
import { FileType, IFileService, IFileSystemProvider } from '../../../../platform/files/common/files.js';
|
||||
import { MarkerSeverity } from '../../../../platform/markers/common/markers.js';
|
||||
import { IThemeService, Themable } from '../../../../platform/theme/common/themeService.js';
|
||||
import { isUntitledResourceEditorInput } from '../../../common/editor.js';
|
||||
import { EditorInput } from '../../../common/editor/editorInput.js';
|
||||
import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
import { IExtensionService, isProposedApiEnabled } from '../../../services/extensions/common/extensions.js';
|
||||
import { UntitledTextEditorInput } from '../../../services/untitled/common/untitledTextEditorInput.js';
|
||||
import { IChatRequestVariableEntry, ISymbolVariableEntry } from '../common/chatModel.js';
|
||||
import { IChatRequestVariableEntry, IDiagnosticVariableEntry, IDiagnosticVariableEntryFilterData, ISymbolVariableEntry } from '../common/chatModel.js';
|
||||
import { ChatAttachmentModel } from './chatAttachmentModel.js';
|
||||
import { IChatInputStyles } from './chatInputPart.js';
|
||||
import { resizeImage } from './imageUtils.js';
|
||||
@@ -35,7 +37,8 @@ enum ChatDragAndDropType {
|
||||
FILE_EXTERNAL,
|
||||
FOLDER,
|
||||
IMAGE,
|
||||
SYMBOL
|
||||
SYMBOL,
|
||||
MARKER,
|
||||
}
|
||||
|
||||
export class ChatDragAndDrop extends Themable {
|
||||
@@ -169,6 +172,8 @@ export class ChatDragAndDrop extends Themable {
|
||||
return this.extensionService.extensions.some(ext => isProposedApiEnabled(ext, 'chatReferenceBinaryData')) ? ChatDragAndDropType.IMAGE : undefined;
|
||||
} else if (containsDragType(e, CodeDataTransfers.SYMBOLS)) {
|
||||
return ChatDragAndDropType.SYMBOL;
|
||||
} else if (containsDragType(e, CodeDataTransfers.MARKERS)) {
|
||||
return ChatDragAndDropType.MARKER;
|
||||
} else if (containsDragType(e, DataTransfers.FILES)) {
|
||||
return ChatDragAndDropType.FILE_EXTERNAL;
|
||||
} else if (containsDragType(e, DataTransfers.INTERNAL_URI_LIST)) {
|
||||
@@ -193,6 +198,7 @@ export class ChatDragAndDrop extends Themable {
|
||||
case ChatDragAndDropType.FOLDER: return localize('folder', 'Folder');
|
||||
case ChatDragAndDropType.IMAGE: return localize('image', 'Image');
|
||||
case ChatDragAndDropType.SYMBOL: return localize('symbol', 'Symbol');
|
||||
case ChatDragAndDropType.MARKER: return localize('problem', 'Problem');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +230,11 @@ export class ChatDragAndDrop extends Themable {
|
||||
return [];
|
||||
}
|
||||
|
||||
const markerData = extractMarkerDropData(e);
|
||||
if (markerData) {
|
||||
return this.resolveMarkerAttachContext(markerData);
|
||||
}
|
||||
|
||||
if (containsDragType(e, CodeDataTransfers.SYMBOLS)) {
|
||||
const data = extractSymbolDropData(e);
|
||||
return this.resolveSymbolsAttachContext(data);
|
||||
@@ -304,6 +315,33 @@ export class ChatDragAndDrop extends Themable {
|
||||
});
|
||||
}
|
||||
|
||||
private resolveMarkerAttachContext(markers: MarkerTransferData[]): IDiagnosticVariableEntry[] {
|
||||
return markers.map((marker): IDiagnosticVariableEntry => {
|
||||
const filter: Mutable<IDiagnosticVariableEntryFilterData> = {};
|
||||
if (!('severity' in marker)) {
|
||||
filter.filterUri = URI.revive(marker.uri);
|
||||
filter.filterSeverity = MarkerSeverity.Warning;
|
||||
} else {
|
||||
filter.filterUri = URI.revive(marker.resource);
|
||||
filter.filterSeverity = marker.severity;
|
||||
filter.filterRange = {
|
||||
startLineNumber: marker.startLineNumber,
|
||||
startColumn: marker.startColumn,
|
||||
endLineNumber: marker.endLineNumber,
|
||||
endColumn: marker.endColumn
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
kind: 'diagnostic',
|
||||
id: IDiagnosticVariableEntryFilterData.id(filter),
|
||||
name: IDiagnosticVariableEntryFilterData.label(filter),
|
||||
value: filter,
|
||||
...filter,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private setOverlay(target: HTMLElement, type: ChatDragAndDropType | undefined): void {
|
||||
// Remove any previous overlay text
|
||||
this.overlayText?.remove();
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { coalesce } from '../../../../../base/common/arrays.js';
|
||||
import { CancellationToken } from '../../../../../base/common/cancellation.js';
|
||||
import { Codicon } from '../../../../../base/common/codicons.js';
|
||||
import { isCancellationError } from '../../../../../base/common/errors.js';
|
||||
import * as glob from '../../../../../base/common/glob.js';
|
||||
import { IMarkdownString, MarkdownString } from '../../../../../base/common/htmlContent.js';
|
||||
import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';
|
||||
import { ResourceSet } from '../../../../../base/common/map.js';
|
||||
import { basename, dirname, joinPath, relativePath } from '../../../../../base/common/resources.js';
|
||||
import { ThemeIcon } from '../../../../../base/common/themables.js';
|
||||
import { URI } from '../../../../../base/common/uri.js';
|
||||
import { IRange, Range } from '../../../../../editor/common/core/range.js';
|
||||
import { IDecorationOptions } from '../../../../../editor/common/editorCommon.js';
|
||||
@@ -22,20 +26,19 @@ import { FileType, IFileService } from '../../../../../platform/files/common/fil
|
||||
import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
|
||||
import { ILabelService } from '../../../../../platform/label/common/label.js';
|
||||
import { ILogService } from '../../../../../platform/log/common/log.js';
|
||||
import { IMarkerService, MarkerSeverity } from '../../../../../platform/markers/common/markers.js';
|
||||
import { PromptsConfig } from '../../../../../platform/prompts/common/config.js';
|
||||
import { IQuickAccessOptions } from '../../../../../platform/quickinput/common/quickAccess.js';
|
||||
import { IQuickInputService, IQuickPickItem } from '../../../../../platform/quickinput/common/quickInput.js';
|
||||
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from '../../../../../platform/quickinput/common/quickInput.js';
|
||||
import { IUriIdentityService } from '../../../../../platform/uriIdentity/common/uriIdentity.js';
|
||||
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
|
||||
import { getExcludes, ISearchConfiguration, IFileQuery, QueryType, ISearchComplete, ISearchService } from '../../../../services/search/common/search.js';
|
||||
import { getExcludes, IFileQuery, ISearchComplete, ISearchConfiguration, ISearchService, QueryType } from '../../../../services/search/common/search.js';
|
||||
import { ISymbolQuickPickItem } from '../../../search/browser/symbolsQuickAccess.js';
|
||||
import { IDiagnosticVariableEntryFilterData } from '../../common/chatModel.js';
|
||||
import { IChatRequestVariableValue, IDynamicVariable } from '../../common/chatVariables.js';
|
||||
import * as glob from '../../../../../base/common/glob.js';
|
||||
import { IChatWidget } from '../chat.js';
|
||||
import { ChatWidget, IChatWidgetContrib } from '../chatWidget.js';
|
||||
import { ChatFileReference } from './chatDynamicVariables/chatFileReference.js';
|
||||
import { CancellationToken } from '../../../../../base/common/cancellation.js';
|
||||
import { ThemeIcon } from '../../../../../base/common/themables.js';
|
||||
import { Codicon } from '../../../../../base/common/codicons.js';
|
||||
import { PromptsConfig } from '../../../../../platform/prompts/common/config.js';
|
||||
|
||||
export const dynamicVariableDecorationType = 'chat-dynamic-variable';
|
||||
|
||||
@@ -645,3 +648,57 @@ export class AddDynamicVariableAction extends Action2 {
|
||||
}
|
||||
}
|
||||
registerAction2(AddDynamicVariableAction);
|
||||
|
||||
export async function createMarkersQuickPick(accessor: ServicesAccessor): Promise<IDiagnosticVariableEntryFilterData | undefined> {
|
||||
const markers = accessor.get(IMarkerService).read();
|
||||
if (!markers.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uriIdentityService = accessor.get(IUriIdentityService);
|
||||
const labelService = accessor.get(ILabelService);
|
||||
markers.sort((a, b) => uriIdentityService.extUri.compare(a.resource, b.resource) || b.severity - a.severity);
|
||||
|
||||
const severities = new Set<MarkerSeverity>();
|
||||
type MarkerPickItem = IQuickPickItem & { resource?: URI; entry: IDiagnosticVariableEntryFilterData };
|
||||
const items: (MarkerPickItem | IQuickPickSeparator)[] = [];
|
||||
for (const marker of markers) {
|
||||
if (!uriIdentityService.extUri.isEqual(marker.resource, (items.at(-1) as MarkerPickItem)?.resource)) {
|
||||
items.push({ type: 'separator', label: labelService.getUriLabel(marker.resource, { relative: true }) });
|
||||
}
|
||||
|
||||
severities.add(marker.severity);
|
||||
items.push({
|
||||
type: 'item',
|
||||
resource: marker.resource,
|
||||
label: marker.message,
|
||||
description: localize('markers.panel.at.ln.col.number', "[Ln {0}, Col {1}]", '' + marker.startLineNumber, '' + marker.startColumn),
|
||||
entry: { filterUri: marker.resource, filterRange: { startLineNumber: marker.startLineNumber, endLineNumber: marker.endLineNumber, startColumn: marker.startColumn, endColumn: marker.endColumn } }
|
||||
});
|
||||
}
|
||||
|
||||
if (items.length === 2) { // single error in a URI
|
||||
return (items[1] as MarkerPickItem).entry;
|
||||
}
|
||||
|
||||
if (items.length > 2) {
|
||||
if (severities.has(MarkerSeverity.Error)) {
|
||||
items.unshift({ type: 'item', label: localize('markers.panel.allErrors', 'All Errors'), entry: { filterSeverity: MarkerSeverity.Error } });
|
||||
}
|
||||
if (severities.has(MarkerSeverity.Warning)) {
|
||||
items.unshift({ type: 'item', label: localize('markers.panel.allWarnings', 'All Warnings'), entry: { filterSeverity: MarkerSeverity.Warning } });
|
||||
}
|
||||
if (severities.has(MarkerSeverity.Info)) {
|
||||
items.unshift({ type: 'item', label: localize('markers.panel.allInfos', 'All Infos'), entry: { filterSeverity: MarkerSeverity.Info } });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
const quickPick = quickInputService.createQuickPick({ useSeparators: true });
|
||||
quickPick.placeholder = localize('pickAProblem', 'Pick a problem to attach...');
|
||||
quickPick.items = items;
|
||||
|
||||
return quickInputService.pick(items, { canPickMany: false }).then(v => v?.entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import { IRange } from '../../../../editor/common/core/range.js';
|
||||
import { Location, SymbolKind, TextEdit } from '../../../../editor/common/languages.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { ILogService } from '../../../../platform/log/common/log.js';
|
||||
import { MarkerSeverity } from '../../../../platform/markers/common/markers.js';
|
||||
import { ICellEditOperation } from '../../notebook/common/notebookCommon.js';
|
||||
import { ChatAgentLocation, IChatAgentCommand, IChatAgentData, IChatAgentResult, IChatAgentService, IChatWelcomeMessageContent, reviveSerializedAgent } from './chatAgents.js';
|
||||
import { ChatRequestTextPart, IParsedChatRequest, reviveParsedChatRequest } from './chatParserTypes.js';
|
||||
@@ -87,7 +88,39 @@ export interface ILinkVariableEntry extends Omit<IBaseChatRequestVariableEntry,
|
||||
readonly value: URI;
|
||||
}
|
||||
|
||||
export type IChatRequestVariableEntry = IChatRequestImplicitVariableEntry | IChatRequestPasteVariableEntry | ISymbolVariableEntry | ICommandResultVariableEntry | ILinkVariableEntry | IBaseChatRequestVariableEntry;
|
||||
export interface IDiagnosticVariableEntryFilterData {
|
||||
readonly filterUri?: URI;
|
||||
readonly filterSeverity?: MarkerSeverity;
|
||||
readonly filterRange?: IRange;
|
||||
}
|
||||
|
||||
export namespace IDiagnosticVariableEntryFilterData {
|
||||
export function id(data: IDiagnosticVariableEntryFilterData) {
|
||||
return [data.filterUri, data.filterSeverity, data.filterRange?.startLineNumber].join(':');
|
||||
}
|
||||
|
||||
export function label(data: IDiagnosticVariableEntryFilterData) {
|
||||
let labelStr: string;
|
||||
if (data.filterSeverity) {
|
||||
const sev = data.filterRange ? MarkerSeverity.toString(data.filterSeverity) : MarkerSeverity.toStringPlural(data.filterSeverity);
|
||||
labelStr = data.filterUri
|
||||
? localize('chat.attachment.problems.severity', "{0} in {1}", sev, basename(data.filterUri))
|
||||
: localize('chat.attachment.problems.severity2', "All {0}", sev);
|
||||
} else {
|
||||
labelStr = data.filterUri
|
||||
? localize('chat.attachment.problems.severity3', "Problems in {0}", basename(data.filterUri))
|
||||
: localize('chat.attachment.problems.severity4', "All Problems");
|
||||
}
|
||||
|
||||
return labelStr;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IDiagnosticVariableEntry extends Omit<IBaseChatRequestVariableEntry, 'kind'>, IDiagnosticVariableEntryFilterData {
|
||||
readonly kind: 'diagnostic';
|
||||
}
|
||||
|
||||
export type IChatRequestVariableEntry = IChatRequestImplicitVariableEntry | IChatRequestPasteVariableEntry | ISymbolVariableEntry | ICommandResultVariableEntry | ILinkVariableEntry | IBaseChatRequestVariableEntry | IDiagnosticVariableEntry;
|
||||
|
||||
export function isImplicitVariableEntry(obj: IChatRequestVariableEntry): obj is IChatRequestImplicitVariableEntry {
|
||||
return obj.kind === 'implicit';
|
||||
@@ -101,6 +134,10 @@ export function isLinkVariableEntry(obj: IChatRequestVariableEntry): obj is ILin
|
||||
return obj.kind === 'link';
|
||||
}
|
||||
|
||||
export function isDiagnosticsVariableEntry(obj: IChatRequestVariableEntry): obj is IDiagnosticVariableEntry {
|
||||
return obj.kind === 'diagnostic';
|
||||
}
|
||||
|
||||
export function isChatRequestVariableEntry(obj: unknown): obj is IChatRequestVariableEntry {
|
||||
const entry = obj as IChatRequestVariableEntry;
|
||||
return typeof entry === 'object' &&
|
||||
|
||||
@@ -5,57 +5,59 @@
|
||||
|
||||
import './media/markers.css';
|
||||
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import * as dom from '../../../../base/browser/dom.js';
|
||||
import { IAction, Separator } from '../../../../base/common/actions.js';
|
||||
import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';
|
||||
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from '../../../services/editor/common/editorService.js';
|
||||
import { Marker, ResourceMarkers, RelatedInformation, MarkerChangesEvent, MarkersModel, compareMarkersByUri, MarkerElement, MarkerTableItem } from './markersModel.js';
|
||||
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { MarkersFilters, IMarkersFiltersChangeEvent } from './markersViewActions.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import Messages from './messages.js';
|
||||
import { RangeHighlightDecorations } from '../../../browser/codeeditor.js';
|
||||
import { IThemeService } from '../../../../platform/theme/common/themeService.js';
|
||||
import { ICodeEditor } from '../../../../editor/browser/editorBrowser.js';
|
||||
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { Iterable } from '../../../../base/common/iterator.js';
|
||||
import { ITreeElement, ITreeNode, ITreeContextMenuEvent, ITreeRenderer, ITreeEvent } from '../../../../base/browser/ui/tree/tree.js';
|
||||
import { Relay, Event } from '../../../../base/common/event.js';
|
||||
import { WorkbenchObjectTree, IListService, IWorkbenchObjectTreeOptions, IOpenEvent } from '../../../../platform/list/browser/listService.js';
|
||||
import { FilterOptions } from './markersFilterOptions.js';
|
||||
import { IExpression } from '../../../../base/common/glob.js';
|
||||
import { deepClone } from '../../../../base/common/objects.js';
|
||||
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
|
||||
import { FilterData, Filter, VirtualDelegate, ResourceMarkersRenderer, MarkerRenderer, RelatedInformationRenderer, MarkersWidgetAccessibilityProvider, MarkersViewModel } from './markersTreeViewer.js';
|
||||
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
|
||||
import { MenuId } from '../../../../platform/actions/common/actions.js';
|
||||
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
|
||||
import { StandardKeyboardEvent, IKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
|
||||
import { ResourceLabels } from '../../../browser/labels.js';
|
||||
import { IMarkerService, MarkerSeverity } from '../../../../platform/markers/common/markers.js';
|
||||
import { MementoObject, Memento } from '../../../common/memento.js';
|
||||
import { IIdentityProvider, IListVirtualDelegate } from '../../../../base/browser/ui/list/list.js';
|
||||
import { KeyCode } from '../../../../base/common/keyCodes.js';
|
||||
import { IViewPaneOptions, FilterViewPane } from '../../../browser/parts/views/viewPane.js';
|
||||
import { IViewDescriptorService } from '../../../common/views.js';
|
||||
import { IOpenerService, withSelection } from '../../../../platform/opener/common/opener.js';
|
||||
import { IKeyboardEvent, StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
|
||||
import { ActionViewItem } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
|
||||
import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';
|
||||
import { DisposableStore, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
|
||||
import { groupBy } from '../../../../base/common/arrays.js';
|
||||
import { ResourceMap } from '../../../../base/common/map.js';
|
||||
import { EditorResourceAccessor, SideBySideEditor } from '../../../common/editor.js';
|
||||
import { IMarkersView } from './markers.js';
|
||||
import { ResourceListDnDHandler } from '../../../browser/dnd.js';
|
||||
import { IIdentityProvider, IListVirtualDelegate } from '../../../../base/browser/ui/list/list.js';
|
||||
import { ITableContextMenuEvent, ITableEvent } from '../../../../base/browser/ui/table/table.js';
|
||||
import { MarkersTable } from './markersTable.js';
|
||||
import { Markers, MarkersContextKeys, MarkersViewMode } from '../common/markers.js';
|
||||
import { registerNavigableContainer } from '../../../browser/actions/widgetNavigationCommands.js';
|
||||
import { ITreeContextMenuEvent, ITreeElement, ITreeEvent, ITreeNode, ITreeRenderer } from '../../../../base/browser/ui/tree/tree.js';
|
||||
import { IAction, Separator } from '../../../../base/common/actions.js';
|
||||
import { groupBy } from '../../../../base/common/arrays.js';
|
||||
import { Event, Relay } from '../../../../base/common/event.js';
|
||||
import { IExpression } from '../../../../base/common/glob.js';
|
||||
import { Iterable } from '../../../../base/common/iterator.js';
|
||||
import { KeyCode } from '../../../../base/common/keyCodes.js';
|
||||
import { DisposableStore, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
|
||||
import { ResourceMap } from '../../../../base/common/map.js';
|
||||
import { deepClone } from '../../../../base/common/objects.js';
|
||||
import { isDefined } from '../../../../base/common/types.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { ICodeEditor } from '../../../../editor/browser/editorBrowser.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { MenuId } from '../../../../platform/actions/common/actions.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
|
||||
import { fillInMarkersDragData, MarkerTransferData } from '../../../../platform/dnd/browser/dnd.js';
|
||||
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
|
||||
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
|
||||
import { ResultKind } from '../../../../platform/keybinding/common/keybindingResolver.js';
|
||||
import { IListService, IOpenEvent, IWorkbenchObjectTreeOptions, WorkbenchObjectTree } from '../../../../platform/list/browser/listService.js';
|
||||
import { IMarkerService, MarkerSeverity } from '../../../../platform/markers/common/markers.js';
|
||||
import { IOpenerService, withSelection } from '../../../../platform/opener/common/opener.js';
|
||||
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
|
||||
import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';
|
||||
import { IThemeService } from '../../../../platform/theme/common/themeService.js';
|
||||
import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';
|
||||
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
|
||||
import { registerNavigableContainer } from '../../../browser/actions/widgetNavigationCommands.js';
|
||||
import { RangeHighlightDecorations } from '../../../browser/codeeditor.js';
|
||||
import { ResourceListDnDHandler } from '../../../browser/dnd.js';
|
||||
import { ResourceLabels } from '../../../browser/labels.js';
|
||||
import { FilterViewPane, IViewPaneOptions } from '../../../browser/parts/views/viewPane.js';
|
||||
import { EditorResourceAccessor, SideBySideEditor } from '../../../common/editor.js';
|
||||
import { Memento, MementoObject } from '../../../common/memento.js';
|
||||
import { IViewDescriptorService } from '../../../common/views.js';
|
||||
import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from '../../../services/editor/common/editorService.js';
|
||||
import { Markers, MarkersContextKeys, MarkersViewMode } from '../common/markers.js';
|
||||
import { IMarkersView } from './markers.js';
|
||||
import { FilterOptions } from './markersFilterOptions.js';
|
||||
import { compareMarkersByUri, Marker, MarkerChangesEvent, MarkerElement, MarkersModel, MarkerTableItem, RelatedInformation, ResourceMarkers } from './markersModel.js';
|
||||
import { MarkersTable } from './markersTable.js';
|
||||
import { Filter, FilterData, MarkerRenderer, MarkersViewModel, MarkersWidgetAccessibilityProvider, RelatedInformationRenderer, ResourceMarkersRenderer, VirtualDelegate } from './markersTreeViewer.js';
|
||||
import { IMarkersFiltersChangeEvent, MarkersFilters } from './markersViewActions.js';
|
||||
import Messages from './messages.js';
|
||||
|
||||
function createResourceMarkersIterator(resourceMarkers: ResourceMarkers): Iterable<ITreeElement<MarkerElement>> {
|
||||
return Iterable.map(resourceMarkers.markers, m => {
|
||||
@@ -495,18 +497,7 @@ export class MarkersView extends FilterViewPane implements IMarkersView {
|
||||
filter: this.filter,
|
||||
accessibilityProvider: this.widgetAccessibilityProvider,
|
||||
identityProvider: this.widgetIdentityProvider,
|
||||
dnd: this.instantiationService.createInstance(ResourceListDnDHandler, (element) => {
|
||||
if (element instanceof ResourceMarkers) {
|
||||
return element.resource;
|
||||
}
|
||||
if (element instanceof Marker) {
|
||||
return withSelection(element.resource, element.range);
|
||||
}
|
||||
if (element instanceof RelatedInformation) {
|
||||
return withSelection(element.raw.resource, element.raw);
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
dnd: this.instantiationService.createInstance(MarkersListDnDHandler),
|
||||
expandOnlyOnTwistieClick: (e: MarkerElement) => e instanceof Marker && e.relatedInformation.length > 0,
|
||||
overrideStyles: this.getLocationBasedColors().listOverrideStyles,
|
||||
selectionNavigation: true,
|
||||
@@ -1078,3 +1069,40 @@ class MarkersTree extends WorkbenchObjectTree<MarkerElement, FilterData> impleme
|
||||
super.layout(height, width);
|
||||
}
|
||||
}
|
||||
|
||||
class MarkersListDnDHandler extends ResourceListDnDHandler<MarkerElement | MarkerTableItem> {
|
||||
constructor(
|
||||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
super(element => {
|
||||
if (element instanceof MarkerTableItem) {
|
||||
return withSelection(element.resource, element.range);
|
||||
} else if (element instanceof ResourceMarkers) {
|
||||
return element.resource;
|
||||
} else if (element instanceof Marker) {
|
||||
return withSelection(element.resource, element.range);
|
||||
} else if (element instanceof RelatedInformation) {
|
||||
return withSelection(element.raw.resource, element.raw);
|
||||
}
|
||||
return null;
|
||||
}, instantiationService);
|
||||
}
|
||||
|
||||
protected override onWillDragElements(elements: (MarkerElement | MarkerTableItem)[], originalEvent: DragEvent) {
|
||||
const data = elements.map((e): MarkerTransferData | undefined => {
|
||||
if (e instanceof RelatedInformation || e instanceof Marker) {
|
||||
return e.marker;
|
||||
}
|
||||
if (e instanceof ResourceMarkers) {
|
||||
return { uri: e.resource };
|
||||
}
|
||||
return undefined;
|
||||
}).filter(isDefined);
|
||||
|
||||
if (!data.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
fillInMarkersDragData(data, originalEvent);
|
||||
}
|
||||
}
|
||||
|
||||
23
src/vscode-dts/vscode.proposed.chatReferenceDiagnostic.d.ts
vendored
Normal file
23
src/vscode-dts/vscode.proposed.chatReferenceDiagnostic.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
export interface ChatPromptReference {
|
||||
/**
|
||||
* The value of this reference. The `string | Uri | Location` types are used today, but this could expand in the future.
|
||||
*/
|
||||
readonly value: string | Uri | Location | ChatReferenceDiagnostic | unknown;
|
||||
}
|
||||
|
||||
export class ChatReferenceDiagnostic {
|
||||
/**
|
||||
* All attached diagnostics. An array of uri-diagnostics tuples or an empty array.
|
||||
*/
|
||||
readonly diagnostics: [Uri, Diagnostic[]][];
|
||||
|
||||
protected constructor(diagnostics: [Uri, Diagnostic[]][]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user