Skip to content

Commit a8769e7

Browse files
author
Benjamin Pasero
committed
debt - change glob to not require paths.relative anymore
1 parent c8b4dfd commit a8769e7

8 files changed

Lines changed: 69 additions & 85 deletions

File tree

src/vs/base/common/glob.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface IExpression {
1818
export interface IRelativePattern {
1919
base: string;
2020
pattern: string;
21+
pathToRelative(from: string, to: string): string;
2122
}
2223

2324
export function getEmptyExpression(): IExpression {
@@ -338,7 +339,7 @@ function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string |
338339
return null;
339340
}
340341

341-
return parsedPattern(paths.relative(arg2.base, path), basename);
342+
return parsedPattern(paths.normalize(arg2.pathToRelative(arg2.base, path)), basename);
342343
};
343344
}
344345

@@ -480,7 +481,7 @@ export function parse(arg1: string | IExpression | IRelativePattern, options: IG
480481
export function isRelativePattern(obj: any): obj is IRelativePattern {
481482
const rp = obj as IRelativePattern;
482483

483-
return typeof rp.base === 'string' && typeof rp.pattern === 'string';
484+
return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string' && typeof rp.pathToRelative === 'function';
484485
}
485486

486487
/**

src/vs/base/common/paths.ts

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55
'use strict';
66

7-
import { isLinux, isWindows } from 'vs/base/common/platform';
8-
import { fill } from 'vs/base/common/arrays';
9-
import { rtrim, beginsWithIgnoreCase, equalsIgnoreCase } from 'vs/base/common/strings';
7+
import { isWindows } from 'vs/base/common/platform';
8+
import { beginsWithIgnoreCase, equalsIgnoreCase } from 'vs/base/common/strings';
109
import { CharCode } from 'vs/base/common/charCode';
1110

1211
/**
@@ -19,35 +18,6 @@ export const sep = '/';
1918
*/
2019
export const nativeSep = isWindows ? '\\' : '/';
2120

22-
export function relative(from: string, to: string): string {
23-
// ignore trailing slashes
24-
const originalNormalizedFrom = rtrim(normalize(from), sep);
25-
const originalNormalizedTo = rtrim(normalize(to), sep);
26-
27-
// we're assuming here that any non=linux OS is case insensitive
28-
// so we must compare each part in its lowercase form
29-
const normalizedFrom = isLinux ? originalNormalizedFrom : originalNormalizedFrom.toLowerCase();
30-
const normalizedTo = isLinux ? originalNormalizedTo : originalNormalizedTo.toLowerCase();
31-
32-
const fromParts = normalizedFrom.split(sep);
33-
const toParts = normalizedTo.split(sep);
34-
35-
let i = 0, max = Math.min(fromParts.length, toParts.length);
36-
37-
for (; i < max; i++) {
38-
if (fromParts[i] !== toParts[i]) {
39-
break;
40-
}
41-
}
42-
43-
const result = [
44-
...fill(fromParts.length - i, () => '..'),
45-
...originalNormalizedTo.split(sep).slice(i)
46-
];
47-
48-
return result.join(sep);
49-
}
50-
5121
/**
5222
* @returns the directory name of a path.
5323
*/

src/vs/base/test/common/paths.test.ts

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,6 @@ import paths = require('vs/base/common/paths');
99
import platform = require('vs/base/common/platform');
1010

1111
suite('Paths', () => {
12-
test('relative', () => {
13-
assert.equal(paths.relative('/test/api/files/test', '/test/api/files/lib/foo'), '../lib/foo');
14-
assert.equal(paths.relative('far/boo', 'boo/far'), '../../boo/far');
15-
assert.equal(paths.relative('far/boo', 'far/boo'), '');
16-
assert.equal(paths.relative('far/boo', 'far/boo/bar/foo'), 'bar/foo');
17-
18-
if (platform.isWindows) {
19-
assert.equal(paths.relative('C:\\test\\api\\files\\test', 'C:\\test\\api\\files\\lib\\foo'), '../lib/foo');
20-
assert.equal(paths.relative('C:\\', 'C:\\vscode'), 'vscode');
21-
assert.equal(paths.relative('C:\\', 'C:\\vscode\\foo.txt'), 'vscode/foo.txt');
22-
}
23-
24-
// // ignore trailing slashes
25-
assert.equal(paths.relative('/test/api/files/test/', '/test/api/files/lib/foo'), '../lib/foo');
26-
assert.equal(paths.relative('/test/api/files/test', '/test/api/files/lib/foo/'), '../lib/foo');
27-
assert.equal(paths.relative('/test/api/files/test/', '/test/api/files/lib/foo/'), '../lib/foo');
28-
assert.equal(paths.relative('far/boo/', 'boo/far'), '../../boo/far');
29-
assert.equal(paths.relative('far/boo/', 'boo/far/'), '../../boo/far');
30-
assert.equal(paths.relative('far/boo/', 'far/boo'), '');
31-
assert.equal(paths.relative('far/boo', 'far/boo/'), '');
32-
assert.equal(paths.relative('far/boo/', 'far/boo/'), '');
33-
34-
if (platform.isWindows) {
35-
assert.equal(paths.relative('C:\\test\\api\\files\\test\\', 'C:\\test\\api\\files\\lib\\foo'), '../lib/foo');
36-
assert.equal(paths.relative('C:\\test\\api\\files\\test', 'C:\\test\\api\\files\\lib\\foo\\'), '../lib/foo');
37-
assert.equal(paths.relative('C:\\test\\api\\files\\test\\', 'C:\\test\\api\\files\\lib\\foo\\'), '../lib/foo');
38-
}
39-
});
4012

4113
test('dirname', () => {
4214
assert.equal(paths.dirname('foo/bar'), 'foo');

src/vs/base/test/node/glob.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ suite('Glob', () => {
916916
assert(!glob.match(p, 'C:\\DNXConsoleApp\\Program.cs'));
917917
assert(!glob.match(p, 'C:\\other\\DNXConsoleApp\\foo\\Program.ts'));
918918
} else {
919-
let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '**/*.cs' };
919+
let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '**/*.cs', pathToRelative: (from, to) => path.relative(from, to) };
920920
assert(glob.match(p, '/DNXConsoleApp/foo/Program.cs'));
921921
assert(glob.match(p, '/DNXConsoleApp/foo/bar/Program.cs'));
922922
assert(!glob.match(p, '/DNXConsoleApp/foo/Program.ts'));
@@ -934,7 +934,7 @@ suite('Glob', () => {
934934
assert(!glob.match(p, 'C:\\DNXConsoleApp\\Program.cs'));
935935
assert(!glob.match(p, 'C:\\other\\DNXConsoleApp\\foo\\Program.ts'));
936936
} else {
937-
let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '*.cs' };
937+
let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: '*.cs', pathToRelative: (from, to) => path.relative(from, to) };
938938
assert(glob.match(p, '/DNXConsoleApp/foo/Program.cs'));
939939
assert(!glob.match(p, '/DNXConsoleApp/foo/bar/Program.cs'));
940940
assert(!glob.match(p, '/DNXConsoleApp/foo/Program.ts'));
@@ -949,7 +949,7 @@ suite('Glob', () => {
949949
assert(glob.match(p, 'C:\\DNXConsoleApp\\foo\\something\\Program.cs'));
950950
assert(!glob.match(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'));
951951
} else {
952-
let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: 'something/*.cs' };
952+
let p: glob.IRelativePattern = { base: '/DNXConsoleApp/foo', pattern: 'something/*.cs', pathToRelative: (from, to) => path.relative(from, to) };
953953
assert(glob.match(p, '/DNXConsoleApp/foo/something/Program.cs'));
954954
assert(!glob.match(p, '/DNXConsoleApp/foo/Program.cs'));
955955
}

src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { LanguageConfiguration } from 'vs/editor/common/modes/languageConfigurat
2121
import { IHeapService } from './mainThreadHeapService';
2222
import { IModeService } from 'vs/editor/common/services/modeService';
2323
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
24+
import { toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters';
2425

2526
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
2627
export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape {
@@ -58,7 +59,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
5859
// --- outline
5960

6061
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
61-
this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(selector, <modes.DocumentSymbolProvider>{
62+
this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentSymbolProvider>{
6263
provideDocumentSymbols: (model: IReadOnlyModel, token: CancellationToken): Thenable<modes.SymbolInformation[]> => {
6364
return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri));
6465
}
@@ -85,7 +86,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
8586
provider.onDidChange = emitter.event;
8687
}
8788

88-
this._registrations[handle] = modes.CodeLensProviderRegistry.register(selector, provider);
89+
this._registrations[handle] = modes.CodeLensProviderRegistry.register(toLanguageSelector(selector), provider);
8990
return undefined;
9091
}
9192

@@ -100,7 +101,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
100101
// --- declaration
101102

102103
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
103-
this._registrations[handle] = modes.DefinitionProviderRegistry.register(selector, <modes.DefinitionProvider>{
104+
this._registrations[handle] = modes.DefinitionProviderRegistry.register(toLanguageSelector(selector), <modes.DefinitionProvider>{
104105
provideDefinition: (model, position, token): Thenable<modes.Definition> => {
105106
return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position));
106107
}
@@ -109,7 +110,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
109110
}
110111

111112
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
112-
this._registrations[handle] = modes.ImplementationProviderRegistry.register(selector, <modes.ImplementationProvider>{
113+
this._registrations[handle] = modes.ImplementationProviderRegistry.register(toLanguageSelector(selector), <modes.ImplementationProvider>{
113114
provideImplementation: (model, position, token): Thenable<modes.Definition> => {
114115
return wireCancellationToken(token, this._proxy.$provideImplementation(handle, model.uri, position));
115116
}
@@ -118,7 +119,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
118119
}
119120

120121
$registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
121-
this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(selector, <modes.TypeDefinitionProvider>{
122+
this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(toLanguageSelector(selector), <modes.TypeDefinitionProvider>{
122123
provideTypeDefinition: (model, position, token): Thenable<modes.Definition> => {
123124
return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position));
124125
}
@@ -129,7 +130,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
129130
// --- extra info
130131

131132
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
132-
this._registrations[handle] = modes.HoverProviderRegistry.register(selector, <modes.HoverProvider>{
133+
this._registrations[handle] = modes.HoverProviderRegistry.register(toLanguageSelector(selector), <modes.HoverProvider>{
133134
provideHover: (model: IReadOnlyModel, position: EditorPosition, token: CancellationToken): Thenable<modes.Hover> => {
134135
return wireCancellationToken(token, this._proxy.$provideHover(handle, model.uri, position));
135136
}
@@ -140,7 +141,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
140141
// --- occurrences
141142

142143
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
143-
this._registrations[handle] = modes.DocumentHighlightProviderRegistry.register(selector, <modes.DocumentHighlightProvider>{
144+
this._registrations[handle] = modes.DocumentHighlightProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentHighlightProvider>{
144145
provideDocumentHighlights: (model: IReadOnlyModel, position: EditorPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> => {
145146
return wireCancellationToken(token, this._proxy.$provideDocumentHighlights(handle, model.uri, position));
146147
}
@@ -151,7 +152,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
151152
// --- references
152153

153154
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
154-
this._registrations[handle] = modes.ReferenceProviderRegistry.register(selector, <modes.ReferenceProvider>{
155+
this._registrations[handle] = modes.ReferenceProviderRegistry.register(toLanguageSelector(selector), <modes.ReferenceProvider>{
155156
provideReferences: (model: IReadOnlyModel, position: EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> => {
156157
return wireCancellationToken(token, this._proxy.$provideReferences(handle, model.uri, position, context));
157158
}
@@ -162,7 +163,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
162163
// --- quick fix
163164

164165
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
165-
this._registrations[handle] = modes.CodeActionProviderRegistry.register(selector, <modes.CodeActionProvider>{
166+
this._registrations[handle] = modes.CodeActionProviderRegistry.register(toLanguageSelector(selector), <modes.CodeActionProvider>{
166167
provideCodeActions: (model: IReadOnlyModel, range: EditorRange, token: CancellationToken): Thenable<(modes.Command | modes.CodeAction)[]> => {
167168
return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range)));
168169
}
@@ -173,7 +174,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
173174
// --- formatting
174175

175176
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
176-
this._registrations[handle] = modes.DocumentFormattingEditProviderRegistry.register(selector, <modes.DocumentFormattingEditProvider>{
177+
this._registrations[handle] = modes.DocumentFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentFormattingEditProvider>{
177178
provideDocumentFormattingEdits: (model: IReadOnlyModel, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
178179
return wireCancellationToken(token, this._proxy.$provideDocumentFormattingEdits(handle, model.uri, options));
179180
}
@@ -182,7 +183,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
182183
}
183184

184185
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
185-
this._registrations[handle] = modes.DocumentRangeFormattingEditProviderRegistry.register(selector, <modes.DocumentRangeFormattingEditProvider>{
186+
this._registrations[handle] = modes.DocumentRangeFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentRangeFormattingEditProvider>{
186187
provideDocumentRangeFormattingEdits: (model: IReadOnlyModel, range: EditorRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
187188
return wireCancellationToken(token, this._proxy.$provideDocumentRangeFormattingEdits(handle, model.uri, range, options));
188189
}
@@ -191,7 +192,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
191192
}
192193

193194
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise<any> {
194-
this._registrations[handle] = modes.OnTypeFormattingEditProviderRegistry.register(selector, <modes.OnTypeFormattingEditProvider>{
195+
this._registrations[handle] = modes.OnTypeFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.OnTypeFormattingEditProvider>{
195196

196197
autoFormatTriggerCharacters,
197198

@@ -227,7 +228,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
227228
// --- rename
228229

229230
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
230-
this._registrations[handle] = modes.RenameProviderRegistry.register(selector, <modes.RenameProvider>{
231+
this._registrations[handle] = modes.RenameProviderRegistry.register(toLanguageSelector(selector), <modes.RenameProvider>{
231232
provideRenameEdits: (model: IReadOnlyModel, position: EditorPosition, newName: string, token: CancellationToken): Thenable<modes.WorkspaceEdit> => {
232233
return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName));
233234
}
@@ -239,7 +240,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
239240

240241
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): TPromise<any> {
241242

242-
this._registrations[handle] = modes.SuggestRegistry.register(selector, <modes.ISuggestSupport>{
243+
this._registrations[handle] = modes.SuggestRegistry.register(toLanguageSelector(selector), <modes.ISuggestSupport>{
243244
triggerCharacters,
244245
provideCompletionItems: (model: IReadOnlyModel, position: EditorPosition, context: modes.SuggestContext, token: CancellationToken): Thenable<modes.ISuggestResult> => {
245246
return wireCancellationToken(token, this._proxy.$provideCompletionItems(handle, model.uri, position, context)).then(result => {
@@ -263,7 +264,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
263264
// --- parameter hints
264265

265266
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any> {
266-
this._registrations[handle] = modes.SignatureHelpProviderRegistry.register(selector, <modes.SignatureHelpProvider>{
267+
this._registrations[handle] = modes.SignatureHelpProviderRegistry.register(toLanguageSelector(selector), <modes.SignatureHelpProvider>{
267268

268269
signatureHelpTriggerCharacters: triggerCharacter,
269270

@@ -278,7 +279,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
278279
// --- links
279280

280281
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
281-
this._registrations[handle] = modes.LinkProviderRegistry.register(selector, <modes.LinkProvider>{
282+
this._registrations[handle] = modes.LinkProviderRegistry.register(toLanguageSelector(selector), <modes.LinkProvider>{
282283
provideLinks: (model, token) => {
283284
return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideDocumentLinks(handle, model.uri)));
284285
},
@@ -293,7 +294,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
293294

294295
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
295296
const proxy = this._proxy;
296-
this._registrations[handle] = modes.ColorProviderRegistry.register(selector, <modes.DocumentColorProvider>{
297+
this._registrations[handle] = modes.ColorProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentColorProvider>{
297298
provideDocumentColors: (model, token) => {
298299
return wireCancellationToken(token, proxy.$provideDocumentColors(handle, model.uri))
299300
.then(documentColors => {

src/vs/workbench/api/node/extHost.api.impl.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs';
5555
import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem';
5656
import { FileChangeType, FileType } from 'vs/platform/files/common/files';
5757
import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations';
58+
import { toGlobPattern, toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters';
5859

5960
export interface IExtensionApiFactory {
6061
(extension: IExtensionDescription): typeof vscode;
@@ -216,7 +217,7 @@ export function createApiFactory(
216217
return extHostLanguages.getLanguages();
217218
},
218219
match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number {
219-
return score(selector, <any>document.uri, document.languageId);
220+
return score(toLanguageSelector(selector), <any>document.uri, document.languageId);
220221
},
221222
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
222223
return languageFeatures.registerCodeActionProvider(selector, provider);
@@ -408,7 +409,7 @@ export function createApiFactory(
408409
return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
409410
},
410411
findFiles: (include, exclude, maxResults?, token?) => {
411-
return extHostWorkspace.findFiles(include, exclude, maxResults, token);
412+
return extHostWorkspace.findFiles(toGlobPattern(include), toGlobPattern(exclude), maxResults, token);
412413
},
413414
saveAll: (includeUntitled?) => {
414415
return extHostWorkspace.saveAll(includeUntitled);
@@ -417,7 +418,7 @@ export function createApiFactory(
417418
return extHostEditors.applyWorkspaceEdit(edit);
418419
},
419420
createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => {
420-
return extHostFileSystemEvent.createFileSystemWatcher(pattern, ignoreCreate, ignoreChange, ignoreDelete);
421+
return extHostFileSystemEvent.createFileSystemWatcher(toGlobPattern(pattern), ignoreCreate, ignoreChange, ignoreDelete);
421422
},
422423
get textDocuments() {
423424
return extHostDocuments.getAllDocumentData().map(data => data.document);

0 commit comments

Comments
 (0)