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

[json] refactor intellisense participants to not depend on schema

上级 dcdff0a5
...@@ -10,6 +10,8 @@ import WinJS = require('vs/base/common/winjs.base'); ...@@ -10,6 +10,8 @@ import WinJS = require('vs/base/common/winjs.base');
import nls = require('vs/nls'); import nls = require('vs/nls');
import JSONWorker = require('vs/languages/json/common/jsonWorker'); import JSONWorker = require('vs/languages/json/common/jsonWorker');
import {IRequestService} from 'vs/platform/request/common/request'; import {IRequestService} from 'vs/platform/request/common/request';
import URI from 'vs/base/common/uri';
import {JSONLocation} from 'vs/languages/json/common/parser/jsonLocation';
export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution { export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution {
...@@ -27,8 +29,13 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution ...@@ -27,8 +29,13 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution
this.requestService = requestService; this.requestService = requestService;
} }
public collectDefaultSuggestions(contributionId: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { private isBowerFile(resource: URI): boolean {
if (contributionId === 'http://json.schemastore.org/bower') { var path = resource.path;
return Strings.endsWith(path, '/bower.json') || Strings.endsWith(path, '/.bower.json');
}
public collectDefaultSuggestions(resource: URI, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
if (this.isBowerFile(resource)) {
var defaultValue = { var defaultValue = {
'name': '{{name}}', 'name': '{{name}}',
'description': '{{description}}', 'description': '{{description}}',
...@@ -39,11 +46,11 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution ...@@ -39,11 +46,11 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution
}; };
result.add({ type: 'type', label: nls.localize('json.bower.default', 'Default bower.json'), codeSnippet: JSON.stringify(defaultValue, null, '\t'), documentationLabel: '' }); result.add({ type: 'type', label: nls.localize('json.bower.default', 'Default bower.json'), codeSnippet: JSON.stringify(defaultValue, null, '\t'), documentationLabel: '' });
} }
return WinJS.Promise.as(0); return null;
} }
public collectPropertySuggestions(contributionId: string, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise { public collectPropertySuggestions(resource: URI, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise {
if (contributionId === 'bower-packages') { if (this.isBowerFile(resource) && (location.matches(['dependencies']) || location.matches(['devDependencies']))) {
if (currentWord.length > 0) { if (currentWord.length > 0) {
var queryUrl = 'https://bower.herokuapp.com/packages/search/' + encodeURIComponent(currentWord); var queryUrl = 'https://bower.herokuapp.com/packages/search/' + encodeURIComponent(currentWord);
...@@ -94,16 +101,17 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution ...@@ -94,16 +101,17 @@ export class BowerJSONContribution implements JSONWorker.IJSONWorkerContribution
result.setAsIncomplete(); result.setAsIncomplete();
} }
} }
return WinJS.Promise.as(0); return null;
} }
public collectValueSuggestions(contributionId: string, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { public collectValueSuggestions(resource: URI, location: JSONLocation, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
// not implemented. Could be do done calling the bower command. Waiting for web API: https://github.com/bower/registry/issues/26 // not implemented. Could be do done calling the bower command. Waiting for web API: https://github.com/bower/registry/issues/26
return WinJS.Promise.as(0); return null;
} }
public getInfoContribution(contributionId: string, pack: string): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> { public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
if (contributionId === 'bower-package') { if (this.isBowerFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']))) {
var pack = location.getSegments()[location.getSegments().length - 1];
var htmlContent : HtmlContent.IHTMLContentElement[] = []; var htmlContent : HtmlContent.IHTMLContentElement[] = [];
htmlContent.push({className: 'type', text: nls.localize('json.bower.package.hover', '{0}', pack) }); htmlContent.push({className: 'type', text: nls.localize('json.bower.package.hover', '{0}', pack) });
......
...@@ -5,12 +5,15 @@ ...@@ -5,12 +5,15 @@
'use strict'; 'use strict';
import HtmlContent = require('vs/base/common/htmlContent'); import HtmlContent = require('vs/base/common/htmlContent');
import Strings = require('vs/base/common/strings');
import EditorCommon = require('vs/editor/common/editorCommon'); import EditorCommon = require('vs/editor/common/editorCommon');
import Modes = require('vs/editor/common/modes'); import Modes = require('vs/editor/common/modes');
import WinJS = require('vs/base/common/winjs.base'); import WinJS = require('vs/base/common/winjs.base');
import nls = require('vs/nls'); import nls = require('vs/nls');
import JSONWorker = require('vs/languages/json/common/jsonWorker'); import JSONWorker = require('vs/languages/json/common/jsonWorker');
import {INullService} from 'vs/platform/instantiation/common/instantiation'; import {INullService} from 'vs/platform/instantiation/common/instantiation';
import URI from 'vs/base/common/uri';
import {JSONLocation} from 'vs/languages/json/common/parser/jsonLocation';
var globProperties:Modes.ISuggestion[] = [ var globProperties:Modes.ISuggestion[] = [
{ type: 'value', label: nls.localize('fileLabel', "Files by Extension"), codeSnippet: '"**/*.{{extension}}": true', documentationLabel: nls.localize('fileDescription', "Match all files of a specific file extension.")}, { type: 'value', label: nls.localize('fileLabel', "Files by Extension"), codeSnippet: '"**/*.{{extension}}": true', documentationLabel: nls.localize('fileDescription', "Match all files of a specific file extension.")},
...@@ -32,27 +35,34 @@ export class GlobPatternContribution implements JSONWorker.IJSONWorkerContributi ...@@ -32,27 +35,34 @@ export class GlobPatternContribution implements JSONWorker.IJSONWorkerContributi
constructor(@INullService ns) { constructor(@INullService ns) {
} }
public collectDefaultSuggestions(contributionId: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { private isSettingsFile(resource: URI): boolean {
return WinJS.Promise.as(0); var path = resource.path;
return Strings.endsWith(path, '/settings.json');
} }
public collectPropertySuggestions(contributionId: string, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise { public collectDefaultSuggestions(resource: URI, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
if (contributionId === 'glob-pattern') { return null;
}
public collectPropertySuggestions(resource: URI, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise {
if (this.isSettingsFile(resource) && (location.matches(['files.exclude']) || location.matches(['search.exclude']))) {
globProperties.forEach((e) => result.add(e)); globProperties.forEach((e) => result.add(e));
} }
return WinJS.Promise.as(0); return null;
} }
public collectValueSuggestions(contributionId: string, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { public collectValueSuggestions(resource: URI, location: JSONLocation, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
if (contributionId === 'glob-pattern') { if (this.isSettingsFile(resource) && (location.matches(['files.exclude']) || location.matches(['search.exclude']))) {
globValues.forEach((e) => result.add(e)); globValues.forEach((e) => result.add(e));
} }
return WinJS.Promise.as(0); return null;
} }
public getInfoContribution(contributionId: string, pack: string): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> { public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
return null; return null;
} }
} }
\ No newline at end of file
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
'use strict'; 'use strict';
import HtmlContent = require('vs/base/common/htmlContent'); import HtmlContent = require('vs/base/common/htmlContent');
import Strings = require('vs/base/common/strings');
import WinJS = require('vs/base/common/winjs.base'); import WinJS = require('vs/base/common/winjs.base');
import nls = require('vs/nls'); import nls = require('vs/nls');
import JSONWorker = require('vs/languages/json/common/jsonWorker'); import JSONWorker = require('vs/languages/json/common/jsonWorker');
import {IRequestService} from 'vs/platform/request/common/request'; import {IRequestService} from 'vs/platform/request/common/request';
import URI from 'vs/base/common/uri';
import {JSONLocation} from 'vs/languages/json/common/parser/jsonLocation';
var LIMIT = 40; var LIMIT = 40;
...@@ -23,12 +26,17 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -23,12 +26,17 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi
private requestService : IRequestService; private requestService : IRequestService;
private isPackageJSONFile(resource: URI): boolean {
var path = resource.path;
return Strings.endsWith(path, '/package.json');
}
public constructor(@IRequestService requestService: IRequestService) { public constructor(@IRequestService requestService: IRequestService) {
this.requestService = requestService; this.requestService = requestService;
} }
public collectDefaultSuggestions(contributionId: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { public collectDefaultSuggestions(resource: URI, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
if (contributionId === 'http://json.schemastore.org/package') { if (this.isPackageJSONFile(resource)) {
var defaultValue = { var defaultValue = {
'name': '{{name}}', 'name': '{{name}}',
'description': '{{description}}', 'description': '{{description}}',
...@@ -39,11 +47,11 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -39,11 +47,11 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi
}; };
result.add({ type: 'module', label: nls.localize('json.package.default', 'Default package.json'), codeSnippet: JSON.stringify(defaultValue, null, '\t'), documentationLabel: '' }); result.add({ type: 'module', label: nls.localize('json.package.default', 'Default package.json'), codeSnippet: JSON.stringify(defaultValue, null, '\t'), documentationLabel: '' });
} }
return WinJS.Promise.as(0); return null;
} }
public collectPropertySuggestions(contributionId: string, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise { public collectPropertySuggestions(resource: URI, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise {
if (contributionId === 'npm-packages') { if (this.isPackageJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['devDependencies']) || location.matches(['optionalDependencies']) || location.matches(['peerDependencies']))) {
var queryUrl : string; var queryUrl : string;
if (currentWord.length > 0) { if (currentWord.length > 0) {
queryUrl = 'https://skimdb.npmjs.com/registry/_design/app/_view/browseAll?group_level=1&limit=' + LIMIT + '&start_key=%5B%22' + encodeURIComponent(currentWord) + '%22%5D&end_key=%5B%22'+ encodeURIComponent(currentWord + 'z') + '%22,%7B%7D%5D'; queryUrl = 'https://skimdb.npmjs.com/registry/_design/app/_view/browseAll?group_level=1&limit=' + LIMIT + '&start_key=%5B%22' + encodeURIComponent(currentWord) + '%22%5D&end_key=%5B%22'+ encodeURIComponent(currentWord + 'z') + '%22,%7B%7D%5D';
...@@ -99,11 +107,11 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -99,11 +107,11 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi
result.setAsIncomplete(); result.setAsIncomplete();
} }
} }
return WinJS.Promise.as(0); return null;
} }
public collectValueSuggestions(contributionId: string, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { public collectValueSuggestions(resource: URI, location: JSONLocation, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
if (contributionId === 'npm-packages') { if (this.isPackageJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['devDependencies']) || location.matches(['optionalDependencies']) || location.matches(['peerDependencies']))) {
var queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(currentKey) + '/latest'; var queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(currentKey) + '/latest';
return this.requestService.makeRequest({ return this.requestService.makeRequest({
...@@ -128,11 +136,13 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -128,11 +136,13 @@ export class PackageJSONContribution implements JSONWorker.IJSONWorkerContributi
return 0; return 0;
}); });
} }
return WinJS.Promise.as(0); return null;
} }
public getInfoContribution(contributionId: string, pack: string): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> { public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
if (contributionId === 'npm-package') { if (this.isPackageJSONFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) {
var pack = location.getSegments()[location.getSegments().length - 1];
var htmlContent : HtmlContent.IHTMLContentElement[] = []; var htmlContent : HtmlContent.IHTMLContentElement[] = [];
htmlContent.push({className: 'type', text: nls.localize('json.npm.package.hover', '{0}', pack) }); htmlContent.push({className: 'type', text: nls.localize('json.npm.package.hover', '{0}', pack) });
......
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
'use strict'; 'use strict';
import HtmlContent = require('vs/base/common/htmlContent'); import HtmlContent = require('vs/base/common/htmlContent');
import Strings = require('vs/base/common/strings');
import WinJS = require('vs/base/common/winjs.base'); import WinJS = require('vs/base/common/winjs.base');
import nls = require('vs/nls'); import nls = require('vs/nls');
import JSONWorker = require('vs/languages/json/common/jsonWorker'); import JSONWorker = require('vs/languages/json/common/jsonWorker');
import {IRequestService} from 'vs/platform/request/common/request'; import {IRequestService} from 'vs/platform/request/common/request';
import {JSONLocation} from 'vs/languages/json/common/parser/jsonLocation';
import URI from 'vs/base/common/uri';
var LIMIT = 40; var LIMIT = 40;
...@@ -20,8 +23,13 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -20,8 +23,13 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi
this.requestService = requestService; this.requestService = requestService;
} }
public collectDefaultSuggestions(contributionId: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { private isProjectJSONFile(resource: URI): boolean {
if (contributionId === 'http://json.schemastore.org/project') { var path = resource.path;
return Strings.endsWith(path, '/project.json');
}
public collectDefaultSuggestions(resource: URI, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
if (this.isProjectJSONFile(resource)) {
var defaultValue = { var defaultValue = {
'version': '{{1.0.0-*}}', 'version': '{{1.0.0-*}}',
'dependencies': {}, 'dependencies': {},
...@@ -32,11 +40,11 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -32,11 +40,11 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi
}; };
result.add({ type: 'type', label: nls.localize('json.project.default', 'Default project.json'), codeSnippet: JSON.stringify(defaultValue, null, '\t'), documentationLabel: '' }); result.add({ type: 'type', label: nls.localize('json.project.default', 'Default project.json'), codeSnippet: JSON.stringify(defaultValue, null, '\t'), documentationLabel: '' });
} }
return WinJS.Promise.as(0); return null;
} }
public collectPropertySuggestions(contributionId: string, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise { public collectPropertySuggestions(resource: URI, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: JSONWorker.ISuggestionsCollector) : WinJS.Promise {
if (contributionId === 'nugget-packages') { if (this.isProjectJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['frameworks', '*', 'dependencies']) || location.matches(['frameworks', '*', 'frameworkAssemblies']))) {
var queryUrl : string; var queryUrl : string;
if (currentWord.length > 0) { if (currentWord.length > 0) {
queryUrl = 'https://www.nuget.org/api/v2/Packages?' queryUrl = 'https://www.nuget.org/api/v2/Packages?'
...@@ -94,11 +102,11 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -94,11 +102,11 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi
return 0; return 0;
}); });
} }
return WinJS.Promise.as(0); return null;
} }
public collectValueSuggestions(contributionId: string, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise { public collectValueSuggestions(resource: URI, location: JSONLocation, currentKey: string, result: JSONWorker.ISuggestionsCollector): WinJS.Promise {
if (contributionId === 'nugget-packages') { if (this.isProjectJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['frameworks', '*', 'dependencies']) || location.matches(['frameworks', '*', 'frameworkAssemblies']))) {
var queryUrl = 'https://www.myget.org/F/aspnetrelease/api/v2/Packages?' var queryUrl = 'https://www.myget.org/F/aspnetrelease/api/v2/Packages?'
+ '$filter=Id%20eq%20\'' + '$filter=Id%20eq%20\''
+ encodeURIComponent(currentKey) + encodeURIComponent(currentKey)
...@@ -137,12 +145,12 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi ...@@ -137,12 +145,12 @@ export class ProjectJSONContribution implements JSONWorker.IJSONWorkerContributi
return 0; return 0;
}); });
} }
return WinJS.Promise.as(0); return null;
} }
public getInfoContribution(contributionId: string, pack: string): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> { public getInfoContribution(resource: URI, location: JSONLocation): WinJS.TPromise<HtmlContent.IHTMLContentElement[]> {
if (this.isProjectJSONFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['frameworks', '*', 'dependencies', '*']) || location.matches(['frameworks', '*', 'frameworkAssemblies', '*']))) {
if (contributionId === 'nugget-package') { var pack = location.getSegments()[location.getSegments().length - 1];
var htmlContent : HtmlContent.IHTMLContentElement[] = []; var htmlContent : HtmlContent.IHTMLContentElement[] = [];
htmlContent.push({className: 'type', text: nls.localize('json.nugget.package.hover', '{0}', pack) }); htmlContent.push({className: 'type', text: nls.localize('json.nugget.package.hover', '{0}', pack) });
......
...@@ -104,12 +104,19 @@ export class JSONIntellisense { ...@@ -104,12 +104,19 @@ export class JSONIntellisense {
if (schema) { if (schema) {
// property proposals with schema // property proposals with schema
var isLast = properties.length === 0 || offset >= properties[properties.length - 1].start; var isLast = properties.length === 0 || offset >= properties[properties.length - 1].start;
this.getPropertySuggestions(resource, schema, doc, node, currentKey, addValue, isLast, collector);
collectionPromises.push(this.getPropertySuggestions(schema, doc, node, currentKey, addValue, isLast, collector));
} else if (node.parent) { } else if (node.parent) {
// property proposals without schema // property proposals without schema
collectionPromises.push(this.getSchemaLessPropertySuggestions(doc, node, collector)); this.getSchemaLessPropertySuggestions(doc, node, collector);
} }
var location = node.getNodeLocation();
this.contributions.forEach((contribution) => {
var collectPromise = contribution.collectPropertySuggestions(resource, location, currentWord, addValue, isLast, collector);
if (collectPromise) {
collectionPromises.push();
}
});
} }
// proposals for values // proposals for values
...@@ -122,20 +129,46 @@ export class JSONIntellisense { ...@@ -122,20 +129,46 @@ export class JSONIntellisense {
if (schema) { if (schema) {
// value proposals with schema // value proposals with schema
collectionPromises.push(this.getValueSuggestions(schema, doc, node, offset, collector)); this.getValueSuggestions(resource, schema, doc, node, offset, collector);
} else { } else {
// value proposals without schema // value proposals without schema
collectionPromises.push(this.getSchemaLessValueSuggestions(doc, node, offset, modelMirror, collector)); this.getSchemaLessValueSuggestions(doc, node, offset, modelMirror, collector);
}
if (!node) {
this.contributions.forEach((contribution) => {
var collectPromise = contribution.collectDefaultSuggestions(resource, collector);
if (collectPromise) {
collectionPromises.push(collectPromise);
}
});
} else {
if ((node.type === 'property') && offset > (<Parser.PropertyASTNode> node).colonOffset) {
var parentKey = (<Parser.PropertyASTNode>node).key.value;
var valueNode = (<Parser.PropertyASTNode> node).value;
if (!valueNode || offset <= valueNode.end) {
var location = node.parent.getNodeLocation();
this.contributions.forEach((contribution) => {
var collectPromise = contribution.collectValueSuggestions(resource, location, parentKey, collector);
if (collectPromise) {
collectionPromises.push(collectPromise);
}
});
} }
}
}
return WinJS.Promise.join(collectionPromises).then(() => { return result; } ); return WinJS.Promise.join(collectionPromises).then(() => { return result; } );
}); });
} }
private getPropertySuggestions(schema: SchemaService.ResolvedSchema, doc: Parser.JSONDocument, node: Parser.ASTNode, currentWord: string, addValue: boolean, isLast: boolean, collector: JsonWorker.ISuggestionsCollector): WinJS.Promise { private getPropertySuggestions(resource: URI, schema: SchemaService.ResolvedSchema, doc: Parser.JSONDocument, node: Parser.ASTNode, currentWord: string, addValue: boolean, isLast: boolean, collector: JsonWorker.ISuggestionsCollector): void {
var matchingSchemas: Parser.IApplicableSchema[] = []; var matchingSchemas: Parser.IApplicableSchema[] = [];
doc.validate(schema.schema, matchingSchemas, node.start); doc.validate(schema.schema, matchingSchemas, node.start);
var collectPromises: WinJS.TPromise<Modes.ISuggestion[]>[] = []; var collectPromises: WinJS.TPromise<Modes.ISuggestion[]>[] = [];
matchingSchemas.forEach((s) => { matchingSchemas.forEach((s) => {
if (s.node === node && !s.inverted) { if (s.node === node && !s.inverted) {
var schemaProperties = s.schema.properties; var schemaProperties = s.schema.properties;
...@@ -145,19 +178,11 @@ export class JSONIntellisense { ...@@ -145,19 +178,11 @@ export class JSONIntellisense {
collector.add({ type: 'property', label: key, codeSnippet: this.getSnippetForProperty(key, propertySchema, addValue, isLast), documentationLabel: propertySchema.description || '' }); collector.add({ type: 'property', label: key, codeSnippet: this.getSnippetForProperty(key, propertySchema, addValue, isLast), documentationLabel: propertySchema.description || '' });
}); });
} }
var contributionKey = s.schema.id;
if (contributionKey) {
this.contributions.forEach((contribution) => {
collectPromises.push(contribution.collectPropertySuggestions(contributionKey, currentWord, addValue, isLast, collector));
});
}
} }
}); });
return WinJS.Promise.join(collectPromises);
} }
private getSchemaLessPropertySuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, collector: JsonWorker.ISuggestionsCollector): WinJS.Promise { private getSchemaLessPropertySuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, collector: JsonWorker.ISuggestionsCollector): void {
var collectSuggestionsForSimilarObject = (obj: Parser.ObjectASTNode) => { var collectSuggestionsForSimilarObject = (obj: Parser.ObjectASTNode) => {
obj.properties.forEach((p) => { obj.properties.forEach((p) => {
var key = p.key.value; var key = p.key.value;
...@@ -181,10 +206,9 @@ export class JSONIntellisense { ...@@ -181,10 +206,9 @@ export class JSONIntellisense {
} }
}); });
} }
return WinJS.Promise.as(0);
} }
public getSchemaLessValueSuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, offset: number, modelMirror: EditorCommon.IMirrorModel, collector: JsonWorker.ISuggestionsCollector): WinJS.Promise { public getSchemaLessValueSuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, offset: number, modelMirror: EditorCommon.IMirrorModel, collector: JsonWorker.ISuggestionsCollector): void {
var collectSuggestionsForValues = (value: Parser.ASTNode) => { var collectSuggestionsForValues = (value: Parser.ASTNode) => {
var content = this.getMatchingSnippet(value, modelMirror); var content = this.getMatchingSnippet(value, modelMirror);
collector.add({ type: this.getSuggestionType(value.type), label: content, codeSnippet: content, documentationLabel: '' }); collector.add({ type: this.getSuggestionType(value.type), label: content, codeSnippet: content, documentationLabel: '' });
...@@ -231,24 +255,20 @@ export class JSONIntellisense { ...@@ -231,24 +255,20 @@ export class JSONIntellisense {
} }
} }
} }
return WinJS.Promise.as(0);
} }
public getValueSuggestions(schema: SchemaService.ResolvedSchema, doc: Parser.JSONDocument, node: Parser.ASTNode, offset: number, collector: JsonWorker.ISuggestionsCollector) : WinJS.Promise { public getValueSuggestions(resource: URI, schema: SchemaService.ResolvedSchema, doc: Parser.JSONDocument, node: Parser.ASTNode, offset: number, collector: JsonWorker.ISuggestionsCollector) : void {
var collectPromises: WinJS.TPromise<Modes.ISuggestion[]>[] = []; var collectPromises: WinJS.TPromise<Modes.ISuggestion[]>[] = [];
if (!node) { if (!node) {
this.addDefaultSuggestion(schema.schema, collector); this.addDefaultSuggestion(schema.schema, collector);
this.contributions.forEach((contribution) => {
collectPromises.push(contribution.collectDefaultSuggestions(schema.schema.id, collector));
});
} else { } else {
var parentKey: string = null; var parentKey: string = null;
if (node && (node.type === 'property') && offset > (<Parser.PropertyASTNode> node).colonOffset) { if (node && (node.type === 'property') && offset > (<Parser.PropertyASTNode> node).colonOffset) {
var valueNode = (<Parser.PropertyASTNode> node).value; var valueNode = (<Parser.PropertyASTNode> node).value;
if (valueNode && offset > valueNode.end) { if (valueNode && offset > valueNode.end) {
return WinJS.Promise.as(0); // we are past the value node return; // we are past the value node
} }
parentKey = (<Parser.PropertyASTNode>node).key.value; parentKey = (<Parser.PropertyASTNode>node).key.value;
node = node.parent; node = node.parent;
...@@ -256,6 +276,7 @@ export class JSONIntellisense { ...@@ -256,6 +276,7 @@ export class JSONIntellisense {
if (node && (parentKey !== null || node.type === 'array')) { if (node && (parentKey !== null || node.type === 'array')) {
var matchingSchemas: Parser.IApplicableSchema[] = []; var matchingSchemas: Parser.IApplicableSchema[] = [];
doc.validate(schema.schema, matchingSchemas, node.start); doc.validate(schema.schema, matchingSchemas, node.start);
matchingSchemas.forEach((s) => { matchingSchemas.forEach((s) => {
if (s.node === node && !s.inverted && s.schema) { if (s.node === node && !s.inverted && s.schema) {
if (s.schema.items) { if (s.schema.items) {
...@@ -269,19 +290,11 @@ export class JSONIntellisense { ...@@ -269,19 +290,11 @@ export class JSONIntellisense {
this.addEnumSuggestion(propertySchema, collector); this.addEnumSuggestion(propertySchema, collector);
} }
} }
var contributionKey = s.schema.id;
if (contributionKey) {
this.contributions.forEach((contribution) => {
collectPromises.push(contribution.collectValueSuggestions(contributionKey, parentKey, collector));
});
}
} }
}); });
} }
} }
return WinJS.Promise.join(collectPromises);
} }
private addBooleanSuggestion(value: boolean, collector: JsonWorker.ISuggestionsCollector): void { private addBooleanSuggestion(value: boolean, collector: JsonWorker.ISuggestionsCollector): void {
......
...@@ -32,6 +32,7 @@ import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; ...@@ -32,6 +32,7 @@ import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import {ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import {IResourceService} from 'vs/editor/common/services/resourceService'; import {IResourceService} from 'vs/editor/common/services/resourceService';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {JSONLocation} from './parser/jsonLocation';
export interface IOptionsSchema { export interface IOptionsSchema {
/** /**
...@@ -64,10 +65,10 @@ export interface ISuggestionsCollector { ...@@ -64,10 +65,10 @@ export interface ISuggestionsCollector {
} }
export interface IJSONWorkerContribution { export interface IJSONWorkerContribution {
getInfoContribution(contributionId: string, propertyKey: string) : WinJS.TPromise<HtmlContent.IHTMLContentElement[]>; getInfoContribution(resource: URI, location: JSONLocation) : WinJS.TPromise<HtmlContent.IHTMLContentElement[]>;
collectPropertySuggestions(contributionId: string, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : WinJS.Promise; collectPropertySuggestions(resource: URI, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : WinJS.Promise;
collectValueSuggestions(contributionId: string, propertyKey: string, result: ISuggestionsCollector): WinJS.Promise; collectValueSuggestions(resource: URI, location: JSONLocation, propertyKey: string, result: ISuggestionsCollector): WinJS.Promise;
collectDefaultSuggestions(contributionId: string, result: ISuggestionsCollector): WinJS.Promise; collectDefaultSuggestions(resource: URI, result: ISuggestionsCollector): WinJS.Promise;
} }
export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSupport { export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSupport {
...@@ -235,15 +236,14 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu ...@@ -235,15 +236,14 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu
return true; return true;
}); });
if (contributonId && node.name) { var location = node.getNodeLocation();
for (var i= this.contributions.length -1; i >= 0; i--) { for (var i= this.contributions.length -1; i >= 0; i--) {
var contribution = this.contributions[i]; var contribution = this.contributions[i];
var promise = contribution.getInfoContribution(contributonId, node.name); var promise = contribution.getInfoContribution(resource, location);
if (promise) { if (promise) {
return promise.then((htmlContent) => { return this.createInfoResult(htmlContent, originalNode, modelMirror); } ); return promise.then((htmlContent) => { return this.createInfoResult(htmlContent, originalNode, modelMirror); } );
} }
} }
}
if (description) { if (description) {
var htmlContent = [ {className: 'documentation', text: description } ]; var htmlContent = [ {className: 'documentation', text: description } ];
...@@ -356,7 +356,8 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu ...@@ -356,7 +356,8 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu
} }
}; };
return this.jsonIntellisense.getValueSuggestions(schema, doc, node.parent, node.start, collector).then(() => { this.jsonIntellisense.getValueSuggestions(resource, schema, doc, node.parent, node.start, collector);
var range = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start); var range = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start);
var text = modelMirror.getValueInRange(range); var text = modelMirror.getValueInRange(range);
for (var i = 0, len = proposals.length; i < len; i++) { for (var i = 0, len = proposals.length; i < len; i++) {
...@@ -377,7 +378,6 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu ...@@ -377,7 +378,6 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu
} }
} }
return null; return null;
});
} }
}); });
} }
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export class JSONLocation {
private segments: string[];
constructor(segments: string[]) {
this.segments = segments;
}
public append(segment: string) : JSONLocation {
return new JSONLocation(this.segments.concat(segment));
}
public getSegments() {
return this.segments;
}
public matches(segments: string[]) {
var k = 0;
for (var i= 0; k < segments.length && i < this.segments.length; i++) {
if (segments[k] === this.segments[i] || segments[k] === '*') {
k++;
} else if (segments[k] !== '**') {
return false;
}
}
return k === segments.length;
}
public toString() : string {
return '[' + this.segments.join('][') + ']';
}
}
\ No newline at end of file
...@@ -9,6 +9,7 @@ import Arrays = require('vs/base/common/arrays'); ...@@ -9,6 +9,7 @@ import Arrays = require('vs/base/common/arrays');
import Types = require('vs/base/common/types'); import Types = require('vs/base/common/types');
import Json = require('vs/base/common/json'); import Json = require('vs/base/common/json');
import JsonSchema = require('vs/base/common/jsonSchema'); import JsonSchema = require('vs/base/common/jsonSchema');
import {JSONLocation} from './jsonLocation';
import SchemaService = require('vs/languages/json/common/jsonSchemaService'); import SchemaService = require('vs/languages/json/common/jsonSchemaService');
export interface IRange { export interface IRange {
...@@ -36,20 +37,14 @@ export class ASTNode { ...@@ -36,20 +37,14 @@ export class ASTNode {
this.parent = parent; this.parent = parent;
} }
public getPath():string[] { public getNodeLocation(): JSONLocation {
var path:string[] = []; var path = this.parent ? this.parent.getNodeLocation() : new JSONLocation([]);
if (this.parent) {
path = this.parent.getPath();
if (this.name) { if (this.name) {
path.push(this.name); path = path.append(this.name);
} }
return path;
} else {
return path; return path;
} }
}
public getChildNodes(): ASTNode[] { public getChildNodes(): ASTNode[] {
return []; return [];
...@@ -925,7 +920,7 @@ export class JSONParser { ...@@ -925,7 +920,7 @@ export class JSONParser {
_scanner.scan(); // consume ColonToken _scanner.scan(); // consume ColonToken
if (!node.setValue(_parseValue(node, node.key.getValue()))) { if (!node.setValue(_parseValue(node, key.value))) {
return _error(nls.localize('ValueExpected', 'Value expected'), node, [], [Json.SyntaxKind.CloseBraceToken, Json.SyntaxKind.CommaToken]); return _error(nls.localize('ValueExpected', 'Value expected'), node, [], [Json.SyntaxKind.CloseBraceToken, Json.SyntaxKind.CommaToken]);
} }
node.end = node.value.end; node.end = node.value.end;
...@@ -1013,7 +1008,7 @@ export class JSONParser { ...@@ -1013,7 +1008,7 @@ export class JSONParser {
_scanner.scan(); _scanner.scan();
_doc.root = _parseValue(null, 'root'); _doc.root = _parseValue(null, null);
if (!_doc.root) { if (!_doc.root) {
_error(nls.localize('Invalid symbol', 'Expected a JSON object, array or literal')); _error(nls.localize('Invalid symbol', 'Expected a JSON object, array or literal'));
} else if (_scanner.getToken() !== Json.SyntaxKind.EOF) { } else if (_scanner.getToken() !== Json.SyntaxKind.EOF) {
......
...@@ -104,7 +104,7 @@ suite('JSON - Parsing', () => { ...@@ -104,7 +104,7 @@ suite('JSON - Parsing', () => {
var node = result.getNodeFromOffset(1); var node = result.getNodeFromOffset(1);
assert.equal(node.type, 'object'); assert.equal(node.type, 'object');
assert.deepEqual(node.getPath(), []); assert.deepEqual(node.getNodeLocation().getSegments(), []);
assert.strictEqual(result.getNodeFromOffset(2), null); assert.strictEqual(result.getNodeFromOffset(2), null);
...@@ -114,8 +114,7 @@ suite('JSON - Parsing', () => { ...@@ -114,8 +114,7 @@ suite('JSON - Parsing', () => {
node = result.getNodeFromOffset(2); node = result.getNodeFromOffset(2);
assert.equal(node.type, 'null'); assert.equal(node.type, 'null');
assert.equal(node.name, '0'); assert.deepEqual(node.getNodeLocation().getSegments(), ['0']);
assert.deepEqual(node.getPath(), ['0']);
result = parser.parse('{"a":true}'); result = parser.parse('{"a":true}');
assert.strictEqual(result.errors.length, 0); assert.strictEqual(result.errors.length, 0);
...@@ -124,7 +123,7 @@ suite('JSON - Parsing', () => { ...@@ -124,7 +123,7 @@ suite('JSON - Parsing', () => {
assert.equal(node.type, 'string'); assert.equal(node.type, 'string');
assert.equal((<Parser.StringASTNode>node).isKey, true); assert.equal((<Parser.StringASTNode>node).isKey, true);
assert.deepEqual(node.getPath(), ['a']); assert.deepEqual(node.getNodeLocation().getSegments(), ['a']);
node = result.getNodeFromOffset(4); node = result.getNodeFromOffset(4);
...@@ -141,8 +140,7 @@ suite('JSON - Parsing', () => { ...@@ -141,8 +140,7 @@ suite('JSON - Parsing', () => {
node = result.getNodeFromOffset(5); node = result.getNodeFromOffset(5);
assert.equal(node.type, 'boolean'); assert.equal(node.type, 'boolean');
assert.equal(node.name, 'a'); assert.deepEqual(node.getNodeLocation().getSegments(), ['a']);
assert.deepEqual(node.getPath(), ['a']);
}); });
...@@ -155,14 +153,14 @@ suite('JSON - Parsing', () => { ...@@ -155,14 +153,14 @@ suite('JSON - Parsing', () => {
assert.strictEqual(result.errors.length, 0); assert.strictEqual(result.errors.length, 0);
var node = result.getNodeFromOffset(content.indexOf('key2') + 2); var node = result.getNodeFromOffset(content.indexOf('key2') + 2);
var path = node.getPath(); var location = node.getNodeLocation();
assert.deepEqual(path, ['key', 'key2']); assert.deepEqual(location.getSegments(), ['key', 'key2']);
node = result.getNodeFromOffset(content.indexOf('42') + 1); node = result.getNodeFromOffset(content.indexOf('42') + 1);
path = node.getPath(); location = node.getNodeLocation();
assert.deepEqual(path, ['key', 'key2']); assert.deepEqual(location.getSegments(), ['key', 'key2']);
}); });
test('Nested AST in Array', function() { test('Nested AST in Array', function() {
...@@ -173,9 +171,9 @@ suite('JSON - Parsing', () => { ...@@ -173,9 +171,9 @@ suite('JSON - Parsing', () => {
assert.strictEqual(result.errors.length, 0); assert.strictEqual(result.errors.length, 0);
var node = result.getNodeFromOffset(17); var node = result.getNodeFromOffset(17);
var path = node.getPath(); var location = node.getNodeLocation();
assert.deepEqual(path, ['key', '0', 'key2']); assert.deepEqual(location.getSegments(), ['key', '0', 'key2']);
}); });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册