From 3a311829e49433f1e270c0ca3c994f1c135a94eb Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 16 Feb 2017 21:38:47 +0100 Subject: [PATCH] [json] remove project.json support (for OmniSharp/omnisharp-vscode#1236) --- extensions/json/server/src/jsonServerMain.ts | 5 +- .../projectJSONContribution.ts | 281 ------------------ 2 files changed, 1 insertion(+), 285 deletions(-) delete mode 100644 extensions/json/server/src/jsoncontributions/projectJSONContribution.ts diff --git a/extensions/json/server/src/jsonServerMain.ts b/extensions/json/server/src/jsonServerMain.ts index 3b06405dcb4ca..8e1d15f3a5539 100644 --- a/extensions/json/server/src/jsonServerMain.ts +++ b/extensions/json/server/src/jsonServerMain.ts @@ -17,7 +17,6 @@ import URI from './utils/uri'; import * as URL from 'url'; import Strings = require('./utils/strings'); import { JSONDocument, JSONSchema, LanguageSettings, getLanguageService } from 'vscode-json-languageservice'; -import { ProjectJSONContribution } from './jsoncontributions/projectJSONContribution'; import { getLanguageModelCache } from './languageModelCache'; import * as nls from 'vscode-nls'; @@ -119,9 +118,7 @@ let schemaRequestService = (uri: string): Thenable => { let languageService = getLanguageService({ schemaRequestService, workspaceContext, - contributions: [ - new ProjectJSONContribution() - ] + contributions: [] }); // The settings interface describes the server relevant settings part diff --git a/extensions/json/server/src/jsoncontributions/projectJSONContribution.ts b/extensions/json/server/src/jsoncontributions/projectJSONContribution.ts deleted file mode 100644 index 427e49efae28d..0000000000000 --- a/extensions/json/server/src/jsoncontributions/projectJSONContribution.ts +++ /dev/null @@ -1,281 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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, InsertTextFormat } from 'vscode-languageserver'; -import Strings = require('../utils/strings'); -import { XHRResponse, getErrorStatusDescription, xhr } from 'request-light'; -import { JSONWorkerContribution, JSONPath, CompletionsCollector } from 'vscode-json-languageservice'; - -import * as nls from 'vscode-nls'; -const localize = nls.loadMessageBundle(); - - -const FEED_INDEX_URL = 'https://api.nuget.org/v3/index.json'; -const LIMIT = 30; -const RESOLVE_ID = 'ProjectJSONContribution-'; - -const CACHE_EXPIRY = 1000 * 60 * 5; // 5 minutes - -interface NugetServices { - 'SearchQueryService'?: string; - 'SearchAutocompleteService'?: string; - 'PackageBaseAddress/3.0.0'?: string; - [key: string]: string; -} - -export class ProjectJSONContribution implements JSONWorkerContribution { - - private cachedProjects: { [id: string]: { version: string, description: string, time: number } } = {}; - private cacheSize: number = 0; - private nugetIndexPromise: Thenable; - - public constructor() { - } - - private isProjectJSONFile(resource: string): boolean { - return Strings.endsWith(resource, '/project.json'); - } - - private completeWithCache(id: string, item: CompletionItem): boolean { - let entry = this.cachedProjects[id]; - if (entry) { - if (new Date().getTime() - entry.time > CACHE_EXPIRY) { - delete this.cachedProjects[id]; - this.cacheSize--; - return false; - } - let insertTextValue = item.insertText; - item.detail = entry.version; - item.documentation = entry.description; - item.insertText = insertTextValue.replace(/\$1/, '${1:' + entry.version + '}'); - return true; - } - return false; - } - - private addCached(id: string, version: string, description: string) { - this.cachedProjects[id] = { version, description, time: new Date().getTime() }; - this.cacheSize++; - if (this.cacheSize > 50) { - let currentTime = new Date().getTime(); - for (let id in this.cachedProjects) { - let entry = this.cachedProjects[id]; - if (currentTime - entry.time > CACHE_EXPIRY) { - delete this.cachedProjects[id]; - this.cacheSize--; - } - } - } - } - - private getNugetIndex(): Thenable { - if (!this.nugetIndexPromise) { - this.nugetIndexPromise = this.makeJSONRequest(FEED_INDEX_URL).then(indexContent => { - let services: NugetServices = {}; - if (indexContent && Array.isArray(indexContent.resources)) { - let resources = indexContent.resources; - for (let i = resources.length - 1; i >= 0; i--) { - let type = resources[i]['@type']; - let id = resources[i]['@id']; - if (type && id) { - services[type] = id; - } - } - } - return services; - }); - } - return this.nugetIndexPromise; - } - - private getNugetService(serviceType: string): Thenable { - return this.getNugetIndex().then(services => { - let serviceURL = services[serviceType]; - if (!serviceURL) { - return Promise.reject(localize('json.nugget.error.missingservice', 'NuGet index document is missing service {0}', serviceType)); - } - return serviceURL; - }); - } - - public collectDefaultCompletions(resource: string, result: CompletionsCollector): Thenable { - if (this.isProjectJSONFile(resource)) { - let insertText = JSON.stringify({ - 'version': '${1:1.0.0-*}', - 'dependencies': {}, - 'frameworks': { - 'net461': {}, - 'netcoreapp1.0': {} - } - }, null, '\t'); - result.add({ kind: CompletionItemKind.Class, label: localize('json.project.default', 'Default project.json'), insertText, insertTextFormat: InsertTextFormat.Snippet, documentation: '' }); - } - return null; - } - - private makeJSONRequest(url: string): Thenable { - return xhr({ - url: url - }).then(success => { - if (success.status === 200) { - try { - return JSON.parse(success.responseText); - } catch (e) { - return Promise.reject(localize('json.nugget.error.invalidformat', '{0} is not a valid JSON document', url)); - } - } - return Promise.reject(localize('json.nugget.error.indexaccess', 'Request to {0} failed: {1}', url, success.responseText)); - }, (error: XHRResponse) => { - return Promise.reject(localize('json.nugget.error.access', 'Request to {0} failed: {1}', url, getErrorStatusDescription(error.status))); - }); - } - - public collectPropertyCompletions(resource: string, location: JSONPath, currentWord: string, addValue: boolean, isLast: boolean, result: CompletionsCollector): Thenable { - if (this.isProjectJSONFile(resource) && (matches(location, ['dependencies']) || matches(location, ['frameworks', '*', 'dependencies']) || matches(location, ['frameworks', '*', 'frameworkAssemblies']))) { - - return this.getNugetService('SearchAutocompleteService').then(service => { - let queryUrl: string; - if (currentWord.length > 0) { - queryUrl = service + '?q=' + encodeURIComponent(currentWord) + '&take=' + LIMIT; - } else { - queryUrl = service + '?take=' + LIMIT; - } - return this.makeJSONRequest(queryUrl).then(resultObj => { - if (Array.isArray(resultObj.data)) { - let results = resultObj.data; - for (let i = 0; i < results.length; i++) { - let name = results[i]; - let insertText = JSON.stringify(name); - if (addValue) { - insertText += ': "$1"'; - if (!isLast) { - insertText += ','; - } - } - let item: CompletionItem = { kind: CompletionItemKind.Property, label: name, insertText: insertText, insertTextFormat: InsertTextFormat.Snippet, filterText: JSON.stringify(name) }; - if (!this.completeWithCache(name, item)) { - item.data = RESOLVE_ID + name; - } - result.add(item); - } - if (results.length === LIMIT) { - result.setAsIncomplete(); - } - } - }, error => { - result.error(error); - }); - }, error => { - result.error(error); - }); - }; - return null; - } - - public collectValueCompletions(resource: string, location: JSONPath, currentKey: string, result: CompletionsCollector): Thenable { - if (this.isProjectJSONFile(resource) && (matches(location, ['dependencies']) || matches(location, ['frameworks', '*', 'dependencies']) || matches(location, ['frameworks', '*', 'frameworkAssemblies']))) { - return this.getNugetService('PackageBaseAddress/3.0.0').then(service => { - let queryUrl = service + currentKey + '/index.json'; - return this.makeJSONRequest(queryUrl).then(obj => { - if (Array.isArray(obj.versions)) { - let results = obj.versions; - for (let i = 0; i < results.length; i++) { - let curr = results[i]; - let name = JSON.stringify(curr); - let label = name; - let documentation = ''; - result.add({ kind: CompletionItemKind.Class, label: label, insertText: name, documentation: documentation }); - } - if (results.length === LIMIT) { - result.setAsIncomplete(); - } - } - }, error => { - result.error(error); - }); - }, error => { - result.error(error); - }); - } - return null; - } - - public getInfoContribution(resource: string, location: JSONPath): Thenable { - if (this.isProjectJSONFile(resource) && (matches(location, ['dependencies', '*']) || matches(location, ['frameworks', '*', 'dependencies', '*']) || matches(location, ['frameworks', '*', 'frameworkAssemblies', '*']))) { - let pack = location[location.length - 1]; - - return this.getNugetService('SearchQueryService').then(service => { - let queryUrl = service + '?q=' + encodeURIComponent(pack) + '&take=' + 5; - return this.makeJSONRequest(queryUrl).then(resultObj => { - let htmlContent: MarkedString[] = []; - htmlContent.push(localize('json.nugget.package.hover', '{0}', pack)); - if (Array.isArray(resultObj.data)) { - let results = resultObj.data; - for (let i = 0; i < results.length; i++) { - let res = results[i]; - this.addCached(res.id, res.version, res.description); - if (res.id === pack) { - if (res.description) { - htmlContent.push(MarkedString.fromPlainText(res.description)); - } - if (res.version) { - htmlContent.push(MarkedString.fromPlainText(localize('json.nugget.version.hover', 'Latest version: {0}', res.version))); - } - break; - } - } - } - return htmlContent; - }, (error) => { - return null; - }); - }, (error) => { - return null; - }); - } - return null; - } - - public resolveSuggestion(item: CompletionItem): Thenable { - if (item.data && Strings.startsWith(item.data, RESOLVE_ID)) { - let pack = item.data.substring(RESOLVE_ID.length); - if (this.completeWithCache(pack, item)) { - return Promise.resolve(item); - } - return this.getNugetService('SearchQueryService').then(service => { - let queryUrl = service + '?q=' + encodeURIComponent(pack) + '&take=' + 10; - return this.makeJSONRequest(queryUrl).then(resultObj => { - let itemResolved = false; - if (Array.isArray(resultObj.data)) { - let results = resultObj.data; - for (let i = 0; i < results.length; i++) { - let curr = results[i]; - this.addCached(curr.id, curr.version, curr.description); - if (curr.id === pack) { - this.completeWithCache(pack, item); - itemResolved = true; - } - } - } - return itemResolved ? item : null; - }); - }); - }; - return null; - } -} - -function matches(segments: JSONPath, pattern: string[]) { - let k = 0; - for (let i = 0; k < pattern.length && i < segments.length; i++) { - if (pattern[k] === segments[i] || pattern[k] === '*') { - k++; - } else if (pattern[k] !== '**') { - return false; - } - } - return k === pattern.length; -} \ No newline at end of file