vscode-json-languageservice 5.1.4 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -1
- package/lib/esm/jsonLanguageService.d.ts +3 -2
- package/lib/esm/jsonLanguageService.js +5 -19
- package/lib/esm/jsonLanguageTypes.d.ts +10 -2
- package/lib/esm/services/jsonCompletion.js +4 -4
- package/lib/esm/services/jsonDocumentSymbols.js +6 -2
- package/lib/esm/services/jsonHover.js +1 -1
- package/lib/esm/services/jsonSchemaService.js +17 -10
- package/lib/esm/services/jsonValidation.js +2 -2
- package/lib/esm/utils/format.js +20 -0
- package/lib/esm/utils/objects.js +3 -3
- package/lib/esm/utils/propertyTree.js +71 -0
- package/lib/esm/utils/sort.js +355 -0
- package/lib/esm/utils/strings.js +1 -1
- package/lib/umd/jsonLanguageService.d.ts +3 -2
- package/lib/umd/jsonLanguageService.js +6 -20
- package/lib/umd/jsonLanguageTypes.d.ts +10 -2
- package/lib/umd/services/jsonCompletion.js +4 -4
- package/lib/umd/services/jsonDocumentSymbols.js +7 -3
- package/lib/umd/services/jsonHover.js +1 -1
- package/lib/umd/services/jsonSchemaService.js +17 -10
- package/lib/umd/services/jsonValidation.js +2 -2
- package/lib/umd/utils/format.js +34 -0
- package/lib/umd/utils/objects.js +3 -3
- package/lib/umd/utils/propertyTree.js +85 -0
- package/lib/umd/utils/sort.js +369 -0
- package/lib/umd/utils/strings.js +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.3.0 / 2023-02-15
|
|
2
|
+
================
|
|
3
|
+
* new API `LanguageService.sort` for sorting all properties in a JSON document
|
|
4
|
+
* new API `SortOptions`
|
|
5
|
+
|
|
6
|
+
5.2.0 / 2023-02-02
|
|
7
|
+
================
|
|
8
|
+
* Added `SchemaConfiguration.folderUri` for folder-specific schema associations
|
|
9
|
+
|
|
10
|
+
5.1.1 / 2022-08/19
|
|
2
11
|
================
|
|
3
12
|
* new type `SchemaDraft`, representing the offical JSON schema draft versions
|
|
4
13
|
* new property `DocumentLanguageSettings.schemaDraft` to specify the schema version to use, if the schema does not contain a `$schema` property
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Thenable, ASTNode, Color, ColorInformation, ColorPresentation, LanguageServiceParams, LanguageSettings, DocumentLanguageSettings, FoldingRange, JSONSchema, SelectionRange, FoldingRangesContext, DocumentSymbolsContext, ColorInformationContext as DocumentColorsContext, TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, FormattingOptions, DocumentSymbol, DefinitionLink, MatchingSchema, JSONLanguageStatus } from './jsonLanguageTypes';
|
|
1
|
+
import { Thenable, ASTNode, Color, ColorInformation, ColorPresentation, LanguageServiceParams, LanguageSettings, DocumentLanguageSettings, FoldingRange, JSONSchema, SelectionRange, FoldingRangesContext, DocumentSymbolsContext, ColorInformationContext as DocumentColorsContext, TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, FormattingOptions, DocumentSymbol, DefinitionLink, MatchingSchema, JSONLanguageStatus, SortOptions } from './jsonLanguageTypes';
|
|
2
2
|
import { DocumentLink } from 'vscode-languageserver-types';
|
|
3
3
|
export type JSONDocument = {
|
|
4
4
|
root: ASTNode | undefined;
|
|
@@ -20,10 +20,11 @@ export interface LanguageService {
|
|
|
20
20
|
findDocumentColors(document: TextDocument, doc: JSONDocument, context?: DocumentColorsContext): Thenable<ColorInformation[]>;
|
|
21
21
|
getColorPresentations(document: TextDocument, doc: JSONDocument, color: Color, range: Range): ColorPresentation[];
|
|
22
22
|
doHover(document: TextDocument, position: Position, doc: JSONDocument): Thenable<Hover | null>;
|
|
23
|
-
format(document: TextDocument, range: Range, options: FormattingOptions): TextEdit[];
|
|
24
23
|
getFoldingRanges(document: TextDocument, context?: FoldingRangesContext): FoldingRange[];
|
|
25
24
|
getSelectionRanges(document: TextDocument, positions: Position[], doc: JSONDocument): SelectionRange[];
|
|
26
25
|
findDefinition(document: TextDocument, position: Position, doc: JSONDocument): Thenable<DefinitionLink[]>;
|
|
27
26
|
findLinks(document: TextDocument, doc: JSONDocument): Thenable<DocumentLink[]>;
|
|
27
|
+
format(document: TextDocument, range: Range, options: FormattingOptions): TextEdit[];
|
|
28
|
+
sort(document: TextDocument, options: SortOptions): TextEdit[];
|
|
28
29
|
}
|
|
29
30
|
export declare function getLanguageService(params: LanguageServiceParams): LanguageService;
|
|
@@ -11,8 +11,8 @@ import { schemaContributions } from './services/configuration';
|
|
|
11
11
|
import { JSONSchemaService } from './services/jsonSchemaService';
|
|
12
12
|
import { getFoldingRanges } from './services/jsonFolding';
|
|
13
13
|
import { getSelectionRanges } from './services/jsonSelectionRanges';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { sort } from './utils/sort';
|
|
15
|
+
import { format } from './utils/format';
|
|
16
16
|
import { findLinks } from './services/jsonLinks';
|
|
17
17
|
export * from './jsonLanguageTypes';
|
|
18
18
|
export function getLanguageService(params) {
|
|
@@ -26,11 +26,7 @@ export function getLanguageService(params) {
|
|
|
26
26
|
return {
|
|
27
27
|
configure: (settings) => {
|
|
28
28
|
jsonSchemaService.clearExternalSchemas();
|
|
29
|
-
|
|
30
|
-
settings.schemas.forEach(settings => {
|
|
31
|
-
jsonSchemaService.registerExternalSchema(settings.uri, settings.fileMatch, settings.schema);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
29
|
+
settings.schemas?.forEach(jsonSchemaService.registerExternalSchema.bind(jsonSchemaService));
|
|
34
30
|
jsonValidation.configure(settings);
|
|
35
31
|
},
|
|
36
32
|
resetSchema: (uri) => jsonSchemaService.onResourceChange(uri),
|
|
@@ -50,17 +46,7 @@ export function getLanguageService(params) {
|
|
|
50
46
|
getSelectionRanges,
|
|
51
47
|
findDefinition: () => Promise.resolve([]),
|
|
52
48
|
findLinks,
|
|
53
|
-
format: (
|
|
54
|
-
|
|
55
|
-
if (r) {
|
|
56
|
-
const offset = d.offsetAt(r.start);
|
|
57
|
-
const length = d.offsetAt(r.end) - offset;
|
|
58
|
-
range = { offset, length };
|
|
59
|
-
}
|
|
60
|
-
const options = { tabSize: o ? o.tabSize : 4, insertSpaces: o?.insertSpaces === true, insertFinalNewline: o?.insertFinalNewline === true, eol: '\n', keepLines: o?.keepLines === true };
|
|
61
|
-
return formatJSON(d.getText(), range, options).map(e => {
|
|
62
|
-
return TextEdit.replace(Range.create(d.positionAt(e.offset), d.positionAt(e.offset + e.length)), e.content);
|
|
63
|
-
});
|
|
64
|
-
}
|
|
49
|
+
format: (document, range, options) => format(document, options, range),
|
|
50
|
+
sort: (document, options) => sort(document, options)
|
|
65
51
|
};
|
|
66
52
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { JSONWorkerContribution, JSONPath, Segment, CompletionsCollector } from './jsonContributions';
|
|
2
2
|
import { JSONSchema } from './jsonSchema';
|
|
3
3
|
import { Range, Position, DocumentUri, MarkupContent, MarkupKind, Color, ColorInformation, ColorPresentation, FoldingRange, FoldingRangeKind, SelectionRange, Diagnostic, DiagnosticSeverity, CompletionItem, CompletionItemKind, CompletionList, CompletionItemTag, InsertTextFormat, SymbolInformation, SymbolKind, DocumentSymbol, Location, Hover, MarkedString, FormattingOptions as LSPFormattingOptions, DefinitionLink, CodeActionContext, Command, CodeAction, DocumentHighlight, DocumentLink, WorkspaceEdit, TextEdit, CodeActionKind, TextDocumentEdit, VersionedTextDocumentIdentifier, DocumentHighlightKind } from 'vscode-languageserver-types';
|
|
4
|
-
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
5
|
-
export { TextDocument, Range, Position, DocumentUri, MarkupContent, MarkupKind, JSONSchema, JSONWorkerContribution, JSONPath, Segment, CompletionsCollector, Color, ColorInformation, ColorPresentation, FoldingRange, FoldingRangeKind, SelectionRange, Diagnostic, DiagnosticSeverity, CompletionItem, CompletionItemKind, CompletionList, CompletionItemTag, InsertTextFormat, DefinitionLink, SymbolInformation, SymbolKind, DocumentSymbol, Location, Hover, MarkedString, CodeActionContext, Command, CodeAction, DocumentHighlight, DocumentLink, WorkspaceEdit, TextEdit, CodeActionKind, TextDocumentEdit, VersionedTextDocumentIdentifier, DocumentHighlightKind };
|
|
4
|
+
import { TextDocument, TextDocumentContentChangeEvent } from 'vscode-languageserver-textdocument';
|
|
5
|
+
export { TextDocument, TextDocumentContentChangeEvent, Range, Position, DocumentUri, MarkupContent, MarkupKind, JSONSchema, JSONWorkerContribution, JSONPath, Segment, CompletionsCollector, Color, ColorInformation, ColorPresentation, FoldingRange, FoldingRangeKind, SelectionRange, Diagnostic, DiagnosticSeverity, CompletionItem, CompletionItemKind, CompletionList, CompletionItemTag, InsertTextFormat, DefinitionLink, SymbolInformation, SymbolKind, DocumentSymbol, Location, Hover, MarkedString, CodeActionContext, Command, CodeAction, DocumentHighlight, DocumentLink, WorkspaceEdit, TextEdit, CodeActionKind, TextDocumentEdit, VersionedTextDocumentIdentifier, DocumentHighlightKind };
|
|
6
6
|
/**
|
|
7
7
|
* Error codes used by diagnostics
|
|
8
8
|
*/
|
|
@@ -141,6 +141,11 @@ export interface SchemaConfiguration {
|
|
|
141
141
|
* If no schema is provided, the schema will be fetched with the schema request service (if available).
|
|
142
142
|
*/
|
|
143
143
|
schema?: JSONSchema;
|
|
144
|
+
/**
|
|
145
|
+
* A parent folder for folder specifc associations. An association that has a folder URI set is only used
|
|
146
|
+
* if the document that is validated has the folderUri as parent
|
|
147
|
+
*/
|
|
148
|
+
folderUri?: string;
|
|
144
149
|
}
|
|
145
150
|
export interface WorkspaceContextService {
|
|
146
151
|
resolveRelativePath(relativePath: string, resource: string): string;
|
|
@@ -290,3 +295,6 @@ export interface FormattingOptions extends LSPFormattingOptions {
|
|
|
290
295
|
insertFinalNewline?: boolean;
|
|
291
296
|
keepLines?: boolean;
|
|
292
297
|
}
|
|
298
|
+
export interface SortOptions extends LSPFormattingOptions {
|
|
299
|
+
insertFinalNewline?: boolean;
|
|
300
|
+
}
|
|
@@ -687,7 +687,7 @@ export class JSONCompletion {
|
|
|
687
687
|
return text.replace(/[\\\$\}]/g, '\\$&'); // escape $, \ and }
|
|
688
688
|
}
|
|
689
689
|
getInsertTextForValue(value, separatorAfter) {
|
|
690
|
-
|
|
690
|
+
const text = JSON.stringify(value, null, '\t');
|
|
691
691
|
if (text === '{}') {
|
|
692
692
|
return '{$1}' + separatorAfter;
|
|
693
693
|
}
|
|
@@ -805,7 +805,7 @@ export class JSONCompletion {
|
|
|
805
805
|
nValueProposals += propertySchema.examples.length;
|
|
806
806
|
}
|
|
807
807
|
if (nValueProposals === 0) {
|
|
808
|
-
|
|
808
|
+
let type = Array.isArray(propertySchema.type) ? propertySchema.type[0] : propertySchema.type;
|
|
809
809
|
if (!type) {
|
|
810
810
|
if (propertySchema.properties) {
|
|
811
811
|
type = 'object';
|
|
@@ -845,8 +845,8 @@ export class JSONCompletion {
|
|
|
845
845
|
return resultText + value + separatorAfter;
|
|
846
846
|
}
|
|
847
847
|
getCurrentWord(document, offset) {
|
|
848
|
-
|
|
849
|
-
|
|
848
|
+
let i = offset - 1;
|
|
849
|
+
const text = document.getText();
|
|
850
850
|
while (i >= 0 && ' \t\n\r\v":{[,]}'.indexOf(text.charAt(i)) === -1) {
|
|
851
851
|
i--;
|
|
852
852
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as Parser from '../parser/jsonParser';
|
|
6
6
|
import * as Strings from '../utils/strings';
|
|
7
7
|
import { colorFromHex } from '../utils/colors';
|
|
8
|
+
import * as l10n from '@vscode/l10n';
|
|
8
9
|
import { Range, TextEdit, SymbolKind, Location } from "../jsonLanguageTypes";
|
|
9
10
|
export class JSONDocumentSymbols {
|
|
10
11
|
constructor(schemaService) {
|
|
@@ -26,7 +27,7 @@ export class JSONDocumentSymbols {
|
|
|
26
27
|
for (const property of item.properties) {
|
|
27
28
|
if (property.keyNode.value === 'key' && property.valueNode) {
|
|
28
29
|
const location = Location.create(document.uri, getRange(document, item));
|
|
29
|
-
result.push({ name:
|
|
30
|
+
result.push({ name: getName(property.valueNode), kind: SymbolKind.Function, location: location });
|
|
30
31
|
limit--;
|
|
31
32
|
if (limit <= 0) {
|
|
32
33
|
if (context && context.onResultLimitExceeded) {
|
|
@@ -100,7 +101,7 @@ export class JSONDocumentSymbols {
|
|
|
100
101
|
if (property.keyNode.value === 'key' && property.valueNode) {
|
|
101
102
|
const range = getRange(document, item);
|
|
102
103
|
const selectionRange = getRange(document, property.keyNode);
|
|
103
|
-
result.push({ name:
|
|
104
|
+
result.push({ name: getName(property.valueNode), kind: SymbolKind.Function, range, selectionRange });
|
|
104
105
|
limit--;
|
|
105
106
|
if (limit <= 0) {
|
|
106
107
|
if (context && context.onResultLimitExceeded) {
|
|
@@ -265,3 +266,6 @@ export class JSONDocumentSymbols {
|
|
|
265
266
|
function getRange(document, node) {
|
|
266
267
|
return Range.create(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
|
|
267
268
|
}
|
|
269
|
+
function getName(node) {
|
|
270
|
+
return Parser.getNodeValue(node) || l10n.t('<empty>');
|
|
271
|
+
}
|
|
@@ -28,7 +28,7 @@ export class JSONHover {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
const hoverRange = Range.create(document.positionAt(hoverRangeNode.offset), document.positionAt(hoverRangeNode.offset + hoverRangeNode.length));
|
|
31
|
-
|
|
31
|
+
const createHover = (contents) => {
|
|
32
32
|
const result = {
|
|
33
33
|
contents: contents,
|
|
34
34
|
range: hoverRange
|
|
@@ -12,7 +12,9 @@ import { isObject, isString } from '../utils/objects';
|
|
|
12
12
|
const BANG = '!';
|
|
13
13
|
const PATH_SEP = '/';
|
|
14
14
|
class FilePatternAssociation {
|
|
15
|
-
constructor(pattern, uris) {
|
|
15
|
+
constructor(pattern, folderUri, uris) {
|
|
16
|
+
this.folderUri = folderUri;
|
|
17
|
+
this.uris = uris;
|
|
16
18
|
this.globWrappers = [];
|
|
17
19
|
try {
|
|
18
20
|
for (let patternString of pattern) {
|
|
@@ -31,7 +33,9 @@ class FilePatternAssociation {
|
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
;
|
|
34
|
-
|
|
36
|
+
if (folderUri && !folderUri.endsWith('/')) {
|
|
37
|
+
this.folderUri = folderUri + '/';
|
|
38
|
+
}
|
|
35
39
|
}
|
|
36
40
|
catch (e) {
|
|
37
41
|
this.globWrappers.length = 0;
|
|
@@ -39,6 +43,9 @@ class FilePatternAssociation {
|
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
matchesPattern(fileName) {
|
|
46
|
+
if (this.folderUri && !fileName.startsWith(this.folderUri)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
42
49
|
let match = false;
|
|
43
50
|
for (const { regexp, include } of this.globWrappers) {
|
|
44
51
|
if (regexp.test(fileName)) {
|
|
@@ -199,7 +206,7 @@ export class JSONSchemaService {
|
|
|
199
206
|
const schemaAssociations = schemaContributions.schemaAssociations;
|
|
200
207
|
for (let schemaAssociation of schemaAssociations) {
|
|
201
208
|
const uris = schemaAssociation.uris.map(normalizeId);
|
|
202
|
-
const association = this.addFilePatternAssociation(schemaAssociation.pattern, uris);
|
|
209
|
+
const association = this.addFilePatternAssociation(schemaAssociation.pattern, schemaAssociation.folderUri, uris);
|
|
203
210
|
this.contributionAssociations.push(association);
|
|
204
211
|
}
|
|
205
212
|
}
|
|
@@ -212,19 +219,19 @@ export class JSONSchemaService {
|
|
|
212
219
|
getOrAddSchemaHandle(id, unresolvedSchemaContent) {
|
|
213
220
|
return this.schemasById[id] || this.addSchemaHandle(id, unresolvedSchemaContent);
|
|
214
221
|
}
|
|
215
|
-
addFilePatternAssociation(pattern, uris) {
|
|
216
|
-
const fpa = new FilePatternAssociation(pattern, uris);
|
|
222
|
+
addFilePatternAssociation(pattern, folderUri, uris) {
|
|
223
|
+
const fpa = new FilePatternAssociation(pattern, folderUri, uris);
|
|
217
224
|
this.filePatternAssociations.push(fpa);
|
|
218
225
|
return fpa;
|
|
219
226
|
}
|
|
220
|
-
registerExternalSchema(
|
|
221
|
-
const id = normalizeId(uri);
|
|
227
|
+
registerExternalSchema(config) {
|
|
228
|
+
const id = normalizeId(config.uri);
|
|
222
229
|
this.registeredSchemasIds[id] = true;
|
|
223
230
|
this.cachedSchemaForResource = undefined;
|
|
224
|
-
if (
|
|
225
|
-
this.addFilePatternAssociation(
|
|
231
|
+
if (config.fileMatch && config.fileMatch.length) {
|
|
232
|
+
this.addFilePatternAssociation(config.fileMatch, config.folderUri, [id]);
|
|
226
233
|
}
|
|
227
|
-
return
|
|
234
|
+
return config.schema ? this.addSchemaHandle(id, config.schema) : this.getOrAddSchemaHandle(id);
|
|
228
235
|
}
|
|
229
236
|
clearExternalSchemas() {
|
|
230
237
|
this.schemasById = {};
|
|
@@ -89,8 +89,8 @@ export class JSONValidation {
|
|
|
89
89
|
return diagnostics;
|
|
90
90
|
};
|
|
91
91
|
if (schema) {
|
|
92
|
-
const
|
|
93
|
-
const handle = this.jsonSchemaService.registerExternalSchema(
|
|
92
|
+
const uri = schema.id || ('schemaservice://untitled/' + idCounter++);
|
|
93
|
+
const handle = this.jsonSchemaService.registerExternalSchema({ uri, schema });
|
|
94
94
|
return handle.getResolvedSchema().then(resolvedSchema => {
|
|
95
95
|
return getDiagnostics(resolvedSchema);
|
|
96
96
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { format as formatJSON } from 'jsonc-parser';
|
|
2
|
+
import { Range, TextEdit } from '../jsonLanguageTypes';
|
|
3
|
+
export function format(documentToFormat, formattingOptions, formattingRange) {
|
|
4
|
+
let range = undefined;
|
|
5
|
+
if (formattingRange) {
|
|
6
|
+
const offset = documentToFormat.offsetAt(formattingRange.start);
|
|
7
|
+
const length = documentToFormat.offsetAt(formattingRange.end) - offset;
|
|
8
|
+
range = { offset, length };
|
|
9
|
+
}
|
|
10
|
+
const options = {
|
|
11
|
+
tabSize: formattingOptions ? formattingOptions.tabSize : 4,
|
|
12
|
+
insertSpaces: formattingOptions?.insertSpaces === true,
|
|
13
|
+
insertFinalNewline: formattingOptions?.insertFinalNewline === true,
|
|
14
|
+
eol: '\n',
|
|
15
|
+
keepLines: formattingOptions?.keepLines === true
|
|
16
|
+
};
|
|
17
|
+
return formatJSON(documentToFormat.getText(), range, options).map(edit => {
|
|
18
|
+
return TextEdit.replace(Range.create(documentToFormat.positionAt(edit.offset), documentToFormat.positionAt(edit.offset + edit.length)), edit.content);
|
|
19
|
+
});
|
|
20
|
+
}
|
package/lib/esm/utils/objects.js
CHANGED
|
@@ -18,7 +18,7 @@ export function equals(one, other) {
|
|
|
18
18
|
if ((Array.isArray(one)) !== (Array.isArray(other))) {
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
let i, key;
|
|
22
22
|
if (Array.isArray(one)) {
|
|
23
23
|
if (one.length !== other.length) {
|
|
24
24
|
return false;
|
|
@@ -30,12 +30,12 @@ export function equals(one, other) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
|
-
|
|
33
|
+
const oneKeys = [];
|
|
34
34
|
for (key in one) {
|
|
35
35
|
oneKeys.push(key);
|
|
36
36
|
}
|
|
37
37
|
oneKeys.sort();
|
|
38
|
-
|
|
38
|
+
const otherKeys = [];
|
|
39
39
|
for (key in other) {
|
|
40
40
|
otherKeys.push(key);
|
|
41
41
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
export var Container;
|
|
6
|
+
(function (Container) {
|
|
7
|
+
Container[Container["Object"] = 0] = "Object";
|
|
8
|
+
Container[Container["Array"] = 1] = "Array";
|
|
9
|
+
})(Container || (Container = {}));
|
|
10
|
+
export class PropertyTree {
|
|
11
|
+
constructor(propertyName, beginningLineNumber) {
|
|
12
|
+
this.propertyName = propertyName ?? '';
|
|
13
|
+
this.beginningLineNumber = beginningLineNumber;
|
|
14
|
+
this.childrenProperties = [];
|
|
15
|
+
this.lastProperty = false;
|
|
16
|
+
this.noKeyName = false;
|
|
17
|
+
}
|
|
18
|
+
addChildProperty(childProperty) {
|
|
19
|
+
childProperty.parent = this;
|
|
20
|
+
if (this.childrenProperties.length > 0) {
|
|
21
|
+
let insertionIndex = 0;
|
|
22
|
+
if (childProperty.noKeyName) {
|
|
23
|
+
insertionIndex = this.childrenProperties.length;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
insertionIndex = binarySearchOnPropertyArray(this.childrenProperties, childProperty, compareProperties);
|
|
27
|
+
}
|
|
28
|
+
if (insertionIndex < 0) {
|
|
29
|
+
insertionIndex = (insertionIndex * -1) - 1;
|
|
30
|
+
}
|
|
31
|
+
this.childrenProperties.splice(insertionIndex, 0, childProperty);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.childrenProperties.push(childProperty);
|
|
35
|
+
}
|
|
36
|
+
return childProperty;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function compareProperties(propertyTree1, propertyTree2) {
|
|
40
|
+
if (propertyTree1.propertyName < propertyTree2.propertyName) {
|
|
41
|
+
return -1;
|
|
42
|
+
}
|
|
43
|
+
else if (propertyTree1.propertyName > propertyTree2.propertyName) {
|
|
44
|
+
return 1;
|
|
45
|
+
}
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
function binarySearchOnPropertyArray(propertyTreeArray, propertyTree, compare_fn) {
|
|
49
|
+
if (propertyTree.propertyName < propertyTreeArray[0].propertyName) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
if (propertyTree.propertyName > propertyTreeArray[propertyTreeArray.length - 1].propertyName) {
|
|
53
|
+
return propertyTreeArray.length;
|
|
54
|
+
}
|
|
55
|
+
let m = 0;
|
|
56
|
+
let n = propertyTreeArray.length - 1;
|
|
57
|
+
while (m <= n) {
|
|
58
|
+
let k = (n + m) >> 1;
|
|
59
|
+
let cmp = compare_fn(propertyTree, propertyTreeArray[k]);
|
|
60
|
+
if (cmp > 0) {
|
|
61
|
+
m = k + 1;
|
|
62
|
+
}
|
|
63
|
+
else if (cmp < 0) {
|
|
64
|
+
n = k - 1;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return k;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return -m - 1;
|
|
71
|
+
}
|