Skip to content

Commit b46b9de

Browse files
committed
II of the MarkersProvider class
1 parent 33028c3 commit b46b9de

File tree

5 files changed

+160
-17
lines changed

5 files changed

+160
-17
lines changed

src/vs/workbench/contrib/chat/browser/promptSyntax/contributions/createPromptCommand/utils/createPromptFile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { assert } from '../../../../../../../../base/common/assert.js';
99
import { VSBuffer } from '../../../../../../../../base/common/buffer.js';
1010
import { dirname } from '../../../../../../../../base/common/resources.js';
1111
import { IFileService } from '../../../../../../../../platform/files/common/files.js';
12-
import { isPromptFile, PROMPT_FILE_EXTENSION } from '../../../../../../../../platform/prompts/common/constants.js';
1312
import { ICommandService } from '../../../../../../../../platform/commands/common/commands.js';
13+
import { isPromptFile, PROMPT_FILE_EXTENSION } from '../../../../../../../../platform/prompts/common/constants.js';
1414

1515
/**
1616
* Options for the {@link createPromptFile} utility.
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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 { assert } from '../../../../../../base/common/assert.js';
7+
import { ITextModel } from '../../../../../../editor/common/model.js';
8+
import { assertDefined } from '../../../../../../base/common/types.js';
9+
import { Disposable } from '../../../../../../base/common/lifecycle.js';
10+
import { IPromptsService } from '../../../common/promptSyntax/service/types.js';
11+
import { IPromptFileReference } from '../../../common/promptSyntax/parsers/types.js';
12+
import { TextModelPromptParser } from '../../../common/promptSyntax/parsers/textModelPromptParser.js';
13+
import { IMarkerData, IMarkerService, MarkerSeverity } from '../../../../../../platform/markers/common/markers.js';
14+
import { FailedToResolveContentsStream, NotPromptFile, ParseError, RecursiveReference } from '../../../common/promptFileReferenceErrors.js';
15+
16+
/**
17+
* TODO: @legomushroom
18+
*/
19+
const MARKERS_OWNER_ID = 'reusable-prompts-syntax';
20+
21+
/**
22+
* TODO: @legomushroom
23+
*/
24+
// TODO: @lego - move under /common
25+
export class MarkersProvider extends Disposable {
26+
/**
27+
* TODO: @legomushroom
28+
*/
29+
private readonly parser: TextModelPromptParser;
30+
31+
constructor(
32+
private readonly editor: ITextModel,
33+
@IMarkerService private readonly markerService: IMarkerService,
34+
@IPromptsService private readonly promptsService: IPromptsService,
35+
) {
36+
super();
37+
38+
this.parser = this.promptsService
39+
.getSyntaxParserFor(this.editor)
40+
.onUpdate(this.updateMarkers.bind(this))
41+
.onDispose(this.dispose.bind(this));
42+
43+
// TODO @legomushroom - uncomment?
44+
// this.updateMarkers();
45+
}
46+
47+
/**
48+
* TODO: @legomushroom
49+
*/
50+
private async updateMarkers() {
51+
// ensure that parsing process is settled
52+
await this.parser.allSettled();
53+
54+
// clean up all previously added markers
55+
this.markerService.remove(MARKERS_OWNER_ID, [this.editor.uri]);
56+
57+
const markers: IMarkerData[] = [];
58+
for (const link of this.parser.allReferences) {
59+
const { errorCondition, linkRange } = link;
60+
61+
if (!errorCondition || !linkRange) {
62+
continue;
63+
}
64+
65+
// the `NotPromptFile` error is allowed because we allow users
66+
// to include non-prompt file links in the prompt files
67+
// note! this check also handles the `FolderReference` error
68+
if (errorCondition instanceof NotPromptFile) {
69+
continue;
70+
}
71+
72+
markers.push(toMarker(link));
73+
}
74+
75+
this.markerService.changeOne(
76+
MARKERS_OWNER_ID,
77+
this.editor.uri,
78+
markers,
79+
);
80+
}
81+
}
82+
83+
/**
84+
* TODO: @legomushroom
85+
*/
86+
// TODO: @legomushroom - add @throws info
87+
const toMarker = (
88+
link: IPromptFileReference,
89+
): IMarkerData => {
90+
const { errorCondition, linkRange } = link;
91+
92+
// a sanity check because this function must be
93+
// used only if these attributes are present
94+
assertDefined(
95+
errorCondition,
96+
'Error condition must to be defined.',
97+
);
98+
assertDefined(
99+
linkRange,
100+
'Link range must to be defined.',
101+
);
102+
assert(
103+
!(errorCondition instanceof NotPromptFile),
104+
'Error must not be of "not prompt file" type.',
105+
);
106+
107+
// `FailedToResolveContentsStream` error check takes into account the `OpenFailed` error too
108+
const severity = (errorCondition instanceof FailedToResolveContentsStream)
109+
? MarkerSeverity.Error
110+
: MarkerSeverity.Warning;
111+
112+
return {
113+
message: getErrorMessage(errorCondition),
114+
severity,
115+
...linkRange,
116+
};
117+
};
118+
119+
/**
120+
* TODO: @legomushroom
121+
*/
122+
// TODO: @legomushroom - add @throws info
123+
// TODO: @legomushroom - localize or reuse existing messages
124+
const getErrorMessage = (
125+
error: ParseError,
126+
): string => {
127+
// a sanity check because this function must be
128+
// used only if error has correct type
129+
assert(
130+
!(error instanceof NotPromptFile),
131+
'Error must not be of "not prompt file" type.',
132+
);
133+
134+
// `FailedToResolveContentsStream` error takes into account the `OpenFailed` error too
135+
if (error instanceof FailedToResolveContentsStream) {
136+
return `The file '${error.uri.fsPath}' is not found.`;
137+
}
138+
139+
if (error instanceof RecursiveReference) {
140+
return 'The file contains recursive child reference that will be ignored.';
141+
}
142+
143+
return `An unexpected error occurred: ${error.message}`;
144+
};

