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

Remove legacy JSON

上级 96f1f812
/*---------------------------------------------------------------------------------------------
* 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 editorCommon = require('vs/editor/common/editorCommon');
import modes = require('vs/editor/common/modes');
import URI from 'vs/base/common/uri';
import WinJS = require('vs/base/common/winjs.base');
import Platform = require('vs/platform/platform');
import jsonWorker = require('vs/languages/json/common/jsonWorker');
import tokenization = require('vs/languages/json/common/features/tokenization');
import {CompatMode, createWordRegExp, ModeWorkerManager} from 'vs/editor/common/modes/abstractMode';
import {IJSONContributionRegistry, Extensions, ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {LanguageConfigurationRegistry, LanguageConfiguration} from 'vs/editor/common/modes/languageConfigurationRegistry';
import {wireCancellationToken} from 'vs/base/common/async';
import {IDisposable} from 'vs/base/common/lifecycle';
import {IModelService} from 'vs/editor/common/services/modelService';
import {onUnexpectedError} from 'vs/base/common/errors';
import {IMarkerService} from 'vs/platform/markers/common/markers';
import {ICompatWorkerService, CompatWorkerAttr} from 'vs/editor/common/services/compatWorkerService';
export class JSONMode extends CompatMode {
public static LANG_CONFIG:LanguageConfiguration = {
wordPattern: createWordRegExp('.-'),
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']']
],
autoClosingPairs: [
{ open: '{', close: '}', notIn: ['string'] },
{ open: '[', close: ']', notIn: ['string'] },
{ open: '"', close: '"', notIn: ['string'] }
]
};
public tokenizationSupport: modes.ITokenizationSupport;
public configSupport:modes.IConfigurationSupport;
public inplaceReplaceSupport:modes.IInplaceReplaceSupport;
private _modeWorkerManager: ModeWorkerManager<jsonWorker.JSONWorker>;
private _validationHelper:ValidationHelper;
constructor(
descriptor:modes.IModeDescriptor,
@IInstantiationService instantiationService: IInstantiationService,
@IModelService modelService: IModelService,
@IMarkerService markerService: IMarkerService,
@ICompatWorkerService compatWorkerService: ICompatWorkerService
) {
super(descriptor.id, compatWorkerService);
this._modeWorkerManager = new ModeWorkerManager<jsonWorker.JSONWorker>(descriptor, 'vs/languages/json/common/jsonWorker', 'JSONWorker', null, instantiationService);
this.tokenizationSupport = tokenization.createTokenizationSupport(this, true);
LanguageConfigurationRegistry.register(this.getId(), JSONMode.LANG_CONFIG);
modes.HoverProviderRegistry.register(this.getId(), {
provideHover: (model, position, token): Thenable<modes.Hover> => {
return wireCancellationToken(token, this._provideHover(model.uri, position));
}
}, true);
this.inplaceReplaceSupport = this;
this.configSupport = this;
// Initialize Outline support
modes.DocumentSymbolProviderRegistry.register(this.getId(), {
provideDocumentSymbols: (model, token): Thenable<modes.SymbolInformation[]> => {
return wireCancellationToken(token, this._provideDocumentSymbols(model.uri));
}
}, true);
modes.DocumentFormattingEditProviderRegistry.register(this.getId(), {
provideDocumentFormattingEdits: (model, options, token): Thenable<editorCommon.ISingleEditOperation[]> => {
return wireCancellationToken(token, this._provideDocumentFormattingEdits(model.uri, options));
}
}, true);
modes.DocumentRangeFormattingEditProviderRegistry.register(this.getId(), {
provideDocumentRangeFormattingEdits: (model, range, options, token): Thenable<editorCommon.ISingleEditOperation[]> => {
return wireCancellationToken(token, this._provideDocumentRangeFormattingEdits(model.uri, range, options));
}
}, true);
modes.SuggestRegistry.register(this.getId(), {
triggerCharacters: [],
shouldAutotriggerSuggest: true,
provideCompletionItems: (model, position, token): Thenable<modes.ISuggestResult[]> => {
return wireCancellationToken(token, this._provideCompletionItems(model.uri, position));
}
}, true);
if (modelService && markerService) {
this._validationHelper = new ValidationHelper(modelService, this.getId(), (uris) => {
this._validate(uris).then((result) => {
result.forEach(r => {
markerService.changeOne(this.getId(), r.resource, r.markerData);
});
}, onUnexpectedError);
});
} else {
this._validationHelper = null;
}
if (this.compatWorkerService && this.compatWorkerService.isInMainThread) {
// Configure all workers
this._configureWorkerSchemas(this.getSchemaConfiguration());
var contributionRegistry = <IJSONContributionRegistry> Platform.Registry.as(Extensions.JSONContribution);
contributionRegistry.addRegistryChangedListener(e => {
this._configureWorkerSchemas(this.getSchemaConfiguration());
});
}
}
private _worker<T>(runner:(worker:jsonWorker.JSONWorker)=>WinJS.TPromise<T>): WinJS.TPromise<T> {
return this._modeWorkerManager.worker(runner);
}
private getSchemaConfiguration() : ISchemaContributions {
var contributionRegistry = <IJSONContributionRegistry> Platform.Registry.as(Extensions.JSONContribution);
return contributionRegistry.getSchemaContributions();
}
public configure(options:any): WinJS.TPromise<void> {
if (!this.compatWorkerService) {
return;
}
if (this.compatWorkerService.isInMainThread) {
if (this._validationHelper) {
this._validationHelper.validateAll();
}
return this._configureWorker(options);
} else {
return this._worker((w) => w._doConfigure(options));
}
}
static $_configureWorker = CompatWorkerAttr(JSONMode, JSONMode.prototype._configureWorker);
private _configureWorker(options:any): WinJS.TPromise<void> {
return this._worker((w) => w._doConfigure(options));
}
static $_configureWorkerSchemas = CompatWorkerAttr(JSONMode, JSONMode.prototype._configureWorkerSchemas);
private _configureWorkerSchemas(data:ISchemaContributions): WinJS.TPromise<boolean> {
return this._worker((w) => w.setSchemaContributions(data));
}
static $_validate = CompatWorkerAttr(JSONMode, JSONMode.prototype._validate);
private _validate(uris:URI[]): WinJS.TPromise<jsonWorker.ValidationResult[]> {
return this._worker((w) => w.validate(uris));
}
static $navigateValueSet = CompatWorkerAttr(JSONMode, JSONMode.prototype.navigateValueSet);
public navigateValueSet(resource:URI, position:editorCommon.IRange, up:boolean):WinJS.TPromise<modes.IInplaceReplaceSupportResult> {
return this._worker((w) => w.navigateValueSet(resource, position, up));
}
static $_provideCompletionItems = CompatWorkerAttr(JSONMode, JSONMode.prototype._provideCompletionItems);
private _provideCompletionItems(resource:URI, position:editorCommon.IPosition):WinJS.TPromise<modes.ISuggestResult[]> {
return this._worker((w) => w.provideCompletionItems(resource, position));
}
static $_provideHover = CompatWorkerAttr(JSONMode, JSONMode.prototype._provideHover);
private _provideHover(resource:URI, position:editorCommon.IPosition): WinJS.TPromise<modes.Hover> {
return this._worker((w) => w.provideHover(resource, position));
}
static $_provideDocumentSymbols = CompatWorkerAttr(JSONMode, JSONMode.prototype._provideDocumentSymbols);
private _provideDocumentSymbols(resource:URI):WinJS.TPromise<modes.SymbolInformation[]> {
return this._worker((w) => w.provideDocumentSymbols(resource));
}
static $_provideDocumentFormattingEdits = CompatWorkerAttr(JSONMode, JSONMode.prototype._provideDocumentFormattingEdits);
public _provideDocumentFormattingEdits(resource:URI, options:modes.FormattingOptions):WinJS.TPromise<editorCommon.ISingleEditOperation[]> {
return this._worker((w) => w.format(resource, null, options));
}
static $_provideDocumentRangeFormattingEdits = CompatWorkerAttr(JSONMode, JSONMode.prototype._provideDocumentRangeFormattingEdits);
public _provideDocumentRangeFormattingEdits(resource:URI, range:editorCommon.IRange, options:modes.FormattingOptions):WinJS.TPromise<editorCommon.ISingleEditOperation[]> {
return this._worker((w) => w.format(resource, range, options));
}
}
class ValidationHelper {
private _disposables: IDisposable[] = [];
private _listener: { [uri: string]: IDisposable } = Object.create(null);
constructor(
private _modelService: IModelService,
private _selector: string,
private _validate:(what:URI[])=>void
) {
const onModelAdd = (model: editorCommon.IModel): void => {
if (model.getModeId() !== _selector) {
return;
}
let modelListener = model.onDidChangeContent(() => {
clearTimeout(handle);
handle = setTimeout(() => this._validate([model.uri]), 500);
});
let handle: number;
this._listener[model.uri.toString()] = {
dispose: () => {
modelListener.dispose();
clearTimeout(handle);
}
};
handle = setTimeout(() => this._validate([model.uri]), 500);
};
const onModelRemoved = (model: editorCommon.IModel): void => {
if (this._listener[model.uri.toString()]) {
this._listener[model.uri.toString()].dispose();
delete this._listener[model.uri.toString()];
}
};
this._disposables.push(this._modelService.onModelAdded(onModelAdd));
this._disposables.push(this._modelService.onModelRemoved(onModelRemoved));
this._disposables.push(this._modelService.onModelModeChanged(event => {
onModelRemoved(event.model);
onModelAdd(event.model);
}));
this._disposables.push({
dispose: () => {
for (let key in this._listener) {
this._listener[key].dispose();
}
}
});
this._modelService.getModels().forEach(onModelAdd);
}
public dispose(): void {
this._disposables.forEach(d => d && d.dispose());
this._disposables = [];
}
public validateAll(): void {
this._validate(Object.keys(this._listener).map(uri => URI.parse(uri)));
}
}
/*---------------------------------------------------------------------------------------------
* 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 URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import EditorCommon = require('vs/editor/common/editorCommon');
import Modes = require('vs/editor/common/modes');
import HtmlContent = require('vs/base/common/htmlContent');
import Parser = require('./parser/jsonParser');
import JSONFormatter = require('vs/base/common/jsonFormatter');
import SchemaService = require('./jsonSchemaService');
import JSONSchema = require('vs/base/common/jsonSchema');
import JSONIntellisense = require('./jsonIntellisense');
import WinJS = require('vs/base/common/winjs.base');
import Strings = require('vs/base/common/strings');
import ProjectJSONContribution = require('./contributions/projectJSONContribution');
import PackageJSONContribution = require('./contributions/packageJSONContribution');
import BowerJSONContribution = require('./contributions/bowerJSONContribution');
import GlobPatternContribution = require('./contributions/globPatternContribution');
import errors = require('vs/base/common/errors');
import {IMarkerData} from 'vs/platform/markers/common/markers';
import {IRequestService} from 'vs/platform/request/common/request';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import {IResourceService} from 'vs/editor/common/services/resourceService';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {JSONLocation} from './parser/jsonLocation';
import {filterSuggestions} from 'vs/editor/common/modes/supports/suggestSupport';
export interface IOptionsSchema {
/**
* HTTP schema URL or a relative path to schema file in workspace
*/
url: string;
/**
* The patterns (e.g. *.pack.json) to map files to this schema
*/
fileMatch: string[];
/**
* A unresolved schema definition. Optional, to avoid fetching from a URL.
*/
schema?: JSONSchema.IJSONSchema;
/* deprecated */
schemaPath: string;
/* deprecated */
filePattern: string;
}
export interface IOptions {
schemas: IOptionsSchema[];
}
export interface ISuggestionsCollector {
add(suggestion: Modes.ISuggestion): void;
setAsIncomplete() : void;
error(message:string): void;
}
export interface IJSONWorkerContribution {
getInfoContribution(resource: URI, location: JSONLocation) : WinJS.TPromise<HtmlContent.MarkedString[]>;
collectPropertySuggestions(resource: URI, location: JSONLocation, currentWord: string, addValue: boolean, isLast:boolean, result: ISuggestionsCollector) : WinJS.Promise;
collectValueSuggestions(resource: URI, location: JSONLocation, propertyKey: string, result: ISuggestionsCollector): WinJS.Promise;
collectDefaultSuggestions(resource: URI, result: ISuggestionsCollector): WinJS.Promise;
}
export interface ValidationResult {
resource: URI;
markerData: IMarkerData[];
}
export class JSONWorker {
private schemaService: SchemaService.IJSONSchemaService;
private requestService: IRequestService;
private contextService: IWorkspaceContextService;
private jsonIntellisense : JSONIntellisense.JSONIntellisense;
private contributions: IJSONWorkerContribution[];
private resourceService:IResourceService;
private _modeId: string;
constructor(
modeId: string,
@IResourceService resourceService: IResourceService,
@IRequestService requestService: IRequestService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IInstantiationService instantiationService: IInstantiationService
) {
this._modeId = modeId;
this.resourceService = resourceService;
this.requestService = requestService;
this.contextService = contextService;
this.schemaService = instantiationService.createInstance(SchemaService.JSONSchemaService);
this.contributions = [
instantiationService.createInstance(ProjectJSONContribution.ProjectJSONContribution),
instantiationService.createInstance(PackageJSONContribution.PackageJSONContribution),
instantiationService.createInstance(BowerJSONContribution.BowerJSONContribution),
instantiationService.createInstance(GlobPatternContribution.GlobPatternContribution)
];
this.jsonIntellisense = new JSONIntellisense.JSONIntellisense(this.schemaService, this.requestService, this.contributions);
}
public navigateValueSet(resource:URI, range:EditorCommon.IRange, up:boolean):WinJS.TPromise<Modes.IInplaceReplaceSupportResult> {
var modelMirror = this.resourceService.get(resource);
var offset = modelMirror.getOffsetFromPosition({ lineNumber: range.startLineNumber, column: range.startColumn });
var parser = new Parser.JSONParser();
var config = new Parser.JSONDocumentConfig();
config.ignoreDanglingComma = true;
var doc = parser.parse(modelMirror.getValue(), config);
var node = doc.getNodeFromOffsetEndInclusive(offset);
if (node && (node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) {
return this.schemaService.getSchemaForResource(resource.toString(), doc).then((schema) => {
if (schema) {
var proposals : Modes.ISuggestion[] = [];
var proposed: any = {};
var collector = {
add: (suggestion: Modes.ISuggestion) => {
if (!proposed[suggestion.label]) {
proposed[suggestion.label] = true;
proposals.push(suggestion);
}
},
setAsIncomplete: () => { /* ignore */ },
error: (message: string) => {
errors.onUnexpectedError(message);
}
};
this.jsonIntellisense.getValueSuggestions(resource, schema, doc, node.parent, node.start, collector);
var range = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start);
var text = modelMirror.getValueInRange(range);
for (var i = 0, len = proposals.length; i < len; i++) {
if (Strings.equalsIgnoreCase(proposals[i].label, text)) {
var nextIdx = i;
if (up) {
nextIdx = (i + 1) % len;
} else {
nextIdx = i - 1;
if (nextIdx < 0) {
nextIdx = len - 1;
}
}
return {
value: proposals[nextIdx].label,
range: range
};
}
}
return null;
}
});
}
return null;
}
/**
* @return true if you want to revalidate your models
*/
_doConfigure(options:IOptions): WinJS.TPromise<void> {
if (options && options.schemas) {
this.schemaService.clearExternalSchemas();
options.schemas.forEach((schema) => {
if (schema.url && (schema.fileMatch || schema.schema)) {
var url = schema.url;
if (!Strings.startsWith(url, 'http://') && !Strings.startsWith(url, 'https://') && !Strings.startsWith(url, 'file://')) {
var resourceURL = this.contextService.toResource(url);
if (resourceURL) {
url = resourceURL.toString();
}
}
if (url) {
this.schemaService.registerExternalSchema(url, schema.fileMatch, schema.schema);
}
} else if (schema.filePattern && schema.schemaPath) {
var url = this.contextService.toResource(schema.schemaPath).toString();
var patterns = schema.filePattern ? [ schema.filePattern ] : [];
this.schemaService.registerExternalSchema(url, patterns);
}
});
}
return WinJS.TPromise.as(void 0);
}
public setSchemaContributions(contributions:ISchemaContributions): WinJS.TPromise<boolean> {
this.schemaService.setSchemaContributions(contributions);
return WinJS.TPromise.as(true);
}
public validate(resources: URI[]):WinJS.TPromise<ValidationResult[]> {
return WinJS.TPromise.join(resources.map(resource => this.doValidate1(resource)));
}
private doValidate1(resource: URI): WinJS.TPromise<ValidationResult> {
var modelMirror = this.resourceService.get(resource);
var parser = new Parser.JSONParser();
var content = modelMirror.getValue();
if (content.length === 0) {
// ignore empty content, no marker can be set anyway
return WinJS.TPromise.as<ValidationResult>({
resource: resource,
markerData: []
});
}
var result = parser.parse(content);
return this.schemaService.getSchemaForResource(resource.toString(), result).then((schema) => {
if (schema) {
if (schema.errors.length && result.root) {
var property = result.root.type === 'object' ? (<Parser.ObjectASTNode> result.root).getFirstProperty('$schema') : null;
if (property) {
var node = property.value || property;
result.warnings.push({ location: { start: node.start, end: node.end }, message: schema.errors[0] });
} else {
result.warnings.push({ location: { start: result.root.start, end: result.root.start + 1 }, message: schema.errors[0] });
}
} else {
result.validate(schema.schema);
}
}
var added : { [signature:string]: boolean} = {};
var markerData: IMarkerData[] = [];
result.errors.concat(result.warnings).forEach((error, idx) => {
// remove duplicated messages
var signature = error.location.start + ' ' + error.location.end + ' ' + error.message;
if (!added[signature]) {
added[signature] = true;
var startPosition = modelMirror.getPositionFromOffset(error.location.start);
var endPosition = modelMirror.getPositionFromOffset(error.location.end);
markerData.push({
message: error.message,
severity: idx >= result.errors.length ? Severity.Warning : Severity.Error,
startLineNumber: startPosition.lineNumber,
startColumn: startPosition.column,
endLineNumber: endPosition.lineNumber,
endColumn: endPosition.column
});
}
});
return {
resource: resource,
markerData: markerData
};
});
}
public provideCompletionItems(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise<Modes.ISuggestResult[]> {
return this.doSuggest(resource, position).then(value => filterSuggestions(value));
}
private doSuggest(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise<Modes.ISuggestResult> {
var modelMirror = this.resourceService.get(resource);
return this.jsonIntellisense.doSuggest(resource, modelMirror, position);
}
public provideHover(resource:URI, position:EditorCommon.IPosition): WinJS.TPromise<Modes.Hover> {
var modelMirror = this.resourceService.get(resource);
var parser = new Parser.JSONParser();
var doc = parser.parse(modelMirror.getValue());
var offset = modelMirror.getOffsetFromPosition(position);
var node = doc.getNodeFromOffset(offset);
var originalNode = node;
// use the property description when hovering over an object key
if (node && node.type === 'string') {
var stringNode = <Parser.StringASTNode>node;
if (stringNode.isKey) {
var propertyNode = <Parser.PropertyASTNode>node.parent;
node = propertyNode.value;
}
}
if (!node) {
return WinJS.TPromise.as(null);
}
return this.schemaService.getSchemaForResource(resource.toString(), doc).then((schema) => {
if (schema) {
var matchingSchemas : Parser.IApplicableSchema[] = [];
doc.validate(schema.schema, matchingSchemas, node.start);
var description: string = null;
var contributonId: string = null;
matchingSchemas.every((s) => {
if (s.node === node && !s.inverted && s.schema) {
description = description || s.schema.description;
contributonId = contributonId || s.schema.id;
}
return true;
});
var location = node.getNodeLocation();
for (var i= this.contributions.length -1; i >= 0; i--) {
var contribution = this.contributions[i];
var promise = contribution.getInfoContribution(resource, location);
if (promise) {
return promise.then((htmlContent) => { return this.createInfoResult(htmlContent, originalNode, modelMirror); } );
}
}
if (description) {
var htmlContent = [ description ];
return this.createInfoResult(htmlContent, originalNode, modelMirror);
}
}
return null;
});
}
private createInfoResult(htmlContent : HtmlContent.MarkedString[], node: Parser.ASTNode, modelMirror: EditorCommon.IMirrorModel) : Modes.Hover {
var range = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start);
var result:Modes.Hover = {
contents: htmlContent,
range: range
};
return result;
}
public provideDocumentSymbols(resource:URI):WinJS.TPromise<Modes.SymbolInformation[]> {
var modelMirror = this.resourceService.get(resource);
var parser = new Parser.JSONParser();
var doc = parser.parse(modelMirror.getValue());
var root = doc.root;
if (!root) {
return WinJS.TPromise.as(null);
}
// special handling for key bindings
var resourceString = resource.toString();
if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
if (root.type === 'array') {
var result : Modes.SymbolInformation[] = [];
(<Parser.ArrayASTNode> root).items.forEach((item) => {
if (item.type === 'object') {
var property = (<Parser.ObjectASTNode> item).getFirstProperty('key');
if (property && property.value) {
var range = modelMirror.getRangeFromOffsetAndLength(item.start, item.end - item.start);
result.push({
name: property.value.getValue(),
kind: Modes.SymbolKind.String,
location: {
uri: resource,
range: range
}
});
}
}
});
return WinJS.TPromise.as(result);
}
}
function collectOutlineEntries(result: Modes.SymbolInformation[], node: Parser.ASTNode, containerName: string): Modes.SymbolInformation[] {
if (node.type === 'array') {
(<Parser.ArrayASTNode>node).items.forEach((node:Parser.ASTNode) => {
collectOutlineEntries(result, node, containerName);
});
} else if (node.type === 'object') {
var objectNode = <Parser.ObjectASTNode>node;
objectNode.properties.forEach((property:Parser.PropertyASTNode) => {
var range = modelMirror.getRangeFromOffsetAndLength(property.start, property.end - property.start);
var valueNode = property.value;
if (valueNode) {
let childContainerName = containerName ? containerName + '.' + property.key.name : property.key.name;
result.push({
name: property.key.getValue(),
kind: getSymbolKind(valueNode.type),
location: {
uri: resource,
range: range,
},
containerName: containerName
});
collectOutlineEntries(result, valueNode, childContainerName);
}
});
}
return result;
}
var result = collectOutlineEntries([], root, void 0);
return WinJS.TPromise.as(result);
}
public format(resource: URI, range: EditorCommon.IRange, options: Modes.FormattingOptions): WinJS.TPromise<EditorCommon.ISingleEditOperation[]> {
let model = this.resourceService.get(resource);
let formatRange = range ? model.getOffsetAndLengthFromRange(range) : void 0;
let edits = JSONFormatter.format(model.getValue(), formatRange, { insertSpaces: options.insertSpaces, tabSize: options.tabSize, eol: model.getEOL() });
let operations = edits.map(e => ({ range: model.getRangeFromOffsetAndLength(e.offset, e.length), text: e.content }));
return WinJS.TPromise.as(operations);
}
}
function getSymbolKind(nodeType: string): Modes.SymbolKind {
switch (nodeType) {
case 'object':
return Modes.SymbolKind.Module;
case 'string':
return Modes.SymbolKind.String;
case 'number':
return Modes.SymbolKind.Number;
case 'array':
return Modes.SymbolKind.Array;
case 'boolean':
return Modes.SymbolKind.Boolean;
default: // 'null'
return Modes.SymbolKind.Variable;
}
}
/*---------------------------------------------------------------------------------------------
* 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 jsonMode = require('vs/languages/json/common/json');
import Modes = require('vs/editor/common/modes');
import modesUtil = require('vs/editor/test/common/modesUtil');
import jsonTokenTypes = require('vs/languages/json/common/features/jsonTokenTypes');
suite('JSON - tokenization', () => {
var tokenizationSupport: Modes.ITokenizationSupport;
var assertOnEnter: modesUtil.IOnEnterAsserter;
(function() {
let mode = new jsonMode.JSONMode(
{ id: 'json' },
null,
null,
null,
null
);
tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), jsonMode.JSONMode.LANG_CONFIG);
})();
test('', () => {
modesUtil.executeTests(tokenizationSupport,[
// tokens and brackets
[{
line: '{',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_OBJECT }
]}],
[{
line: '[',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_ARRAY }
]}],
[{
line: '}',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_OBJECT }
]}],
[{
line: ']',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_ARRAY }
]}],
[{
line: ':',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_COLON }
]}],
[{
line: ',',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_COMMA }
]}],
// literals and keyword
[{
line: '-0.123e+9203',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_VALUE_NUMBER }
]}],
[{
line: 'true',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_VALUE_BOOLEAN }
]}],
[{
line: 'false',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_VALUE_BOOLEAN }
]}],
[{
line: 'null',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_VALUE_NULL }
]}],
[{
line: '"foo"',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_PROPERTY_NAME }
]}],
[{
line: '"foo',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_PROPERTY_NAME }
]}],
// comments and whitespace
[{
line: '//null',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_COMMENT_LINE }
]}],
[{
line: '/*null*/',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_COMMENT_BLOCK }
]}],
[{
line: '/*null',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_COMMENT_BLOCK }
]}],
[{
line: '\t \r\n',
tokens: [
{ startIndex: 0, type: '' },
{ startIndex: 2, type: '' }
]}],
// sequences
[{
line: '{ "foo": null }',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_OBJECT },
{ startIndex:1, type: '' },
{ startIndex:2, type: jsonTokenTypes.TOKEN_PROPERTY_NAME },
{ startIndex:7, type: jsonTokenTypes.TOKEN_DELIM_COLON },
{ startIndex:8, type: '' },
{ startIndex:9, type: jsonTokenTypes.TOKEN_VALUE_NULL },
{ startIndex:13, type: '' },
{ startIndex:14, type: jsonTokenTypes.TOKEN_DELIM_OBJECT }
]}],
// JSON sample
[{
line: '{ "foo": "bar" }',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_OBJECT },
{ startIndex:1, type: '' },
{ startIndex:2, type: jsonTokenTypes.TOKEN_PROPERTY_NAME },
{ startIndex:7, type: jsonTokenTypes.TOKEN_DELIM_COLON },
{ startIndex:8, type: '' },
{ startIndex:9, type: jsonTokenTypes.TOKEN_VALUE_STRING },
{ startIndex:14, type: '' },
{ startIndex:15, type: jsonTokenTypes.TOKEN_DELIM_OBJECT }
]}],
// Arrays, keywords, and numbers
[{
line: '[-1.5e+4, true, false, null]',
tokens: [
{ startIndex:0, type: jsonTokenTypes.TOKEN_DELIM_ARRAY },
{ startIndex:1, type: jsonTokenTypes.TOKEN_VALUE_NUMBER },
{ startIndex:8, type: jsonTokenTypes.TOKEN_DELIM_COMMA },
{ startIndex:9, type: '' },
{ startIndex:10, type: jsonTokenTypes.TOKEN_VALUE_BOOLEAN },
{ startIndex:14, type: jsonTokenTypes.TOKEN_DELIM_COMMA },
{ startIndex:15, type: '' },
{ startIndex:16, type: jsonTokenTypes.TOKEN_VALUE_BOOLEAN },
{ startIndex:21, type: jsonTokenTypes.TOKEN_DELIM_COMMA },
{ startIndex:22, type: '' },
{ startIndex:23, type: jsonTokenTypes.TOKEN_VALUE_NULL },
{ startIndex:27, type: jsonTokenTypes.TOKEN_DELIM_ARRAY }
]}]
]);
});
test('onEnter', function() {
assertOnEnter.indents('', '"value": {', '');
assertOnEnter.nothing('', '"value":(', '');
assertOnEnter.indents('', '"value":[', '');
assertOnEnter.indentsOutdents('', '"value":{', '}');
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册