JSON completion contributors
This commit is contained in:
parent
1a7316771f
commit
0587f20cd7
|
@ -10,45 +10,52 @@ import Parser = require('./jsonParser');
|
|||
import SchemaService = require('./jsonSchemaService');
|
||||
import JsonSchema = require('./json-toolbox/jsonSchema');
|
||||
import nls = require('./utils/nls');
|
||||
import {IJSONWorkerContribution} from './jsonContributions';
|
||||
|
||||
import {CompletionItem, CompletionItemKind, CompletionOptions, ITextDocument, TextDocumentIdentifier, TextDocumentPosition, Range, TextEdit} from 'vscode-languageserver';
|
||||
|
||||
export interface ISuggestionsCollector {
|
||||
add(suggestion: CompletionItem): void;
|
||||
error(message: string): void;
|
||||
error(message:string): void;
|
||||
setAsIncomplete(): void;
|
||||
}
|
||||
|
||||
export class JSONCompletion {
|
||||
|
||||
private schemaService: SchemaService.IJSONSchemaService;
|
||||
private contributions: IJSONWorkerContribution[];
|
||||
|
||||
constructor(schemaService: SchemaService.IJSONSchemaService) {
|
||||
constructor(schemaService: SchemaService.IJSONSchemaService, contributions: IJSONWorkerContribution[] = []) {
|
||||
this.schemaService = schemaService;
|
||||
this.contributions = contributions;
|
||||
}
|
||||
|
||||
public doSuggest(document: ITextDocument, textDocumentPosition: TextDocumentPosition, doc: Parser.JSONDocument): Thenable<CompletionItem[]> {
|
||||
|
||||
var offset = document.offsetAt(textDocumentPosition.position);
|
||||
var node = doc.getNodeFromOffsetEndInclusive(offset);
|
||||
|
||||
var overwriteRange = null;
|
||||
var result: CompletionItem[] = [];
|
||||
let offset = document.offsetAt(textDocumentPosition.position);
|
||||
let node = doc.getNodeFromOffsetEndInclusive(offset);
|
||||
|
||||
let overwriteRange = null;
|
||||
let result: CompletionItem[] = [];
|
||||
|
||||
if (node && (node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) {
|
||||
overwriteRange = Range.create(document.positionAt(node.start), document.positionAt(node.end));
|
||||
}
|
||||
|
||||
var proposed: { [key: string]: boolean } = {};
|
||||
var collector: ISuggestionsCollector = {
|
||||
let proposed: { [key: string]: boolean } = {};
|
||||
let collector: ISuggestionsCollector = {
|
||||
add: (suggestion: CompletionItem) => {
|
||||
if (!proposed[suggestion.label]) {
|
||||
proposed[suggestion.label] = true;
|
||||
if (overwriteRange) {
|
||||
suggestion.textEdit = TextEdit.replace(overwriteRange, suggestion.insertText);
|
||||
}
|
||||
|
||||
|
||||
result.push(suggestion);
|
||||
}
|
||||
},
|
||||
setAsIncomplete: () => {
|
||||
|
||||
},
|
||||
error: (message: string) => {
|
||||
console.log(message);
|
||||
|
@ -56,17 +63,21 @@ export class JSONCompletion {
|
|||
};
|
||||
|
||||
return this.schemaService.getSchemaForResource(textDocumentPosition.uri, doc).then((schema) => {
|
||||
var addValue = true;
|
||||
var currentKey = '';
|
||||
var currentProperty: Parser.PropertyASTNode = null;
|
||||
let collectionPromises: Thenable<any>[] = [];
|
||||
|
||||
let addValue = true;
|
||||
let currentKey = '';
|
||||
let currentWord = '';
|
||||
let currentProperty: Parser.PropertyASTNode = null;
|
||||
if (node) {
|
||||
|
||||
if (node.type === 'string') {
|
||||
var stringNode = <Parser.StringASTNode>node;
|
||||
let stringNode = <Parser.StringASTNode>node;
|
||||
if (stringNode.isKey) {
|
||||
addValue = !(node.parent && ((<Parser.PropertyASTNode>node.parent).value));
|
||||
currentProperty = node.parent ? <Parser.PropertyASTNode>node.parent : null;
|
||||
currentKey = document.getText().substr(node.start + 1, node.end - node.start - 1);
|
||||
currentKey = document.getText().substring(node.start + 1, node.end - 1);
|
||||
currentWord = document.getText().substring(node.start + 1, offset);
|
||||
if (node.parent) {
|
||||
node = node.parent.parent;
|
||||
}
|
||||
|
@ -82,21 +93,29 @@ export class JSONCompletion {
|
|||
return result;
|
||||
}
|
||||
// don't suggest properties that are already present
|
||||
var properties = (<Parser.ObjectASTNode>node).properties;
|
||||
let properties = (<Parser.ObjectASTNode>node).properties;
|
||||
properties.forEach(p => {
|
||||
if (!currentProperty || currentProperty !== p) {
|
||||
proposed[p.key.value] = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let isLast = properties.length === 0 || offset >= properties[properties.length - 1].start;
|
||||
if (schema) {
|
||||
// property proposals with schema
|
||||
var isLast = properties.length === 0 || offset >= properties[properties.length - 1].start;
|
||||
this.getPropertySuggestions(schema, doc, node, currentKey, addValue, isLast, collector);
|
||||
} else if (node.parent) {
|
||||
// property proposals without schema
|
||||
this.getSchemaLessPropertySuggestions(doc, node, collector);
|
||||
}
|
||||
|
||||
let location = node.getNodeLocation();
|
||||
this.contributions.forEach((contribution) => {
|
||||
let collectPromise = contribution.collectPropertySuggestions(textDocumentPosition.uri, location, this.getCurrentWord(document, offset), addValue, isLast, collector);
|
||||
if (collectPromise) {
|
||||
collectionPromises.push(collectPromise);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
@ -112,23 +131,43 @@ export class JSONCompletion {
|
|||
// value proposals without schema
|
||||
this.getSchemaLessValueSuggestions(doc, node, offset, document, collector);
|
||||
}
|
||||
if (!node) {
|
||||
this.contributions.forEach((contribution) => {
|
||||
let collectPromise = contribution.collectDefaultSuggestions(textDocumentPosition.uri, collector);
|
||||
if (collectPromise) {
|
||||
collectionPromises.push(collectPromise);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if ((node.type === 'property') && offset > (<Parser.PropertyASTNode> node).colonOffset) {
|
||||
let parentKey = (<Parser.PropertyASTNode>node).key.value;
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
let valueNode = (<Parser.PropertyASTNode> node).value;
|
||||
if (!valueNode || offset <= valueNode.end) {
|
||||
let location = node.parent.getNodeLocation();
|
||||
this.contributions.forEach((contribution) => {
|
||||
let collectPromise = contribution.collectValueSuggestions(textDocumentPosition.uri, location, parentKey, collector);
|
||||
if (collectPromise) {
|
||||
collectionPromises.push(collectPromise);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.all(collectionPromises).then(() => result );
|
||||
});
|
||||
}
|
||||
|
||||
private getPropertySuggestions(schema: SchemaService.ResolvedSchema, doc: Parser.JSONDocument, node: Parser.ASTNode, currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): void {
|
||||
var matchingSchemas: Parser.IApplicableSchema[] = [];
|
||||
let matchingSchemas: Parser.IApplicableSchema[] = [];
|
||||
doc.validate(schema.schema, matchingSchemas, node.start);
|
||||
|
||||
matchingSchemas.forEach((s) => {
|
||||
if (s.node === node && !s.inverted) {
|
||||
var schemaProperties = s.schema.properties;
|
||||
let schemaProperties = s.schema.properties;
|
||||
if (schemaProperties) {
|
||||
Object.keys(schemaProperties).forEach((key: string) => {
|
||||
var propertySchema = schemaProperties[key];
|
||||
let propertySchema = schemaProperties[key];
|
||||
collector.add({ kind: CompletionItemKind.Property, label: key, insertText: this.getSnippetForProperty(key, propertySchema, addValue, isLast), documentation: propertySchema.description || '' });
|
||||
});
|
||||
}
|
||||
|
@ -137,15 +176,15 @@ export class JSONCompletion {
|
|||
}
|
||||
|
||||
private getSchemaLessPropertySuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, collector: ISuggestionsCollector): void {
|
||||
var collectSuggestionsForSimilarObject = (obj: Parser.ObjectASTNode) => {
|
||||
let collectSuggestionsForSimilarObject = (obj: Parser.ObjectASTNode) => {
|
||||
obj.properties.forEach((p) => {
|
||||
var key = p.key.value;
|
||||
let key = p.key.value;
|
||||
collector.add({ kind: CompletionItemKind.Property, label: key, insertText: this.getSnippetForSimilarProperty(key, p.value), documentation: '' });
|
||||
});
|
||||
};
|
||||
if (node.parent.type === 'property') {
|
||||
// if the object is a property value, check the tree for other objects that hang under a property of the same name
|
||||
var parentKey = (<Parser.PropertyASTNode>node.parent).key.value;
|
||||
let parentKey = (<Parser.PropertyASTNode>node.parent).key.value;
|
||||
doc.visit((n) => {
|
||||
if (n.type === 'property' && (<Parser.PropertyASTNode>n).key.value === parentKey && (<Parser.PropertyASTNode>n).value && (<Parser.PropertyASTNode>n).value.type === 'object') {
|
||||
collectSuggestionsForSimilarObject(<Parser.ObjectASTNode>(<Parser.PropertyASTNode>n).value);
|
||||
|
@ -163,8 +202,8 @@ export class JSONCompletion {
|
|||
}
|
||||
|
||||
private getSchemaLessValueSuggestions(doc: Parser.JSONDocument, node: Parser.ASTNode, offset: number, document: ITextDocument, collector: ISuggestionsCollector): void {
|
||||
var collectSuggestionsForValues = (value: Parser.ASTNode) => {
|
||||
var content = this.getMatchingSnippet(value, document);
|
||||
let collectSuggestionsForValues = (value: Parser.ASTNode) => {
|
||||
let content = this.getMatchingSnippet(value, document);
|
||||
collector.add({ kind: this.getSuggestionKind(value.type), label: content, insertText: content, documentation: '' });
|
||||
if (value.type === 'boolean') {
|
||||
this.addBooleanSuggestion(!value.getValue(), collector);
|
||||
|
@ -176,12 +215,12 @@ export class JSONCompletion {
|
|||
collector.add({ kind: this.getSuggestionKind('array'), label: 'Empty array', insertText: '[\n\t{{}}\n]', documentation: '' });
|
||||
} else {
|
||||
if (node.type === 'property' && offset > (<Parser.PropertyASTNode>node).colonOffset) {
|
||||
var valueNode = (<Parser.PropertyASTNode>node).value;
|
||||
let valueNode = (<Parser.PropertyASTNode>node).value;
|
||||
if (valueNode && offset > valueNode.end) {
|
||||
return;
|
||||
}
|
||||
// suggest values at the same key
|
||||
var parentKey = (<Parser.PropertyASTNode>node).key.value;
|
||||
let parentKey = (<Parser.PropertyASTNode>node).key.value;
|
||||
doc.visit((n) => {
|
||||
if (n.type === 'property' && (<Parser.PropertyASTNode>n).key.value === parentKey && (<Parser.PropertyASTNode>n).value) {
|
||||
collectSuggestionsForValues((<Parser.PropertyASTNode>n).value);
|
||||
|
@ -192,7 +231,7 @@ export class JSONCompletion {
|
|||
if (node.type === 'array') {
|
||||
if (node.parent && node.parent.type === 'property') {
|
||||
// suggest items of an array at the same key
|
||||
var parentKey = (<Parser.PropertyASTNode>node.parent).key.value;
|
||||
let parentKey = (<Parser.PropertyASTNode>node.parent).key.value;
|
||||
doc.visit((n) => {
|
||||
if (n.type === 'property' && (<Parser.PropertyASTNode>n).key.value === parentKey && (<Parser.PropertyASTNode>n).value && (<Parser.PropertyASTNode>n).value.type === 'array') {
|
||||
((<Parser.ArrayASTNode>(<Parser.PropertyASTNode>n).value).items).forEach((n) => {
|
||||
|
@ -217,9 +256,9 @@ export class JSONCompletion {
|
|||
if (!node) {
|
||||
this.addDefaultSuggestion(schema.schema, collector);
|
||||
} else {
|
||||
var parentKey: string = null;
|
||||
let parentKey: string = null;
|
||||
if (node && (node.type === 'property') && offset > (<Parser.PropertyASTNode>node).colonOffset) {
|
||||
var valueNode = (<Parser.PropertyASTNode>node).value;
|
||||
let valueNode = (<Parser.PropertyASTNode>node).value;
|
||||
if (valueNode && offset > valueNode.end) {
|
||||
return; // we are past the value node
|
||||
}
|
||||
|
@ -227,7 +266,7 @@ export class JSONCompletion {
|
|||
node = node.parent;
|
||||
}
|
||||
if (node && (parentKey !== null || node.type === 'array')) {
|
||||
var matchingSchemas: Parser.IApplicableSchema[] = [];
|
||||
let matchingSchemas: Parser.IApplicableSchema[] = [];
|
||||
doc.validate(schema.schema, matchingSchemas, node.start);
|
||||
|
||||
matchingSchemas.forEach((s) => {
|
||||
|
@ -237,7 +276,7 @@ export class JSONCompletion {
|
|||
this.addEnumSuggestion(s.schema.items, collector);
|
||||
}
|
||||
if (s.schema.properties) {
|
||||
var propertySchema = s.schema.properties[parentKey];
|
||||
let propertySchema = s.schema.properties[parentKey];
|
||||
if (propertySchema) {
|
||||
this.addDefaultSuggestion(propertySchema, collector);
|
||||
this.addEnumSuggestion(propertySchema, collector);
|
||||
|
@ -293,7 +332,7 @@ export class JSONCompletion {
|
|||
}
|
||||
|
||||
private getLabelForValue(value: any): string {
|
||||
var label = JSON.stringify(value);
|
||||
let label = JSON.stringify(value);
|
||||
label = label.replace('{{', '').replace('}}', '');
|
||||
if (label.length > 57) {
|
||||
return label.substr(0, 57).trim() + '...';
|
||||
|
@ -302,7 +341,7 @@ export class JSONCompletion {
|
|||
}
|
||||
|
||||
private getSnippetForValue(value: any): string {
|
||||
var snippet = JSON.stringify(value, null, '\t');
|
||||
let snippet = JSON.stringify(value, null, '\t');
|
||||
switch (typeof value) {
|
||||
case 'object':
|
||||
if (value === null) {
|
||||
|
@ -320,7 +359,7 @@ export class JSONCompletion {
|
|||
|
||||
private getSuggestionKind(type: any): CompletionItemKind {
|
||||
if (Array.isArray(type)) {
|
||||
var array = <any[]>type;
|
||||
let array = <any[]>type;
|
||||
type = array.length > 0 ? array[0] : null;
|
||||
}
|
||||
if (!type) {
|
||||
|
@ -342,20 +381,20 @@ export class JSONCompletion {
|
|||
case 'object':
|
||||
return '{}';
|
||||
default:
|
||||
var content = document.getText().substr(node.start, node.end - node.start);
|
||||
let content = document.getText().substr(node.start, node.end - node.start);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
private getSnippetForProperty(key: string, propertySchema: JsonSchema.IJSONSchema, addValue: boolean, isLast: boolean): string {
|
||||
|
||||
var result = '"' + key + '"';
|
||||
let result = '"' + key + '"';
|
||||
if (!addValue) {
|
||||
return result;
|
||||
}
|
||||
result += ': ';
|
||||
|
||||
var defaultVal = propertySchema.default;
|
||||
let defaultVal = propertySchema.default;
|
||||
if (typeof defaultVal !== 'undefined') {
|
||||
result = result + this.getSnippetForValue(defaultVal);
|
||||
} else if (propertySchema.enum && propertySchema.enum.length > 0) {
|
||||
|
@ -393,4 +432,13 @@ export class JSONCompletion {
|
|||
private getSnippetForSimilarProperty(key: string, templateValue: Parser.ASTNode): string {
|
||||
return '"' + key + '"';
|
||||
}
|
||||
}
|
||||
|
||||
private getCurrentWord(document: ITextDocument, offset: number) {
|
||||
var i = offset - 1;
|
||||
var text = document.getText();
|
||||
while (i >= 0 && ' \t\n\r\v"'.indexOf(text.charAt(i)) === -1) {
|
||||
i--;
|
||||
}
|
||||
return text.substring(i+1, offset);
|
||||
}
|
||||
}
|
20
extensions/json/server/src/jsonContributions.ts
Normal file
20
extensions/json/server/src/jsonContributions.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {JSONLocation} from './jsonLocation';
|
||||
import {ISuggestionsCollector} from './jsonCompletion';
|
||||
|
||||
import {MarkedString} from 'vscode-languageserver';
|
||||
|
||||
export {ISuggestionsCollector} from './jsonCompletion';
|
||||
|
||||
|
||||
export interface IJSONWorkerContribution {
|
||||
getInfoContribution(resource: string, location: JSONLocation) : Thenable<MarkedString[]>;
|
||||
collectPropertySuggestions(resource: string, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : Thenable<any>;
|
||||
collectValueSuggestions(resource: string, location: JSONLocation, propertyKey: string, result: ISuggestionsCollector): Thenable<any>;
|
||||
collectDefaultSuggestions(resource: string, result: ISuggestionsCollector): Thenable<any>;
|
||||
}
|
|
@ -7,15 +7,18 @@
|
|||
|
||||
import Parser = require('./jsonParser');
|
||||
import SchemaService = require('./jsonSchemaService');
|
||||
import {IJSONWorkerContribution} from './jsonContributions';
|
||||
|
||||
import {Hover, ITextDocument, TextDocumentPosition, Range, MarkedString, RemoteConsole} from 'vscode-languageserver';
|
||||
|
||||
export class JSONHover {
|
||||
|
||||
private schemaService: SchemaService.IJSONSchemaService;
|
||||
private contributions: IJSONWorkerContribution[];
|
||||
|
||||
constructor(schemaService: SchemaService.IJSONSchemaService) {
|
||||
constructor(schemaService: SchemaService.IJSONSchemaService, contributions: IJSONWorkerContribution[] = []) {
|
||||
this.schemaService = schemaService;
|
||||
this.contributions = contributions;
|
||||
}
|
||||
|
||||
public doHover(document: ITextDocument, textDocumentPosition: TextDocumentPosition, doc: Parser.JSONDocument): Thenable<Hover> {
|
||||
|
@ -52,15 +55,28 @@ export class JSONHover {
|
|||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (description) {
|
||||
|
||||
function createHover(contents: MarkedString[]) {
|
||||
let range = Range.create(document.positionAt(node.start), document.positionAt(node.end));
|
||||
let result: Hover = {
|
||||
contents: [description],
|
||||
contents: contents,
|
||||
range: range
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
let location = node.getNodeLocation();
|
||||
for (let i = this.contributions.length - 1; i >= 0; i--) {
|
||||
let contribution = this.contributions[i];
|
||||
let promise = contribution.getInfoContribution(textDocumentPosition.uri, location);
|
||||
if (promise) {
|
||||
return promise.then(htmlContent => createHover(htmlContent));
|
||||
}
|
||||
}
|
||||
|
||||
if (description) {
|
||||
return createHover([description]);
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {MarkedString, CompletionItemKind} from 'vscode-languageserver';
|
||||
import Strings = require('../utils/strings');
|
||||
import nls = require('../utils/nls');
|
||||
import {IJSONWorkerContribution, ISuggestionsCollector} from '../jsonContributions';
|
||||
import {IRequestService} from '../jsonSchemaService';
|
||||
import {JSONLocation} from '../jsonLocation';
|
||||
|
||||
export class BowerJSONContribution implements IJSONWorkerContribution {
|
||||
|
||||
private requestService : IRequestService;
|
||||
|
||||
private topRanked = ['twitter','bootstrap','angular-1.1.6','angular-latest','angulerjs','d3','myjquery','jq','abcdef1234567890','jQuery','jquery-1.11.1','jquery',
|
||||
'sushi-vanilla-x-data','font-awsome','Font-Awesome','font-awesome','fontawesome','html5-boilerplate','impress.js','homebrew',
|
||||
'backbone','moment1','momentjs','moment','linux','animate.css','animate-css','reveal.js','jquery-file-upload','blueimp-file-upload','threejs','express','chosen',
|
||||
'normalize-css','normalize.css','semantic','semantic-ui','Semantic-UI','modernizr','underscore','underscore1',
|
||||
'material-design-icons','ionic','chartjs','Chart.js','nnnick-chartjs','select2-ng','select2-dist','phantom','skrollr','scrollr','less.js','leancss','parser-lib',
|
||||
'hui','bootstrap-languages','async','gulp','jquery-pjax','coffeescript','hammer.js','ace','leaflet','jquery-mobile','sweetalert','typeahead.js','soup','typehead.js',
|
||||
'sails','codeigniter2'];
|
||||
|
||||
public constructor(requestService: IRequestService) {
|
||||
this.requestService = requestService;
|
||||
}
|
||||
|
||||
private isBowerFile(resource: string): boolean {
|
||||
return Strings.endsWith(resource, '/bower.json') || Strings.endsWith(resource, '/.bower.json');
|
||||
}
|
||||
|
||||
public collectDefaultSuggestions(resource: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
if (this.isBowerFile(resource)) {
|
||||
let defaultValue = {
|
||||
'name': '{{name}}',
|
||||
'description': '{{description}}',
|
||||
'authors': [ '{{author}}' ],
|
||||
'version': '{{1.0.0}}',
|
||||
'main': '{{pathToMain}}',
|
||||
'dependencies': {}
|
||||
};
|
||||
result.add({ kind: CompletionItemKind.Class, label: nls.localize('json.bower.default', 'Default bower.json'), insertText: JSON.stringify(defaultValue, null, '\t'), documentation: '' });
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectPropertySuggestions(resource: string, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : Thenable<any> {
|
||||
if (this.isBowerFile(resource) && (location.matches(['dependencies']) || location.matches(['devDependencies']))) {
|
||||
if (currentWord.length > 0) {
|
||||
let queryUrl = 'https://bower.herokuapp.com/packages/search/' + encodeURIComponent(currentWord);
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
if (success.status === 200) {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
if (Array.isArray(obj)) {
|
||||
let results = <{name:string; description:string;}[]> obj;
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let name = results[i].name;
|
||||
let description = results[i].description || '';
|
||||
let insertText = JSON.stringify(name);
|
||||
if (addValue) {
|
||||
insertText += ': "{{*}}"';
|
||||
if (!isLast) {
|
||||
insertText += ',';
|
||||
}
|
||||
}
|
||||
result.add({ kind: CompletionItemKind.Property, label: name, insertText: insertText, documentation: description });
|
||||
}
|
||||
result.setAsIncomplete();
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
} else {
|
||||
result.error(nls.localize('json.bower.error.repoaccess', 'Request to the bower repository failed: {0}', success.responseText));
|
||||
return 0;
|
||||
}
|
||||
}, (error) => {
|
||||
result.error(nls.localize('json.bower.error.repoaccess', 'Request to the bower repository failed: {0}', error.responseText));
|
||||
return 0;
|
||||
});
|
||||
} else {
|
||||
this.topRanked.forEach((name) => {
|
||||
let insertText = JSON.stringify(name);
|
||||
if (addValue) {
|
||||
insertText += ': "{{*}}"';
|
||||
if (!isLast) {
|
||||
insertText += ',';
|
||||
}
|
||||
}
|
||||
result.add({ kind: CompletionItemKind.Property, label: name, insertText: insertText, documentation: '' });
|
||||
});
|
||||
result.setAsIncomplete();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectValueSuggestions(resource: string, location: JSONLocation, currentKey: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
// not implemented. Could be do done calling the bower command. Waiting for web API: https://github.com/bower/registry/issues/26
|
||||
return null;
|
||||
}
|
||||
|
||||
public getInfoContribution(resource: string, location: JSONLocation): Thenable<MarkedString[]> {
|
||||
if (this.isBowerFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']))) {
|
||||
let pack = location.getSegments()[location.getSegments().length - 1];
|
||||
let htmlContent : MarkedString[] = [];
|
||||
htmlContent.push(nls.localize('json.bower.package.hover', '{0}', pack));
|
||||
|
||||
let queryUrl = 'https://bower.herokuapp.com/packages/' + encodeURIComponent(pack);
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
if (obj && obj.url) {
|
||||
let url = obj.url;
|
||||
if (Strings.startsWith(url, 'git://')) {
|
||||
url = url.substring(6);
|
||||
}
|
||||
if (Strings.endsWith(url, '.git')) {
|
||||
url = url.substring(0, url.length - 4);
|
||||
}
|
||||
htmlContent.push(url);
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return htmlContent;
|
||||
}, (error) => {
|
||||
return htmlContent;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {MarkedString, CompletionItemKind, CompletionItem} from 'vscode-languageserver';
|
||||
import Strings = require('../utils/strings');
|
||||
import nls = require('../utils/nls');
|
||||
import {IJSONWorkerContribution, ISuggestionsCollector} from '../jsonContributions';
|
||||
import {IRequestService} from '../jsonSchemaService';
|
||||
import {JSONLocation} from '../jsonLocation';
|
||||
|
||||
let globProperties:CompletionItem[] = [
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('fileLabel', "Files by Extension"), insertText: '"**/*.{{extension}}": true', documentation: nls.localize('fileDescription', "Match all files of a specific file extension.")},
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('filesLabel', "Files with Multiple Extensions"), insertText: '"**/*.{ext1,ext2,ext3}": true', documentation: nls.localize('filesDescription', "Match all files with any of the file extensions.")},
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('derivedLabel', "Files with Siblings by Name"), insertText: '"**/*.{{source-extension}}": { "when": "$(basename).{{target-extension}}" }', documentation: nls.localize('derivedDescription', "Match files that have siblings with the same name but a different extension.")},
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('topFolderLabel', "Folder by Name (Top Level)"), insertText: '"{{name}}": true', documentation: nls.localize('topFolderDescription', "Match a top level folder with a specific name.")},
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('topFoldersLabel', "Folders with Multiple Names (Top Level)"), insertText: '"{folder1,folder2,folder3}": true', documentation: nls.localize('topFoldersDescription', "Match multiple top level folders.")},
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('folderLabel', "Folder by Name (Any Location)"), insertText: '"**/{{name}}": true', documentation: nls.localize('folderDescription', "Match a folder with a specific name in any location.")},
|
||||
];
|
||||
|
||||
let globValues:CompletionItem[] = [
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('trueLabel', "True"), insertText: 'true', documentation: nls.localize('trueDescription', "Enable the pattern.")},
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('falseLabel', "False"), insertText: 'false', documentation: nls.localize('falseDescription', "Disable the pattern.")},
|
||||
{ kind: CompletionItemKind.Value, label: nls.localize('derivedLabel', "Files with Siblings by Name"), insertText: '{ "when": "$(basename).{{extension}}" }', documentation: nls.localize('siblingsDescription', "Match files that have siblings with the same name but a different extension.")}
|
||||
];
|
||||
|
||||
export class GlobPatternContribution implements IJSONWorkerContribution {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
private isSettingsFile(resource: string): boolean {
|
||||
return Strings.endsWith(resource, '/settings.json');
|
||||
}
|
||||
|
||||
public collectDefaultSuggestions(resource: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectPropertySuggestions(resource: string, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : Thenable<any> {
|
||||
if (this.isSettingsFile(resource) && (location.matches(['files.exclude']) || location.matches(['search.exclude']))) {
|
||||
|
||||
globProperties.forEach((e) => result.add(e));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectValueSuggestions(resource: string, location: JSONLocation, currentKey: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
if (this.isSettingsFile(resource) && (location.matches(['files.exclude']) || location.matches(['search.exclude']))) {
|
||||
|
||||
globValues.forEach((e) => result.add(e));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public getInfoContribution(resource: string, location: JSONLocation): Thenable<MarkedString[]> {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {MarkedString, CompletionItemKind, CompletionItem} from 'vscode-languageserver';
|
||||
import Strings = require('../utils/strings');
|
||||
import nls = require('../utils/nls');
|
||||
import {IJSONWorkerContribution, ISuggestionsCollector} from '../jsonContributions';
|
||||
import {IRequestService} from '../jsonSchemaService';
|
||||
import {JSONLocation} from '../jsonLocation';
|
||||
|
||||
let LIMIT = 40;
|
||||
|
||||
export class PackageJSONContribution implements IJSONWorkerContribution {
|
||||
|
||||
private mostDependedOn = [ 'lodash', 'async', 'underscore', 'request', 'commander', 'express', 'debug', 'chalk', 'colors', 'q', 'coffee-script',
|
||||
'mkdirp', 'optimist', 'through2', 'yeoman-generator', 'moment', 'bluebird', 'glob', 'gulp-util', 'minimist', 'cheerio', 'jade', 'redis', 'node-uuid',
|
||||
'socket', 'io', 'uglify-js', 'winston', 'through', 'fs-extra', 'handlebars', 'body-parser', 'rimraf', 'mime', 'semver', 'mongodb', 'jquery',
|
||||
'grunt', 'connect', 'yosay', 'underscore', 'string', 'xml2js', 'ejs', 'mongoose', 'marked', 'extend', 'mocha', 'superagent', 'js-yaml', 'xtend',
|
||||
'shelljs', 'gulp', 'yargs', 'browserify', 'minimatch', 'react', 'less', 'prompt', 'inquirer', 'ws', 'event-stream', 'inherits', 'mysql', 'esprima',
|
||||
'jsdom', 'stylus', 'when', 'readable-stream', 'aws-sdk', 'concat-stream', 'chai', 'Thenable', 'wrench'];
|
||||
|
||||
private requestService : IRequestService;
|
||||
|
||||
private isPackageJSONFile(resource: string): boolean {
|
||||
return Strings.endsWith(resource, '/package.json');
|
||||
}
|
||||
|
||||
public constructor(requestService: IRequestService) {
|
||||
this.requestService = requestService;
|
||||
}
|
||||
|
||||
public collectDefaultSuggestions(resource: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
if (this.isPackageJSONFile(resource)) {
|
||||
let defaultValue = {
|
||||
'name': '{{name}}',
|
||||
'description': '{{description}}',
|
||||
'author': '{{author}}',
|
||||
'version': '{{1.0.0}}',
|
||||
'main': '{{pathToMain}}',
|
||||
'dependencies': {}
|
||||
};
|
||||
result.add({ kind: CompletionItemKind.Module, label: nls.localize('json.package.default', 'Default package.json'), insertText: JSON.stringify(defaultValue, null, '\t'), documentation: '' });
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectPropertySuggestions(resource: string, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : Thenable<any> {
|
||||
if (this.isPackageJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['devDependencies']) || location.matches(['optionalDependencies']) || location.matches(['peerDependencies']))) {
|
||||
let queryUrl : string;
|
||||
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';
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
if (success.status === 200) {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
if (obj && Array.isArray(obj.rows)) {
|
||||
let results = <{ key: string[]; }[]> obj.rows;
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let keys = results[i].key;
|
||||
if (Array.isArray(keys) && keys.length > 0) {
|
||||
let name = keys[0];
|
||||
let insertText = JSON.stringify(name);
|
||||
if (addValue) {
|
||||
insertText += ': "{{*}}"';
|
||||
if (!isLast) {
|
||||
insertText += ',';
|
||||
}
|
||||
}
|
||||
result.add({ kind: CompletionItemKind.Property, label: name, insertText: insertText, documentation: '' });
|
||||
}
|
||||
}
|
||||
if (results.length === LIMIT) {
|
||||
result.setAsIncomplete();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
} else {
|
||||
result.error(nls.localize('json.npm.error.repoaccess', 'Request to the NPM repository failed: {0}', success.responseText));
|
||||
return 0;
|
||||
}
|
||||
}, (error) => {
|
||||
result.error(nls.localize('json.npm.error.repoaccess', 'Request to the NPM repository failed: {0}', error.responseText));
|
||||
return 0;
|
||||
});
|
||||
} else {
|
||||
this.mostDependedOn.forEach((name) => {
|
||||
let insertText = JSON.stringify(name);
|
||||
if (addValue) {
|
||||
insertText += ': "{{*}}"';
|
||||
if (!isLast) {
|
||||
insertText += ',';
|
||||
}
|
||||
}
|
||||
result.add({ kind: CompletionItemKind.Property, label: name, insertText: insertText, documentation: '' });
|
||||
});
|
||||
result.setAsIncomplete();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectValueSuggestions(resource: string, location: JSONLocation, currentKey: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
if (this.isPackageJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['devDependencies']) || location.matches(['optionalDependencies']) || location.matches(['peerDependencies']))) {
|
||||
let queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(currentKey) + '/latest';
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
if (obj && obj.version) {
|
||||
let version = obj.version;
|
||||
let name = JSON.stringify(version);
|
||||
result.add({ kind: CompletionItemKind.Class, label: name, insertText: name, documentation: nls.localize('json.npm.latestversion', 'The currently latest version of the package') });
|
||||
name = JSON.stringify('^' + version);
|
||||
result.add({ kind: CompletionItemKind.Class, label: name, insertText: name, documentation: nls.localize('json.npm.majorversion', 'Matches the most recent major version (1.x.x)') });
|
||||
name = JSON.stringify('~' + version);
|
||||
result.add({ kind: CompletionItemKind.Class, label: name, insertText: name, documentation: nls.localize('json.npm.minorversion', 'Matches the most recent minor version (1.2.x)') });
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return 0;
|
||||
}, (error) => {
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getInfoContribution(resource: string, location: JSONLocation): Thenable<MarkedString[]> {
|
||||
if (this.isPackageJSONFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) {
|
||||
let pack = location.getSegments()[location.getSegments().length - 1];
|
||||
|
||||
let htmlContent : MarkedString[] = [];
|
||||
htmlContent.push(nls.localize('json.npm.package.hover', '{0}', pack));
|
||||
|
||||
let queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(pack) + '/latest';
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
if (obj) {
|
||||
if (obj.description) {
|
||||
htmlContent.push(obj.description);
|
||||
}
|
||||
if (obj.version) {
|
||||
htmlContent.push(nls.localize('json.npm.version.hover', 'Latest version: {0}', obj.version));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return htmlContent;
|
||||
}, (error) => {
|
||||
return htmlContent;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {MarkedString, CompletionItemKind, CompletionItem} from 'vscode-languageserver';
|
||||
import Strings = require('../utils/strings');
|
||||
import nls = require('../utils/nls');
|
||||
import {IJSONWorkerContribution, ISuggestionsCollector} from '../jsonContributions';
|
||||
import {IRequestService} from '../jsonSchemaService';
|
||||
import {JSONLocation} from '../jsonLocation';
|
||||
|
||||
let LIMIT = 40;
|
||||
|
||||
export class ProjectJSONContribution implements IJSONWorkerContribution {
|
||||
|
||||
private requestService : IRequestService;
|
||||
|
||||
public constructor(requestService: IRequestService) {
|
||||
this.requestService = requestService;
|
||||
}
|
||||
|
||||
private isProjectJSONFile(resource: string): boolean {
|
||||
return Strings.endsWith(resource, '/project.json');
|
||||
}
|
||||
|
||||
public collectDefaultSuggestions(resource: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
if (this.isProjectJSONFile(resource)) {
|
||||
let defaultValue = {
|
||||
'version': '{{1.0.0-*}}',
|
||||
'dependencies': {},
|
||||
'frameworks': {
|
||||
'dnx451': {},
|
||||
'dnxcore50': {}
|
||||
}
|
||||
};
|
||||
result.add({ kind: CompletionItemKind.Class, label: nls.localize('json.project.default', 'Default project.json'), insertText: JSON.stringify(defaultValue, null, '\t'), documentation: '' });
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectPropertySuggestions(resource: string, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : Thenable<any> {
|
||||
if (this.isProjectJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['frameworks', '*', 'dependencies']) || location.matches(['frameworks', '*', 'frameworkAssemblies']))) {
|
||||
let queryUrl : string;
|
||||
if (currentWord.length > 0) {
|
||||
queryUrl = 'https://www.nuget.org/api/v2/Packages?'
|
||||
+ '$filter=Id%20ge%20\''
|
||||
+ encodeURIComponent(currentWord)
|
||||
+ '\'%20and%20Id%20lt%20\''
|
||||
+ encodeURIComponent(currentWord + 'z')
|
||||
+ '\'%20and%20IsAbsoluteLatestVersion%20eq%20true'
|
||||
+ '&$select=Id,Version,Description&$format=json&$top=' + LIMIT;
|
||||
} else {
|
||||
queryUrl = 'https://www.nuget.org/api/v2/Packages?'
|
||||
+ '$filter=IsAbsoluteLatestVersion%20eq%20true'
|
||||
+ '&$orderby=DownloadCount%20desc&$top=' + LIMIT
|
||||
+ '&$select=Id,Version,DownloadCount,Description&$format=json';
|
||||
}
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
if (success.status === 200) {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
if (Array.isArray(obj.d)) {
|
||||
let results = <any[]> obj.d;
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let curr = results[i];
|
||||
let name = curr.Id;
|
||||
let version = curr.Version;
|
||||
if (name) {
|
||||
let documentation = curr.Description;
|
||||
let typeLabel = curr.Version;
|
||||
let insertText = JSON.stringify(name);
|
||||
if (addValue) {
|
||||
insertText += ': "{{' + version + '}}"';
|
||||
if (!isLast) {
|
||||
insertText += ',';
|
||||
}
|
||||
}
|
||||
result.add({ kind: CompletionItemKind.Property, label: name, insertText: insertText, detail: typeLabel, documentation: documentation });
|
||||
}
|
||||
}
|
||||
if (results.length === LIMIT) {
|
||||
result.setAsIncomplete();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
} else {
|
||||
result.error(nls.localize('json.nugget.error.repoaccess', 'Request to the nuget repository failed: {0}', success.responseText));
|
||||
return 0;
|
||||
}
|
||||
}, (error) => {
|
||||
result.error(nls.localize('json.nugget.error.repoaccess', 'Request to the nuget repository failed: {0}', error.responseText));
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectValueSuggestions(resource: string, location: JSONLocation, currentKey: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
if (this.isProjectJSONFile(resource) && (location.matches(['dependencies']) || location.matches(['frameworks', '*', 'dependencies']) || location.matches(['frameworks', '*', 'frameworkAssemblies']))) {
|
||||
let queryUrl = 'https://www.myget.org/F/aspnetrelease/api/v2/Packages?'
|
||||
+ '$filter=Id%20eq%20\''
|
||||
+ encodeURIComponent(currentKey)
|
||||
+ '\'&$select=Version,IsAbsoluteLatestVersion&$format=json&$top=' + LIMIT;
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
if (Array.isArray(obj.d)) {
|
||||
let results = <any[]> obj.d;
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let curr = results[i];
|
||||
let version = curr.Version;
|
||||
if (version) {
|
||||
let name = JSON.stringify(version);
|
||||
let isLatest = curr.IsAbsoluteLatestVersion === 'true';
|
||||
let label = name;
|
||||
let documentation = '';
|
||||
if (isLatest) {
|
||||
documentation = nls.localize('json.nugget.versiondescription.suggest', 'The currently latest version of the package');
|
||||
}
|
||||
result.add({ kind: CompletionItemKind.Class, label: label, insertText: name, documentation: documentation });
|
||||
}
|
||||
}
|
||||
if (results.length === LIMIT) {
|
||||
result.setAsIncomplete();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return 0;
|
||||
}, (error) => {
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getInfoContribution(resource: string, location: JSONLocation): Thenable<MarkedString[]> {
|
||||
if (this.isProjectJSONFile(resource) && (location.matches(['dependencies', '*']) || location.matches(['frameworks', '*', 'dependencies', '*']) || location.matches(['frameworks', '*', 'frameworkAssemblies', '*']))) {
|
||||
let pack = location.getSegments()[location.getSegments().length - 1];
|
||||
|
||||
let htmlContent : MarkedString[] = [];
|
||||
htmlContent.push(nls.localize('json.nugget.package.hover', '{0}', pack));
|
||||
|
||||
let queryUrl = 'https://www.myget.org/F/aspnetrelease/api/v2/Packages?'
|
||||
+ '$filter=Id%20eq%20\''
|
||||
+ encodeURIComponent(pack)
|
||||
+ '\'%20and%20IsAbsoluteLatestVersion%20eq%20true'
|
||||
+ '&$select=Version,Description&$format=json&$top=5';
|
||||
|
||||
return this.requestService({
|
||||
url : queryUrl
|
||||
}).then((success) => {
|
||||
let content = success.responseText;
|
||||
if (content) {
|
||||
try {
|
||||
let obj = JSON.parse(content);
|
||||
if (obj.d && obj.d[0]) {
|
||||
let res = obj.d[0];
|
||||
if (res.Description) {
|
||||
htmlContent.push(res.Description);
|
||||
}
|
||||
if (res.Version) {
|
||||
htmlContent.push(nls.localize('json.nugget.version.hover', 'Latest version: {0}', res.Version));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return htmlContent;
|
||||
}, (error) => {
|
||||
return htmlContent;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,10 @@ import {JSONHover} from './jsonHover';
|
|||
import {JSONDocumentSymbols} from './jsonDocumentSymbols';
|
||||
import {format as formatJSON} from './jsonFormatter';
|
||||
import {schemaContributions} from './configuration';
|
||||
import {BowerJSONContribution} from './jsoncontributions/bowerJSONContribution';
|
||||
import {PackageJSONContribution} from './jsoncontributions/packageJSONContribution';
|
||||
import {ProjectJSONContribution} from './jsoncontributions/projectJSONContribution';
|
||||
import {GlobPatternContribution} from './jsoncontributions/globPatternContribution';
|
||||
|
||||
namespace TelemetryNotification {
|
||||
export const type: NotificationType<{ key: string, data: any }> = { get method() { return 'telemetry'; } };
|
||||
|
@ -106,11 +110,18 @@ let request = (options: IXHROptions): Thenable<IXHRResponse> => {
|
|||
return xhr(options);
|
||||
}
|
||||
|
||||
let contributions = [
|
||||
new ProjectJSONContribution(request),
|
||||
new PackageJSONContribution(request),
|
||||
new BowerJSONContribution(request),
|
||||
new GlobPatternContribution()
|
||||
];
|
||||
|
||||
let jsonSchemaService = new JSONSchemaService(request, workspaceContext, telemetry);
|
||||
jsonSchemaService.setSchemaContributions(schemaContributions);
|
||||
|
||||
let jsonCompletion = new JSONCompletion(jsonSchemaService);
|
||||
let jsonHover = new JSONHover(jsonSchemaService);
|
||||
let jsonCompletion = new JSONCompletion(jsonSchemaService, contributions);
|
||||
let jsonHover = new JSONHover(jsonSchemaService, contributions);
|
||||
let jsonDocumentSymbols = new JSONDocumentSymbols();
|
||||
|
||||
// The content of a text document has changed. This event is emitted
|
||||
|
|
|
@ -22,7 +22,7 @@ export interface IXHROptions {
|
|||
agent?: any;
|
||||
strictSSL?: boolean;
|
||||
responseType?: string;
|
||||
followRedirects: number;
|
||||
followRedirects?: number;
|
||||
}
|
||||
|
||||
export interface IXHRResponse {
|
||||
|
@ -47,6 +47,9 @@ export function xhr(options: IXHROptions): Promise<IXHRResponse> {
|
|||
const agent = getProxyAgent(options.url, { proxyUrl, strictSSL });
|
||||
options = assign({}, options);
|
||||
options = assign(options, { agent, strictSSL });
|
||||
if (typeof options.followRedirects !== 'number') {
|
||||
options.followRedirects = 5;
|
||||
}
|
||||
|
||||
return request(options).then(result => new Promise<IXHRResponse>((c, e) => {
|
||||
let res = result.res;
|
||||
|
|
Loading…
Reference in a new issue