src/vs/workbench/contrib/chat/common/promptFileReferenceErrors.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,36 +41,36 @@ export abstract class ParseError extends Error {
4141
}
4242

4343
/**
44-
* A generic error for failing to resolve prompt contents stream.
44+
* Base resolve error class used when file reference resolution fails.
4545
*/
46-
export class FailedToResolveContentsStream extends ParseError {
47-
public override errorType = 'FailedToResolveContentsStream';
46+
export abstract class ResolveError extends ParseError {
47+
public abstract override errorType: string;
4848

4949
constructor(
5050
public readonly uri: URI,
51-
public readonly originalError: unknown,
52-
message: string = `Failed to resolve prompt contents stream for '${uri.toString()}': ${originalError}.`,
51+
message?: string,
52+
options?: ErrorOptions,
5353
) {
54-
super(message);
54+
super(message, options);
5555
}
5656
}
5757

58-
5958
/**
60-
* Base resolve error class used when file reference resolution fails.
59+
* A generic error for failing to resolve prompt contents stream.
6160
*/
62-
export abstract class ResolveError extends ParseError {
63-
public abstract override errorType: string;
61+
export class FailedToResolveContentsStream extends ResolveError {
62+
public override errorType = 'FailedToResolveContentsStream';
6463

6564
constructor(
66-
public readonly uri: URI,
67-
message?: string,
68-
options?: ErrorOptions,
65+
uri: URI,
66+
public readonly originalError: unknown,
67+
message: string = `Failed to resolve prompt contents stream for '${uri.toString()}': ${originalError}.`,
6968
) {
70-
super(message, options);
69+
super(uri, message);
7170
}
7271
}
7372

73+
7474
/**
7575
* Error that reflects the case when attempt to open target file fails.
7676
*/

src/vs/workbench/contrib/chat/common/promptSyntax/parsers/basePromptParser.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,6 @@ export abstract class BasePromptParser<T extends IPromptContentsProvider> extend
457457
return undefined;
458458
}
459459

460-
461460
// if the first error is the error of the root reference,
462461
// then return it as an `error` otherwise use `warning`
463462
const [firstError, ...restErrors] = errors;

src/vs/workbench/contrib/chat/common/promptSyntax/utils/promptFilesLocator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { IWorkspaceContextService } from '../../../../../../platform/workspace/c
1313
import { IConfigurationService } from '../../../../../../platform/configuration/common/configuration.js';
1414

1515
/**
16-
* Class to locate prompt files.
16+
* Utility class to locate prompt files.
1717
*/
1818
export class PromptFilesLocator {
1919
constructor(

0 commit comments

Comments
 (0)