提交 f0c6cccc 编写于 作者: M Martin Aeschlimann

Fixes #3494: [snippets] [debt] don't allow snippet syntax in default values

上级 c676ceb7
......@@ -5,42 +5,43 @@
'use strict';
export interface IJSONSchema {
id?:string;
id?: string;
$schema?: string;
type?:any;
title?:string;
default?:any;
definitions?:IJSONSchemaMap;
description?:string;
type?: string | string[];
title?: string;
default?: any;
definitions?: IJSONSchemaMap;
description?: string;
properties?: IJSONSchemaMap;
patternProperties?:IJSONSchemaMap;
additionalProperties?:any;
minProperties?:number;
maxProperties?:number;
dependencies?:any;
items?:any;
minItems?:number;
maxItems?:number;
uniqueItems?:boolean;
additionalItems?:boolean;
pattern?:string;
minLength?:number;
maxLength?:number;
minimum?:number;
maximum?:number;
exclusiveMinimum?:boolean;
exclusiveMaximum?:boolean;
multipleOf?:number;
required?:string[];
$ref?:string;
anyOf?:IJSONSchema[];
allOf?:IJSONSchema[];
oneOf?:IJSONSchema[];
not?:IJSONSchema;
enum?:any[];
patternProperties?: IJSONSchemaMap;
additionalProperties?: boolean | IJSONSchema;
minProperties?: number;
maxProperties?: number;
dependencies?: IJSONSchemaMap | string[];
items?: IJSONSchema | IJSONSchema[];
minItems?: number;
maxItems?: number;
uniqueItems?: boolean;
additionalItems?: boolean;
pattern?: string;
minLength?: number;
maxLength?: number;
minimum?: number;
maximum?: number;
exclusiveMinimum?: boolean;
exclusiveMaximum?: boolean;
multipleOf?: number;
required?: string[];
$ref?: string;
anyOf?: IJSONSchema[];
allOf?: IJSONSchema[];
oneOf?: IJSONSchema[];
not?: IJSONSchema;
enum?: any[];
format?: string;
errorMessage?:string; // VS code internal
defaultSnippets?: { label?: string; description?: string; body: any; }[]; // VSCode extension
errorMessage?: string; // VSCode extension
}
export interface IJSONSchemaMap {
......
......@@ -172,7 +172,7 @@ export class JSONCompletion {
if (schemaProperties) {
Object.keys(schemaProperties).forEach((key: string) => {
let propertySchema = schemaProperties[key];
collector.add({ kind: CompletionItemKind.Property, label: key, insertText: this.getSnippetForProperty(key, propertySchema, addValue, isLast), documentation: propertySchema.description || '' });
collector.add({ kind: CompletionItemKind.Property, label: key, insertText: this.getTextForProperty(key, propertySchema, addValue, isLast), documentation: propertySchema.description || '' });
});
}
}
......@@ -183,7 +183,7 @@ export class JSONCompletion {
let collectSuggestionsForSimilarObject = (obj: Parser.ObjectASTNode) => {
obj.properties.forEach((p) => {
let key = p.key.value;
collector.add({ kind: CompletionItemKind.Property, label: key, insertText: this.getSnippetForSimilarProperty(key, p.value), documentation: '' });
collector.add({ kind: CompletionItemKind.Property, label: key, insertText: this.getTextForSimilarProperty(key, p.value), documentation: '' });
});
};
if (node.parent) {
......@@ -206,14 +206,14 @@ export class JSONCompletion {
}
}
if (!currentKey && currentWord.length > 0) {
collector.add({ kind: CompletionItemKind.Property, label: JSON.stringify(currentWord), insertText: this.getSnippetForProperty(currentWord, null, true, isLast), documentation: '' });
collector.add({ kind: CompletionItemKind.Property, label: this.getLabelForValue(currentWord), insertText: this.getTextForProperty(currentWord, null, true, isLast), documentation: '' });
}
}
private getSchemaLessValueSuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, offset: number, document: ITextDocument, collector: ISuggestionsCollector): void {
let collectSuggestionsForValues = (value: Parser.ASTNode) => {
if (!value.contains(offset)) {
let content = this.getMatchingSnippet(value, document);
let content = this.getTextForMatchingNode(value, document);
collector.add({ kind: this.getSuggestionKind(value.type), label: content, insertText: content, documentation: '' });
}
if (value.type === 'boolean') {
......@@ -347,6 +347,16 @@ export class JSONCompletion {
detail: nls.localize('json.suggest.default', 'Default value'),
});
}
if (Array.isArray(schema.defaultSnippets)) {
schema.defaultSnippets.forEach(s => {
collector.add({
kind: CompletionItemKind.Snippet,
label: this.getLabelForSnippetValue(s.body),
insertText: this.getTextForSnippetValue(s.body)
});
});
}
if (Array.isArray(schema.allOf)) {
schema.allOf.forEach((s) => this.addDefaultSuggestion(s, collector));
}
......@@ -360,7 +370,15 @@ export class JSONCompletion {
private getLabelForValue(value: any): string {
let label = JSON.stringify(value);
label = label.replace('{{', '').replace('}}', '');
if (label.length > 57) {
return label.substr(0, 57).trim() + '...';
}
return label;
}
private getLabelForSnippetValue(value: any): string {
let label = JSON.stringify(value);
label = label.replace(/\{\{|\}\}/g, '');
if (label.length > 57) {
return label.substr(0, 57).trim() + '...';
}
......@@ -368,11 +386,17 @@ export class JSONCompletion {
}
private getTextForValue(value: any): string {
var text = JSON.stringify(value, null, '\t');
text = text.replace(/[\\\{\}]/g, '\\$&');
return text;
}
private getTextForSnippetValue(value: any): string {
return JSON.stringify(value, null, '\t');
}
private getSnippetForValue(value: any): string {
let snippet = JSON.stringify(value, null, '\t');
private getTextForEnumValue(value: any): string {
let snippet = this.getTextForValue(value);
switch (typeof value) {
case 'object':
if (value === null) {
......@@ -405,7 +429,7 @@ export class JSONCompletion {
}
private getMatchingSnippet(node: Parser.ASTNode, document: ITextDocument): string {
private getTextForMatchingNode(node: Parser.ASTNode, document: ITextDocument): string {
switch (node.type) {
case 'array':
return '[]';
......@@ -417,9 +441,9 @@ export class JSONCompletion {
}
}
private getSnippetForProperty(key: string, propertySchema: JsonSchema.IJSONSchema, addValue: boolean, isLast: boolean): string {
private getTextForProperty(key: string, propertySchema: JsonSchema.IJSONSchema, addValue: boolean, isLast: boolean): string {
let result = '"' + key + '"';
let result = this.getTextForValue(key);
if (!addValue) {
return result;
}
......@@ -428,9 +452,9 @@ export class JSONCompletion {
if (propertySchema) {
let defaultVal = propertySchema.default;
if (typeof defaultVal !== 'undefined') {
result = result + this.getSnippetForValue(defaultVal);
result = result + this.getTextForEnumValue(defaultVal);
} else if (propertySchema.enum && propertySchema.enum.length > 0) {
result = result + this.getSnippetForValue(propertySchema.enum[0]);
result = result + this.getTextForEnumValue(propertySchema.enum[0]);
} else {
var type = Array.isArray(propertySchema.type) ? propertySchema.type[0] : propertySchema.type;
switch (type) {
......@@ -465,8 +489,8 @@ export class JSONCompletion {
return result;
}
private getSnippetForSimilarProperty(key: string, templateValue: Parser.ASTNode): string {
return '"' + key + '"';
private getTextForSimilarProperty(key: string, templateValue: Parser.ASTNode): string {
return this.getTextForValue(key);
}
private getCurrentWord(document: ITextDocument, offset: number) {
......
......@@ -103,7 +103,7 @@ export class ASTNode {
if ((<string[]>schema.type).indexOf(this.type) === -1) {
validationResult.warnings.push({
location: { start: this.start, end: this.end },
message: nls.localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}', schema.type.join(', '))
message: nls.localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}', (<string[]>schema.type).join(', '))
});
}
}
......@@ -277,14 +277,14 @@ export class ArrayASTNode extends ASTNode {
super.validate(schema, validationResult, matchingSchemas, offset);
if (Array.isArray(schema.items)) {
let subSchemas: JsonSchema.IJSONSchema[] = schema.items;
let subSchemas = <JsonSchema.IJSONSchema[]> schema.items;
subSchemas.forEach((subSchema, index) => {
let itemValidationResult = new ValidationResult();
let item = this.items[index];
if (item) {
item.validate(subSchema, itemValidationResult, matchingSchemas, offset);
validationResult.mergePropertyMatch(itemValidationResult);
} else if (this.items.length >= schema.items.length) {
} else if (this.items.length >= subSchemas.length) {
validationResult.propertiesValueMatches++;
}
});
......@@ -294,8 +294,8 @@ export class ArrayASTNode extends ASTNode {
location: { start: this.start, end: this.end },
message: nls.localize('additionalItemsWarning', 'Array has too many items according to schema. Expected {0} or fewer', subSchemas.length)
});
} else if (this.items.length >= schema.items.length) {
validationResult.propertiesValueMatches += (this.items.length - schema.items.length);
} else if (this.items.length >= subSchemas.length) {
validationResult.propertiesValueMatches += (this.items.length - subSchemas.length);
}
}
else if (schema.items) {
......
......@@ -24,7 +24,7 @@ suite('JSON Completion', () => {
var matches = completions.filter(function(completion: CompletionItem) {
return completion.label === label && (!documentation || completion.documentation === documentation);
});
assert.equal(matches.length, 1, label + " should only existing once");
assert.equal(matches.length, 1, label + " should only existing once: Actual: " + completions.map(c => c.label).join(', '));
if (document && resultText) {
assert.equal(applyEdits(document, [ matches[0].textEdit ]), resultText);
}
......@@ -51,8 +51,6 @@ suite('JSON Completion', () => {
})
};
test('Complete keys no schema', function(testDone) {
Promise.all([
testSuggestionsFor('[ { "name": "John", "age": 44 }, { /**/ }', '/**/', null, result => {
......@@ -478,4 +476,44 @@ suite('JSON Completion', () => {
}),
]).then(() => testDone(), (error) => testDone(error));
});
});
\ No newline at end of file
test('Escaping no schema', function(testDone) {
Promise.all([
testSuggestionsFor('[ { "\\\\{{}}": "John" }, { "/**/" }', '/**/', null, result => {
assertSuggestion(result, '\\{{}}');
}),
testSuggestionsFor('[ { "\\\\{{}}": "John" }, { /**/ }', '/**/', null, (result, document) => {
assertSuggestion(result, '\\{{}}', null, document, '[ { "\\\\{{}}": "John" }, { "\\\\\\\\\\{\\{\\}\\}"/**/ }');
}),
testSuggestionsFor('[ { "name": "\\{" }, { "name": /**/ }', '/**/', null, result => {
assertSuggestion(result, '"\\{"');
})
]).then(() => testDone(), (error) => testDone(error));
});
test('Escaping with schema', function(testDone) {
var schema: JsonSchema.IJSONSchema = {
type: 'object',
properties: {
'{\\}': {
default: "{\\}",
defaultSnippets: [ { body: "{{var}}"} ],
enum: ['John{\\}']
}
}
};
Promise.all([
testSuggestionsFor('{ /**/ }', '/**/', schema, (result, document) => {
assertSuggestion(result, '{\\}', null, document, '{ "\\{\\\\\\\\\\}": "{{\\{\\\\\\\\\\}}}"/**/ }');
}),
testSuggestionsFor('{ "{\\\\}": /**/ }', '/**/', schema, (result, document) => {
assertSuggestion(result, '"{\\\\}"', null, document, '{ "{\\\\}": "\\{\\\\\\\\\\}"/**/ }');
assertSuggestion(result, '"John{\\\\}"', null, document, '{ "{\\\\}": "John\\{\\\\\\\\\\}"/**/ }');
assertSuggestion(result, '"var"', null, document, '{ "{\\\\}": "{{var}}"/**/ }');
})
]).then(() => testDone(), (error) => testDone(error));
});
});
......@@ -5,41 +5,43 @@
'use strict';
export interface IJSONSchema {
id?:string;
id?: string;
$schema?: string;
type?:any;
title?:string;
default?:any;
definitions?:IJSONSchemaMap;
description?:string;
type?: string | string[];
title?: string;
default?: any;
definitions?: IJSONSchemaMap;
description?: string;
properties?: IJSONSchemaMap;
patternProperties?:IJSONSchemaMap;
additionalProperties?:any;
minProperties?:number;
maxProperties?:number;
dependencies?:any;
items?:any;
minItems?:number;
maxItems?:number;
uniqueItems?:boolean;
additionalItems?:boolean;
pattern?:string;
errorMessage?: string;
minLength?:number;
maxLength?:number;
minimum?:number;
maximum?:number;
exclusiveMinimum?:boolean;
exclusiveMaximum?:boolean;
multipleOf?:number;
required?:string[];
$ref?:string;
anyOf?:IJSONSchema[];
allOf?:IJSONSchema[];
oneOf?:IJSONSchema[];
not?:IJSONSchema;
enum?:any[];
patternProperties?: IJSONSchemaMap;
additionalProperties?: boolean | IJSONSchema;
minProperties?: number;
maxProperties?: number;
dependencies?: IJSONSchemaMap | string[];
items?: IJSONSchema | IJSONSchema[];
minItems?: number;
maxItems?: number;
uniqueItems?: boolean;
additionalItems?: boolean;
pattern?: string;
minLength?: number;
maxLength?: number;
minimum?: number;
maximum?: number;
exclusiveMinimum?: boolean;
exclusiveMaximum?: boolean;
multipleOf?: number;
required?: string[];
$ref?: string;
anyOf?: IJSONSchema[];
allOf?: IJSONSchema[];
oneOf?: IJSONSchema[];
not?: IJSONSchema;
enum?: any[];
format?: string;
defaultSnippets?: { label?: string; description?: string; body: any; }[]; // VSCode extension
errorMessage?: string; // VSCode extension
}
export interface IJSONSchemaMap {
......
......@@ -38,10 +38,10 @@ interface IModeConfigurationMap { [modeId: string]: any; }
let languagesExtPoint = PluginsRegistry.registerExtensionPoint<ILanguageExtensionPoint[]>('languages', {
description: nls.localize('vscode.extension.contributes.languages', 'Contributes language declarations.'),
type: 'array',
default: [{ id: '', aliases: [], extensions: [] }],
defaultSnippets: [{ body: [{ id: '', aliases: [], extensions: [] }] }],
items: {
type: 'object',
default: { id: '', extensions: [] },
defaultSnippets: [{ body: { id: '', extensions: [] } }],
properties: {
id: {
description: nls.localize('vscode.extension.contributes.languages.id', 'ID of the language.'),
......@@ -73,7 +73,7 @@ let languagesExtPoint = PluginsRegistry.registerExtensionPoint<ILanguageExtensio
description: nls.localize('vscode.extension.contributes.languages.filenamePatterns', 'File name glob patterns associated to the language.'),
default: ['bar*foo.txt'],
type: 'array',
item: {
items: {
type: 'string'
}
},
......
......@@ -69,11 +69,6 @@ export class CodeSnippet implements ICodeSnippet {
}
private parseTemplate(template: string): void {
if (template === '"`~!@#$%^&*()-=+[{]}\\\\|;:\'\\",.<>/?"') {
this.lines.push(template);
return;
}
var placeHoldersMap: collections.IStringDictionary<IPlaceHolder> = {};
var i: number, len: number, j: number, lenJ: number, templateLines = template.split('\n');
......
......@@ -33,10 +33,10 @@ export function snippetUpdated(modeId: string, filePath: string): TPromise<void>
let snippetsExtensionPoint = PluginsRegistry.registerExtensionPoint<ITMSnippetsExtensionPoint[]>('snippets', {
description: nls.localize('vscode.extension.contributes.snippets', 'Contributes textmate snippets.'),
type: 'array',
default: [{ language: '', path: '' }],
defaultSnippets: [ { body: [{ language: '', path: '' }] }],
items: {
type: 'object',
default: { language: '{{id}}', path: './snippets/{{id}}.json.'},
defaultSnippets: [ { body: { language: '{{id}}', path: './snippets/{{id}}.json.'} }] ,
properties: {
language: {
description: nls.localize('vscode.extension.contributes.snippets-language', 'Language id for which this snippet is contributed to.'),
......
......@@ -23,10 +23,10 @@ export interface ITMSyntaxExtensionPoint {
let grammarsExtPoint = PluginsRegistry.registerExtensionPoint<ITMSyntaxExtensionPoint[]>('grammars', {
description: nls.localize('vscode.extension.contributes.grammars', 'Contributes textmate tokenizers.'),
type: 'array',
default: [{ id: '', extensions: [] }],
defaultSnippets: [ { body: [{ id: '', extensions: [] }] }],
items: {
type: 'object',
default: { language: '{{id}}', scopeName: 'source.{{id}}', path: './syntaxes/{{id}}.tmLanguage.'},
defaultSnippets: [ { body: { language: '{{id}}', scopeName: 'source.{{id}}', path: './syntaxes/{{id}}.tmLanguage.'} }],
properties: {
language: {
description: nls.localize('vscode.extension.contributes.grammars.language', 'Language id for which this syntax is contributed to.'),
......
......@@ -30,7 +30,7 @@ configurationRegistry.registerConfiguration({
'description': nls.localize('jsonConfiguration.schemas', "Associate schemas to JSON files in the current project"),
'items': {
'type': 'object',
'default': { fileMatch: [ '{{/myfile}}' ], url: '{{schemaURL}}' },
'defaultSnippets': [{ body: { fileMatch: [ '{{/myfile}}' ], url: '{{schemaURL}}' } }],
'properties': {
'url': {
'type': 'string',
......
......@@ -179,7 +179,7 @@ export class JSONIntellisense {
if (schemaProperties) {
Object.keys(schemaProperties).forEach((key: string) => {
var propertySchema = schemaProperties[key];
collector.add({ type: 'property', label: key, codeSnippet: this.getSnippetForProperty(key, propertySchema, addValue, isLast), documentationLabel: propertySchema.description || '' });
collector.add({ type: 'property', label: key, codeSnippet: this.getTextForProperty(key, propertySchema, addValue, isLast), documentationLabel: propertySchema.description || '' });
});
}
}
......@@ -190,7 +190,7 @@ export class JSONIntellisense {
var collectSuggestionsForSimilarObject = (obj: Parser.ObjectASTNode) => {
obj.properties.forEach((p) => {
var key = p.key.value;
collector.add({ type: 'property', label: key, codeSnippet: this.getSnippetForSimilarProperty(key, p.value), documentationLabel: '' });
collector.add({ type: 'property', label: key, codeSnippet: this.getTextForSimilarProperty(key, p.value), documentationLabel: '' });
});
};
if (node.parent.type === 'property') {
......@@ -214,7 +214,7 @@ export class JSONIntellisense {
public getSchemaLessValueSuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, offset: number, modelMirror: EditorCommon.IMirrorModel, collector: JsonWorker.ISuggestionsCollector): void {
var collectSuggestionsForValues = (value: Parser.ASTNode) => {
var content = this.getMatchingSnippet(value, modelMirror);
var content = this.getTextForMatchingNode(value, modelMirror);
collector.add({ type: this.getSuggestionType(value.type), label: content, codeSnippet: content, documentationLabel: '' });
if (value.type === 'boolean') {
this.addBooleanSuggestion(!value.getValue(), collector);
......@@ -301,12 +301,12 @@ export class JSONIntellisense {
}
private addBooleanSuggestion(value: boolean, collector: JsonWorker.ISuggestionsCollector): void {
collector.add({ type: this.getSuggestionType('boolean'), label: value ? 'true' : 'false', codeSnippet: this.getSnippetForValue(value), documentationLabel: '' });
collector.add({ type: this.getSuggestionType('boolean'), label: value ? 'true' : 'false', codeSnippet: this.getTextForEnumValue(value), documentationLabel: '' });
}
private addEnumSuggestion(schema: JsonSchema.IJSONSchema, collector: JsonWorker.ISuggestionsCollector): void {
if (Array.isArray(schema.enum)) {
schema.enum.forEach((enm) => collector.add({ type: this.getSuggestionType(schema.type), label: this.getLabelForValue(enm), codeSnippet: this.getSnippetForValue(enm), documentationLabel: '' }));
schema.enum.forEach((enm) => collector.add({ type: this.getSuggestionType(schema.type), label: this.getLabelForValue(enm), codeSnippet: this.getTextForEnumValue(enm), documentationLabel: '' }));
} else if (schema.type === 'boolean') {
this.addBooleanSuggestion(true, collector);
this.addBooleanSuggestion(false, collector);
......@@ -327,10 +327,19 @@ export class JSONIntellisense {
collector.add({
type: this.getSuggestionType(schema.type),
label: this.getLabelForValue(schema.default),
codeSnippet: this.getSnippetForValue(schema.default),
codeSnippet: this.getTextForValue(schema.default),
typeLabel: nls.localize('json.suggest.default', 'Default value'),
});
}
if (Array.isArray(schema.defaultSnippets)) {
schema.defaultSnippets.forEach(s => {
collector.add({
type: 'snippet',
label: this.getLabelForSnippetValue(s.body),
codeSnippet: this.getTextForSnippetValue(s.body)
});
});
}
if (Array.isArray(schema.allOf)) {
schema.allOf.forEach((s) => this.addDefaultSuggestion(s, collector));
}
......@@ -351,7 +360,26 @@ export class JSONIntellisense {
return label;
}
private getSnippetForValue(value: any) : string {
private getLabelForSnippetValue(value: any): string {
let label = JSON.stringify(value);
label = label.replace(/\{\{|\}\}/g, '');
if (label.length > 57) {
return label.substr(0, 57).trim() + '...';
}
return label;
}
private getTextForValue(value: any): string {
var text = JSON.stringify(value, null, '\t');
text = text.replace(/[\\\{\}]/g, '\\$&');
return text;
}
private getTextForSnippetValue(value: any): string {
return JSON.stringify(value, null, '\t');
}
private getTextForEnumValue(value: any) : string {
var snippet = JSON.stringify(value, null, '\t');
switch (typeof value) {
case 'object':
......@@ -386,7 +414,7 @@ export class JSONIntellisense {
}
private getMatchingSnippet(node: Parser.ASTNode, modelMirror: EditorCommon.IMirrorModel): string {
private getTextForMatchingNode(node: Parser.ASTNode, modelMirror: EditorCommon.IMirrorModel): string {
switch (node.type) {
case 'array':
return '[]';
......@@ -398,9 +426,9 @@ export class JSONIntellisense {
}
}
private getSnippetForProperty(key: string, propertySchema: JsonSchema.IJSONSchema, addValue:boolean, isLast: boolean): string {
private getTextForProperty(key: string, propertySchema: JsonSchema.IJSONSchema, addValue:boolean, isLast: boolean): string {
var result = '"' + key + '"';
let result = this.getTextForValue(key);
if (!addValue) {
return result;
}
......@@ -408,9 +436,9 @@ export class JSONIntellisense {
var defaultVal = propertySchema.default;
if (!Types.isUndefined(defaultVal)) {
result = result + this.getSnippetForValue(defaultVal);
result = result + this.getTextForEnumValue(defaultVal);
} else if (propertySchema.enum && propertySchema.enum.length > 0) {
result = result + this.getSnippetForValue(propertySchema.enum[0]);
result = result + this.getTextForEnumValue(propertySchema.enum[0]);
} else {
switch (propertySchema.type) {
case 'boolean':
......@@ -442,7 +470,7 @@ export class JSONIntellisense {
return result;
}
private getSnippetForSimilarProperty(key: string, templateValue: Parser.ASTNode): string {
return '"' + key + '"';
private getTextForSimilarProperty(key: string, templateValue: Parser.ASTNode): string {
return this.getTextForValue(key);
}
}
......@@ -102,10 +102,10 @@ export class ASTNode {
}
if (Array.isArray(schema.type)) {
if (Arrays.contains(schema.type, this.type) === false) {
if (Arrays.contains(<string[]> schema.type, this.type) === false) {
validationResult.warnings.push({
location: { start: this.start, end: this.end },
message: nls.localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}', schema.type.join())
message: nls.localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}', (<string[]> schema.type).join())
});
}
}
......@@ -279,14 +279,14 @@ export class ArrayASTNode extends ASTNode {
super.validate(schema, validationResult, matchingSchemas, offset);
if (Array.isArray(schema.items)) {
var subSchemas:JsonSchema.IJSONSchema[] = schema.items;
var subSchemas = <JsonSchema.IJSONSchema[]> schema.items;
subSchemas.forEach((subSchema, index) => {
var itemValidationResult = new ValidationResult();
var item = this.items[index];
if (item) {
item.validate(subSchema, itemValidationResult, matchingSchemas, offset);
validationResult.mergePropertyMatch(itemValidationResult);
} else if (this.items.length >= schema.items.length) {
} else if (this.items.length >= subSchemas.length) {
validationResult.propertiesValueMatches++;
}
});
......@@ -296,8 +296,8 @@ export class ArrayASTNode extends ASTNode {
location: { start: this.start, end: this.end },
message: nls.localize('additionalItemsWarning', 'Array has too many items according to schema. Expected {0} or fewer', subSchemas.length)
});
} else if (this.items.length >= schema.items.length) {
validationResult.propertiesValueMatches += (this.items.length - schema.items.length);
} else if (this.items.length >= subSchemas.length) {
validationResult.propertiesValueMatches += (this.items.length - subSchemas.length);
}
}
else if (schema.items) {
......@@ -361,7 +361,7 @@ export class NumberASTNode extends ASTNode {
// work around type validation in the base class
var typeIsInteger = false;
if (schema.type === 'integer' || (Array.isArray(schema.type) && Arrays.contains(schema.type, 'integer'))) {
if (schema.type === 'integer' || (Array.isArray(schema.type) && Arrays.contains(<string[]> schema.type, 'integer'))) {
typeIsInteger = true;
}
if (typeIsInteger && this.isInteger === true) {
......
......@@ -39,7 +39,7 @@ export interface IConfigurationRegistry {
export interface IConfigurationNode {
id?: string;
order?: number;
type?: string;
type?: string | string[];
title?: string;
description?: string;
default?: any;
......@@ -96,7 +96,7 @@ platform.Registry.add(Extensions.Configuration, configurationRegistry);
let configurationExtPoint = PluginsRegistry.registerExtensionPoint<IConfigurationNode>('configuration', {
description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'),
type: 'object',
default: { title: '', properties: {} },
defaultSnippets: [{ body: { title: '', properties: {} } }],
properties: {
title: {
description: nls.localize('vscode.extension.contributes.configuration.title', 'A summary of the settings. This label will be used in the settings file as separating comment.'),
......
......@@ -221,8 +221,9 @@ function addIndent(str: string): string {
return str.split('\n').join('\n\t');
}
function getDefaultValue(type: string): any {
switch (type) {
function getDefaultValue(type: string | string[]): any {
let t = Array.isArray(type) ? (<string[]> type)[0] : <string> type;
switch (t) {
case 'boolean':
return false;
case 'integer':
......
......@@ -23,10 +23,10 @@ let schemaRegistry = <JSONContributionRegistry.IJSONContributionRegistry>Registr
let configurationExtPoint = PluginsRegistry.registerExtensionPoint<IJSONValidationExtensionPoint[]>('jsonValidation', {
description: nls.localize('contributes.jsonValidation', 'Contributes json schema configuration.'),
type: 'array',
default: [{ fileMatch: '{{file.json}}', url: '{{url}}' }],
defaultSnippets: [{ body: [{ fileMatch: '{{file.json}}', url: '{{url}}' }] }],
items: {
type: 'object',
default: { fileMatch: '{{file.json}}', url: '{{url}}' },
defaultSnippets: [{ body: { fileMatch: '{{file.json}}', url: '{{url}}' } }],
properties: {
fileMatch: {
type: 'string',
......
......@@ -30,10 +30,10 @@ import { IQuickOpenService } from 'vs/workbench/services/quickopen/common/quickO
export var debuggersExtPoint = pluginsRegistry.PluginsRegistry.registerExtensionPoint<debug.IRawAdapter[]>('debuggers', {
description: nls.localize('vscode.extension.contributes.debuggers', 'Contributes debug adapters.'),
type: 'array',
default: [{ type: '', extensions: [] }],
defaultSnippets: [{ body: [{ type: '', extensions: [] }] }],
items: {
type: 'object',
default: { type: '', program: '', runtime: '', enableBreakpointsFor: { languageIds: [ '' ] } },
defaultSnippets: [{ body: { type: '', program: '', runtime: '', enableBreakpointsFor: { languageIds: [ '' ] } } }],
properties: {
type: {
description: nls.localize('vscode.extension.contributes.debuggers.type', "Unique identifier for this debug adapter."),
......@@ -205,7 +205,7 @@ export class ConfigurationManager {
this.adapters.forEach(adapter => {
const schemaAttributes = adapter.getSchemaAttributes();
if (schemaAttributes) {
schema.properties['configurations'].items.oneOf.push(...schemaAttributes);
(<IJSONSchema> schema.properties['configurations'].items).oneOf.push(...schemaAttributes);
}
});
});
......
......@@ -132,7 +132,10 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenSn
let schemaId = 'vscode://schemas/snippets';
let schema : IJSONSchema = {
'id': schemaId,
'default': { '{{snippetName}}': { 'prefix': '{{prefix}}', 'body': '{{snippet}}', 'description': '{{description}}' } },
'defaultSnippets': [{
'label': nls.localize('snippetSchema.json.default', "Empty snippet"),
'body': { '{{snippetName}}': { 'prefix': '{{prefix}}', 'body': '{{snippet}}', 'description': '{{description}}' } }
}],
'type': 'object',
'description': nls.localize('snippetSchema.json', 'User snippet configuration'),
'additionalProperties': {
......
......@@ -292,7 +292,7 @@ let schema : IJSONSchema = {
'items': {
'required': ['key'],
'type': 'object',
'default': { 'key': '{{_}}', 'command': '{{_}}', 'when': '{{_}}' },
'defaultSnippets': [ { 'body': { 'key': '{{_}}', 'command': '{{_}}', 'when': '{{_}}' } }],
'properties': {
'key': {
'type': 'string',
......
......@@ -23,10 +23,10 @@ let defaultBaseTheme = Themes.getBaseThemeId(DEFAULT_THEME_ID);
let themesExtPoint = PluginsRegistry.registerExtensionPoint<IThemeExtensionPoint[]>('themes', {
description: nls.localize('vscode.extension.contributes.themes', 'Contributes textmate color themes.'),
type: 'array',
default: [{ label: '{{label}}', uiTheme: 'vs-dark', path: './themes/{{id}}.tmTheme.' }],
defaultSnippets: [{ body: [{ label: '{{label}}', uiTheme: 'vs-dark', path: './themes/{{id}}.tmTheme.' }] }],
items: {
type: 'object',
default: { label: '{{label}}', uiTheme: 'vs-dark', path: './themes/{{id}}.tmTheme.' },
defaultSnippets: [{ body: { label: '{{label}}', uiTheme: 'vs-dark', path: './themes/{{id}}.tmTheme.' } }],
properties: {
label: {
description: nls.localize('vscode.extension.contributes.themes.label', 'Label of the color theme as shown in the UI.'),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册