textfiles.ts ×5

Frontier kind: Code frontier

unlabeled · c_01affa7153f0

80 tests · 21989 LOC · 106 files · introduces 0 tests · 575 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
5 ranges575 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2279 ranges21989 lines · 106 files · Browse complete extent
All tests (intent)
80 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 575 introduced LOC across 5 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/services/textfile/common/textfiles.ts 575 introduced LOC · 5 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- textfiles.ts
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 { URI } from '../../../../base/common/uri.js';
7 > import { Event } from '../../../../base/common/event.js';
8 > import { IDisposable } from '../../../../base/common/lifecycle.js';
9 > import { ISaveOptions, IRevertOptions, SaveReason } from '../../../common/editor.js';
10 > import { ReadableStream } from '../../../../base/common/stream.js';
11 > import { IBaseFileStatWithMetadata, IFileStatWithMetadata, IWriteFileOptions, FileOperationError, FileOperationResult, IReadFileStreamOptions, IFileReadLimits } from '../../../../platform/files/common/files.js';
12 > import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
13 > import { ITextEditorModel } from '../../../../editor/common/services/resolverService.js';
14 > import { ITextBufferFactory, ITextModel, ITextSnapshot } from '../../../../editor/common/model.js';
15 > import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from '../../../../base/common/buffer.js';
16 > import { areFunctions, isUndefinedOrNull } from '../../../../base/common/types.js';
17 > import { IWorkingCopy, IWorkingCopySaveEvent } from '../../workingCopy/common/workingCopy.js';
18 > import { IUntitledTextEditorModelManager } from '../../untitled/common/untitledTextEditorService.js';
19 > import { CancellationToken } from '../../../../base/common/cancellation.js';
20 > import { IProgress, IProgressStep } from '../../../../platform/progress/common/progress.js';
21 > import { IFileOperationUndoRedoInfo } from '../../workingCopy/common/workingCopyFileService.js';
22 >
23 > export const ITextFileService = createDecorator<ITextFileService>('textFileService');
24 >
25 > export interface ITextFileService extends IDisposable {
26 >
27 > readonly _serviceBrand: undefined;
28 >
29 > /**
30 > * Access to the manager of text file editor models providing further
31 > * methods to work with them.
32 > */
33 > readonly files: ITextFileEditorModelManager;
34 >
35 > /**
36 > * Access to the manager of untitled text editor models providing further
37 > * methods to work with them.
38 > */
39 > readonly untitled: IUntitledTextEditorModelManager;
40 >
41 > /**
42 > * Helper to determine encoding for resources.
43 > */
44 > readonly encoding: IResourceEncodings;
45 >
46 > /**
47 > * A resource is dirty if it has unsaved changes or is an untitled file not yet saved.
48 > *
49 > * @param resource the resource to check for being dirty
50 > */
51 > isDirty(resource: URI): boolean;
52 >
53 > /**
54 > * Saves the resource.
55 > *
56 > * @param resource the resource to save
57 > * @param options optional save options
58 > * @return Path of the saved resource or undefined if canceled.
59 > */
60 > save(resource: URI, options?: ITextFileSaveOptions): Promise<URI | undefined>;
61 >
62 > /**
63 > * Saves the provided resource asking the user for a file name or using the provided one.
64 > *
65 > * @param resource the resource to save as.
66 > * @param targetResource the optional target to save to.
67 > * @param options optional save options
68 > * @return Path of the saved resource or undefined if canceled.
69 > */
70 > saveAs(resource: URI, targetResource?: URI, options?: ITextFileSaveAsOptions): Promise<URI | undefined>;
71 >
72 > /**
73 > * Reverts the provided resource.
74 > *
75 > * @param resource the resource of the file to revert.
76 > * @param force to force revert even when the file is not dirty
77 > */
78 > revert(resource: URI, options?: IRevertOptions): Promise<void>;
79 >
80 > /**
81 > * Read the contents of a file identified by the resource.
82 > */
83 > read(resource: URI, options?: IReadTextFileOptions): Promise<ITextFileContent>;
84 >
85 > /**
86 > * Read the contents of a file identified by the resource as stream.
87 > */
88 > readStream(resource: URI, options?: IReadTextFileOptions): Promise<ITextFileStreamContent>;
89 >
90 > /**
91 > * Update a file with given contents.
92 > */
93 > write(resource: URI, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<IFileStatWithMetadata>;
94 >
95 > /**
96 > * Create files. If the file exists it will be overwritten with the contents if
97 > * the options enable to overwrite.
98 > */
99 > create(operations: { resource: URI; value?: string | ITextSnapshot; options?: { overwrite?: boolean } }[], undoInfo?: IFileOperationUndoRedoInfo): Promise<readonly IFileStatWithMetadata[]>;
100 >
101 > /**
102 > * Returns the readable that uses the appropriate encoding. This method should
103 > * be used whenever a `string` or `ITextSnapshot` is being persisted to the
104 > * file system.
105 > */
106 > getEncodedReadable(resource: URI | undefined, value: ITextSnapshot, options?: IWriteTextFileOptions): Promise<VSBufferReadable>;
107 > getEncodedReadable(resource: URI | undefined, value: string, options?: IWriteTextFileOptions): Promise<VSBuffer | VSBufferReadable>;
108 > getEncodedReadable(resource: URI | undefined, value?: ITextSnapshot, options?: IWriteTextFileOptions): Promise<VSBufferReadable | undefined>;
109 > getEncodedReadable(resource: URI | undefined, value?: string, options?: IWriteTextFileOptions): Promise<VSBuffer | VSBufferReadable | undefined>;
110 > getEncodedReadable(resource: URI | undefined, value?: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<VSBuffer | VSBufferReadable | undefined>;
111 >
112 > /**
113 > * Returns a stream of strings that uses the appropriate encoding. This method should
114 > * be used whenever a `VSBufferReadableStream` is being loaded from the file system.
115 > *
116 > * Will throw an error if `acceptTextOnly: true` for resources that seem to be binary.
117 > */
118 > getDecodedStream(resource: URI | undefined, value: VSBufferReadableStream, options?: IReadTextFileEncodingOptions): Promise<ReadableStream<string>>;
119 >
120 > /**
121 > * Get the encoding for the provided `resource`. Will try to determine the encoding
122 > * from any existing model for that `resource` and fallback to the configured defaults.
123 > */
124 > getEncoding(resource: URI): string;
125 >
126 > /**
127 > * Get the properties for decoding the provided `resource` based on configuration.
128 > */
129 > resolveDecoding(resource: URI | undefined, options?: IReadTextFileEncodingOptions): Promise<{ preferredEncoding: string; guessEncoding: boolean; candidateGuessEncodings: string[] }>;
130 >
131 > /**
132 > * Get the properties for encoding the provided `resource` based on configuration.
133 > */
134 > resolveEncoding(resource: URI | undefined, options?: IWriteTextFileOptions): Promise<{ encoding: string; addBOM: boolean }>;
135 >
136 > /**
137 > * Given a detected encoding, validate it against the configured encoding options.
138 > */
139 > validateDetectedEncoding(resource: URI | undefined, detectedEncoding: string, options?: IReadTextFileEncodingOptions): Promise<string>;
140 > }
141 >
142 > export interface IReadTextFileEncodingOptions {
143 >
144 > /**
145 > * The optional encoding parameter allows to specify the desired encoding when resolving
146 > * the contents of the file.
147 > */
148 > readonly encoding?: string;
149 >
150 > /**
151 > * The optional guessEncoding parameter allows to guess encoding from content of the file.
152 > */
153 > readonly autoGuessEncoding?: boolean;
154 >
155 > /**
156 > * The optional candidateGuessEncodings parameter limits the allowed encodings to guess from.
157 > */
158 > readonly candidateGuessEncodings?: string[];
159 >
160 > /**
161 > * The optional acceptTextOnly parameter allows to fail this request early if the file
162 > * contents are not textual.
163 > */
164 > readonly acceptTextOnly?: boolean;
165 > }
166 >
167 > export interface IReadTextFileOptions extends IReadTextFileEncodingOptions, IReadFileStreamOptions { }
168 >
169 > export interface IWriteTextFileOptions extends IWriteFileOptions {
170 >
171 > /**
172 > * The encoding to use when updating a file.
173 > */
174 > readonly encoding?: string;
175 >
176 > /**
177 > * Whether to write to the file as elevated (admin) user. When setting this option a prompt will
178 > * ask the user to authenticate as super user.
179 > */
180 > readonly writeElevated?: boolean;
181 > }
182 >
183 > export const enum TextFileOperationResult {
184 > FILE_IS_BINARY
185 > }
186 >
187 > export class TextFileOperationError extends FileOperationError {
188 >
189 > static isTextFileOperationError(obj: unknown): obj is TextFileOperationError {
190 > return obj instanceof Error && !isUndefinedOrNull((obj as TextFileOperationError).textFileOperationResult);
191 > }
192 >
193 > override readonly options?: IReadTextFileOptions & IWriteTextFileOptions;
194 >
195 > constructor(
196 message: string,
197 public textFileOperationResult: TextFileOperationResult,
202 this.options = options;
203 }
204 > } textfiles.ts
205 >
206 > export interface IResourceEncodings {
207 > getPreferredReadEncoding(resource: URI): Promise<IResourceEncoding>;
208 > getPreferredWriteEncoding(resource: URI, preferredEncoding?: string): Promise<IResourceEncoding>;
209 > }
210 >
211 > export interface IResourceEncoding {
212 > readonly encoding: string;
213 > readonly hasBOM: boolean;
214 > }
215 >
216 > /**
217 > * The save error handler can be installed on the text file editor model to install code that executes when save errors occur.
218 > */
219 > export interface ISaveErrorHandler {
220 >
221 > /**
222 > * Called whenever a save fails.
223 > */
224 > onSaveError(error: Error, model: ITextFileEditorModel, options: ITextFileSaveAsOptions): void;
225 > }
226 >
227 > /**
228 > * States the text file editor model can be in.
229 > */
230 > export const enum TextFileEditorModelState {
231 >
232 > /**
233 > * A model is saved.
234 > */
235 > SAVED,
236 >
237 > /**
238 > * A model is dirty.
239 > */
240 > DIRTY,
241 >
242 > /**
243 > * A model is currently being saved but this operation has not completed yet.
244 > */
245 > PENDING_SAVE,
246 >
247 > /**
248 > * A model is in conflict mode when changes cannot be saved because the
249 > * underlying file has changed. Models in conflict mode are always dirty.
250 > */
251 > CONFLICT,
252 >
253 > /**
254 > * A model is in orphan state when the underlying file has been deleted.
255 > */
256 > ORPHAN,
257 >
258 > /**
259 > * Any error that happens during a save that is not causing the CONFLICT state.
260 > * Models in error mode are always dirty.
261 > */
262 > ERROR
263 > }
264 >
265 > export const enum TextFileResolveReason {
266 > EDITOR = 1,
267 > REFERENCE = 2,
268 > OTHER = 3
269 > }
270 >
271 > interface IBaseTextFileContent extends IBaseFileStatWithMetadata {
272 >
273 > /**
274 > * The encoding of the content if known.
275 > */
276 > readonly encoding: string;
277 > }
278 >
279 > export interface ITextFileContent extends IBaseTextFileContent {
280 >
281 > /**
282 > * The content of a text file.
283 > */
284 > readonly value: string;
285 > }
286 >
287 > export interface ITextFileStreamContent extends IBaseTextFileContent {
288 >
289 > /**
290 > * The line grouped content of a text file.
291 > */
292 > readonly value: ITextBufferFactory;
293 > }
294 >
295 > export interface ITextFileEditorModelResolveOrCreateOptions extends ITextFileResolveOptions {
296 >
297 > /**
298 > * The language id to use for the model text content.
299 > */
300 > readonly languageId?: string;
301 >
302 > /**
303 > * The encoding to use when resolving the model text content.
304 > */
305 > readonly encoding?: string;
306 >
307 > /**
308 > * If the model was already resolved before, allows to trigger
309 > * a reload of it to fetch the latest contents.
310 > */
311 > readonly reload?: {
312 >
313 > /**
314 > * Controls whether the reload happens in the background
315 > * or whether `resolve` will await the reload to happen.
316 > */
317 > readonly async: boolean;
318 > };
319 > }
320 >
321 > export interface ITextFileSaveEvent extends ITextFileEditorModelSaveEvent {
322 >
323 > /**
324 > * The model that was saved.
325 > */
326 > readonly model: ITextFileEditorModel;
327 > }
328 >
329 > export interface ITextFileResolveEvent {
330 >
331 > /**
332 > * The model that was resolved.
333 > */
334 > readonly model: ITextFileEditorModel;
335 >
336 > /**
337 > * The reason why the model was resolved.
338 > */
339 > readonly reason: TextFileResolveReason;
340 > }
341 >
342 > export interface ITextFileSaveParticipantContext {
343 >
344 > /**
345 > * The reason why the save was triggered.
346 > */
347 > readonly reason: SaveReason;
348 >
349 > /**
350 > * Only applies to when a text file was saved as, for
351 > * example when starting with untitled and saving. This
352 > * provides access to the initial resource the text
353 > * file had before.
354 > */
355 > readonly savedFrom?: URI;
356 > }
357 >
358 > export interface ITextFileSaveParticipant {
359 >
360 > /**
361 > * The ordinal number which determines the order of participation.
362 > * Lower values mean to participant sooner
363 > */
364 > readonly ordinal?: number;
365 >
366 > /**
367 > * Participate in a save of a model. Allows to change the model
368 > * before it is being saved to disk.
369 > */
370 > participate(
371 > model: ITextFileEditorModel,
372 > context: ITextFileSaveParticipantContext,
373 > progress: IProgress<IProgressStep>,
374 > token: CancellationToken
375 > ): Promise<void>;
376 > }
377 >
378 > export interface ITextFileEditorModelManager {
379 >
380 > readonly onDidCreate: Event<ITextFileEditorModel>;
381 > readonly onDidResolve: Event<ITextFileResolveEvent>;
382 > readonly onDidChangeDirty: Event<ITextFileEditorModel>;
383 > readonly onDidChangeReadonly: Event<ITextFileEditorModel>;
384 > readonly onDidRemove: Event<URI>;
385 > readonly onDidChangeOrphaned: Event<ITextFileEditorModel>;
386 > readonly onDidChangeEncoding: Event<ITextFileEditorModel>;
387 > readonly onDidSaveError: Event<ITextFileEditorModel>;
388 > readonly onDidSave: Event<ITextFileSaveEvent>;
389 > readonly onDidRevert: Event<ITextFileEditorModel>;
390 >
391 > /**
392 > * Access to all text file editor models in memory.
393 > */
394 > readonly models: ITextFileEditorModel[];
395 >
396 > /**
397 > * Allows to configure the error handler that is called on save errors.
398 > */
399 > saveErrorHandler: ISaveErrorHandler;
400 >
401 > /**
402 > * Returns the text file editor model for the provided resource
403 > * or undefined if none.
404 > */
405 > get(resource: URI): ITextFileEditorModel | undefined;
406 >
407 > /**
408 > * Allows to resolve a text file model from disk.
409 > */
410 > resolve(resource: URI, options?: ITextFileEditorModelResolveOrCreateOptions): Promise<ITextFileEditorModel>;
411 >
412 > /**
413 > * Adds a participant for saving text file models.
414 > */
415 > addSaveParticipant(participant: ITextFileSaveParticipant): IDisposable;
416 >
417 > /**
418 > * Runs the registered save participants on the provided model.
419 > */
420 > runSaveParticipants(model: ITextFileEditorModel, context: ITextFileSaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void>;
421 >
422 > /**
423 > * Waits for the model to be ready to be disposed. There may be conditions
424 > * under which the model cannot be disposed, e.g. when it is dirty. Once the
425 > * promise is settled, it is safe to dispose the model.
426 > */
427 > canDispose(model: ITextFileEditorModel): true | Promise<true>;
428 > }
429 >
430 > export interface ITextFileSaveOptions extends ISaveOptions {
431 >
432 > /**
433 > * Save the file with an attempt to unlock it.
434 > */
435 > readonly writeUnlock?: boolean;
436 >
437 > /**
438 > * Save the file with elevated privileges.
439 > *
440 > * Note: This may not be supported in all environments.
441 > */
442 > readonly writeElevated?: boolean;
443 >
444 > /**
445 > * Allows to write to a file even if it has been modified on disk.
446 > */
447 > readonly ignoreModifiedSince?: boolean;
448 >
449 > /**
450 > * If set, will bubble up the error to the caller instead of handling it.
451 > */
452 > readonly ignoreErrorHandler?: boolean;
453 > }
454 >
455 > export interface ITextFileSaveAsOptions extends ITextFileSaveOptions {
456 >
457 > /**
458 > * Optional URI of the resource the text file is saved from if known.
459 > */
460 > readonly from?: URI;
461 >
462 > /**
463 > * Optional URI to use as suggested file path to save as.
464 > */
465 > readonly suggestedTarget?: URI;
466 > }
467 >
468 > export interface ITextFileResolveOptions {
469 >
470 > /**
471 > * The contents to use for the model if known. If not
472 > * provided, the contents will be retrieved from the
473 > * underlying resource or backup if present.
474 > */
475 > readonly contents?: ITextBufferFactory;
476 >
477 > /**
478 > * Go to file bypassing any cache of the model if any.
479 > */
480 > readonly forceReadFromFile?: boolean;
481 >
482 > /**
483 > * Allow to resolve a model even if we think it is a binary file.
484 > */
485 > readonly allowBinary?: boolean;
486 >
487 > /**
488 > * Context why the model is being resolved.
489 > */
490 > readonly reason?: TextFileResolveReason;
491 >
492 > /**
493 > * If provided, the size of the file will be checked against the limits
494 > * and an error will be thrown if any limit is exceeded.
495 > */
496 > readonly limits?: IFileReadLimits;
497 > }
498 >
499 > export const enum EncodingMode {
500 >
501 > /**
502 > * Instructs the encoding support to encode the object with the provided encoding
503 > */
504 > Encode,
505 >
506 > /**
507 > * Instructs the encoding support to decode the object with the provided encoding
508 > */
509 > Decode
510 > }
511 >
512 > export interface IEncodingSupport {
513 >
514 > /**
515 > * Gets the encoding of the object if known.
516 > */
517 > getEncoding(): string | undefined;
518 >
519 > /**
520 > * Sets the encoding for the object for saving.
521 > */
522 > setEncoding(encoding: string, mode: EncodingMode): Promise<void>;
523 > }
524 >
525 > export interface ILanguageSupport {
526 >
527 > /**
528 > * Sets the language id of the object.
529 > */
530 > setLanguageId(languageId: string, source?: string): void;
531 > }
532 >
533 > export interface ITextFileEditorModelSaveEvent extends IWorkingCopySaveEvent {
534 >
535 > /**
536 > * The resolved stat from the save operation.
537 > */
538 > readonly stat: IFileStatWithMetadata;
539 > }
540 >
541 > export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport, ILanguageSupport, IWorkingCopy {
542 >
543 > readonly onDidSave: Event<ITextFileEditorModelSaveEvent>;
544 > readonly onDidSaveError: Event<void>;
545 > readonly onDidChangeOrphaned: Event<void>;
546 > readonly onDidChangeReadonly: Event<void>;
547 > readonly onDidChangeEncoding: Event<void>;
548 >
549 > hasState(state: TextFileEditorModelState): boolean;
550 > joinState(state: TextFileEditorModelState.PENDING_SAVE): Promise<void>;
551 >
552 > updatePreferredEncoding(encoding: string | undefined): void;
553 >
554 > save(options?: ITextFileSaveAsOptions): Promise<boolean>;
555 > revert(options?: IRevertOptions): Promise<void>;
556 >
557 > resolve(options?: ITextFileResolveOptions): Promise<void>;
558 >
559 > isDirty(): this is IResolvedTextFileEditorModel;
560 >
561 > getLanguageId(): string | undefined;
562 >
563 > isResolved(): this is IResolvedTextFileEditorModel;
564 > }
565 >
566 > export function isTextFileEditorModel(model: ITextEditorModel): model is ITextFileEditorModel {
567 const candidate = model as ITextFileEditorModel;
568
569 return areFunctions(candidate.setEncoding, candidate.getEncoding, candidate.save, candidate.revert, candidate.isDirty, candidate.getLanguageId);
570 }
571 > textfiles.ts
572 > export interface IResolvedTextFileEditorModel extends ITextFileEditorModel {
573 >
574 > readonly textEditorModel: ITextModel;
575 >
576 > createSnapshot(): ITextSnapshot;
577 > }
578 >
579 > export function snapshotToString(snapshot: ITextSnapshot): string {
580 const chunks: string[] = [];
581
587 return chunks.join('');
588 }
589 > textfiles.ts
590 > export function stringToSnapshot(value: string): ITextSnapshot {
591 let done = false;
592
603 };
604 }
605 > textfiles.ts
606 > export function toBufferOrReadable(value: string): VSBuffer;
607 > export function toBufferOrReadable(value: ITextSnapshot): VSBufferReadable;
608 > export function toBufferOrReadable(value: string | ITextSnapshot): VSBuffer | VSBufferReadable;
609 > export function toBufferOrReadable(value: string | ITextSnapshot | undefined): VSBuffer | VSBufferReadable | undefined;
610 > export function toBufferOrReadable(value: string | ITextSnapshot | undefined): VSBuffer | VSBufferReadable | undefined {
611 if (typeof value === 'undefined') {
612 return undefined;