提交 2ea4e8e6 编写于 作者: A Alex Dima

Remove vs/languages/razor

上级 8bed8f36
......@@ -4,12 +4,12 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {IMode, IState, IStream, ITokenizationResult, ITokenizationSupport, TokenizationRegistry} from 'vs/editor/common/modes';
import {IMode, IState, IStream, ITokenizationResult, TokenizationRegistry} from 'vs/editor/common/modes';
import {AbstractState} from 'vs/editor/common/modes/abstractState';
import {TokenizationSupport} from 'vs/editor/common/modes/supports/tokenizationSupport';
let instanceCount = 0;
export function generateMockModeId(): string {
function generateMockModeId(): string {
return 'mockMode' + (++instanceCount);
}
......
......@@ -5,11 +5,7 @@
'use strict';
import * as assert from 'assert';
import {Model} from 'vs/editor/common/model/model';
import * as modes from 'vs/editor/common/modes';
import {RichEditSupport, LanguageConfiguration} from 'vs/editor/common/modes/languageConfigurationRegistry';
import {Token} from 'vs/editor/common/core/token';
import {generateMockModeId} from 'vs/editor/test/common/mocks/mockMode';
export interface ITestToken {
startIndex: number;
......@@ -21,10 +17,6 @@ export interface ITestItem {
tokens: ITestToken[];
}
export function assertWords(actual:string[], expected:string[], message?:string): void {
assert.deepEqual(actual, expected, message);
}
export function assertTokenization(tokenizationSupport: modes.ITokenizationSupport, tests: ITestItem[]): void {
var state = tokenizationSupport.getInitialState();
for (var i = 0, len = tests.length; i < len; i++) {
......@@ -37,71 +29,3 @@ export function assertTokenization(tokenizationSupport: modes.ITokenizationSuppo
state = result.endState;
}
}
export interface IOnEnterAsserter {
nothing(oneLineAboveText:string, beforeText:string, afterText:string): void;
indents(oneLineAboveText:string, beforeText:string, afterText:string): void;
outdents(oneLineAboveText:string, beforeText:string, afterText:string): void;
indentsOutdents(oneLineAboveText:string, beforeText:string, afterText:string): void;
}
export function createOnEnterAsserter(conf: LanguageConfiguration): IOnEnterAsserter {
const modeId = generateMockModeId();
const assertOne = (oneLineAboveText:string, beforeText:string, afterText:string, expected: modes.IndentAction) => {
let model = Model.createFromString(
[ oneLineAboveText, beforeText + afterText ].join('\n'),
undefined,
modeId
);
let richEditSupport = new RichEditSupport(modeId, null, conf);
let actual = richEditSupport.onEnter.onEnter(model, { lineNumber: 2, column: beforeText.length + 1 });
if (expected === modes.IndentAction.None) {
assert.equal(actual, null, oneLineAboveText + '\\n' + beforeText + '|' + afterText);
} else {
assert.equal(actual.indentAction, expected, oneLineAboveText + '\\n' + beforeText + '|' + afterText);
}
model.dispose();
};
return {
nothing: (oneLineAboveText:string, beforeText:string, afterText:string): void => {
assertOne(oneLineAboveText, beforeText, afterText, modes.IndentAction.None);
},
indents: (oneLineAboveText:string, beforeText:string, afterText:string): void => {
assertOne(oneLineAboveText, beforeText, afterText, modes.IndentAction.Indent);
},
outdents: (oneLineAboveText:string, beforeText:string, afterText:string): void => {
assertOne(oneLineAboveText, beforeText, afterText, modes.IndentAction.Outdent);
},
indentsOutdents: (oneLineAboveText:string, beforeText:string, afterText:string): void => {
assertOne(oneLineAboveText, beforeText, afterText, modes.IndentAction.IndentOutdent);
}
};
}
export function executeTests(tokenizationSupport: modes.ITokenizationSupport, tests:ITestItem[][]): void {
for (var i = 0, len = tests.length; i < len; i++) {
assert.ok(true, 'TEST #' + i);
executeTest(tokenizationSupport, tests[i]);
}
}
function executeTest(tokenizationSupport: modes.ITokenizationSupport, tests:ITestItem[]): void {
var state = tokenizationSupport.getInitialState();
for (var i = 0, len = tests.length; i < len; i++) {
assert.ok(true, tests[i].line);
var result = tokenizationSupport.tokenize(tests[i].line, state);
if (tests[i].tokens) {
assertTokens(result.tokens, tests[i].tokens, 'Tokenizing line ' + tests[i].line);
}
state = result.endState;
}
}
function assertTokens(actual:Token[], expected:ITestToken[], message?:string): void {
assert.deepEqual(actual, expected, message + ': ' + JSON.stringify(actual, null, '\t'));
}
......@@ -49,10 +49,5 @@ exports.collectModules = function(args) {
// .combine(worker)
// .define('vs/languages/html/common/htmlWorker', ['vs/languages/lib/common/beautify-html']);
// // ---- razor -----------------------------------
// common.define('vs/languages/razor/common/razor', ['vs/languages/html/common/html'])
// .combine(worker)
// .define('vs/languages/razor/common/razorWorker', ['vs/languages/html/common/htmlWorker', 'vs/languages/lib/common/beautify-html'] );
return result;
};
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 objects = require('vs/base/common/objects');
import Modes = require('vs/editor/common/modes');
import htmlMode = require('vs/languages/html/common/html');
import VSXML = require('vs/languages/razor/common/vsxml');
import {AbstractState} from 'vs/editor/common/modes/abstractState';
import {isDigit} from 'vs/editor/common/modes/abstractMode';
import razorTokenTypes = require('vs/languages/razor/common/razorTokenTypes');
var htmlTokenTypes = htmlMode.htmlTokenTypes;
var punctuations = '+-*%&|^~!=<>/?;:.,';
var separators = '+-*/%&|^~!=<>(){}[]\"\'\\/?;:.,';
var whitespace = '\t ';
var brackets = (function() {
let bracketsSource = [
{ tokenType:'punctuation.bracket.cs', open: '{', close: '}' },
{ tokenType:'punctuation.array.cs', open: '[', close: ']' },
{ tokenType:'punctuation.parenthesis.cs', open: '(', close: ')' }
];
let MAP: {
[text:string]:{
tokenType: string;
}
} = Object.create(null);
for (let i = 0; i < bracketsSource.length; i++) {
let bracket = bracketsSource[i];
MAP[bracket.open] = {
tokenType: bracket.tokenType,
};
MAP[bracket.close] = {
tokenType: bracket.tokenType,
};
}
return {
stringIsBracket: (text:string): boolean => {
return !!MAP[text];
},
tokenTypeFromString: (text:string): string => {
return MAP[text].tokenType;
}
};
})();
var isKeyword = objects.createKeywordMatcher([
'abstract', 'as', 'async', 'await', 'base', 'bool',
'break', 'by', 'byte', 'case',
'catch', 'char', 'checked', 'class',
'const', 'continue', 'decimal', 'default',
'delegate', 'do', 'double', 'descending',
'explicit', 'event', 'extern', 'else',
'enum', 'false', 'finally', 'fixed',
'float', 'for', 'foreach', 'from',
'goto', 'group', 'if', 'implicit',
'in', 'int', 'interface', 'internal',
'into', 'is', 'lock', 'long', 'nameof',
'new', 'null', 'namespace', 'object',
'operator', 'out', 'override', 'orderby',
'params', 'private', 'protected', 'public',
'readonly', 'ref', 'return', 'switch',
'struct', 'sbyte', 'sealed', 'short',
'sizeof', 'stackalloc', 'static', 'string',
'select', 'this', 'throw', 'true',
'try', 'typeof', 'uint', 'ulong',
'unchecked', 'unsafe', 'ushort', 'using',
'var', 'virtual', 'volatile', 'void', 'when',
'while', 'where', 'yield',
'model', 'inject' // Razor specific
]);
var ispunctuation = (character:string) => {
return punctuations.indexOf(character) > -1;
};
export abstract class CSState extends AbstractState {
public name:string;
public parent:AbstractState;
constructor(modeId:string, name:string, parent:AbstractState) {
super(modeId);
this.name = name;
this.parent = parent;
}
public equals(other:Modes.IState):boolean {
if (!super.equals(other)) {
return false;
}
var otherCSState:CSState = <CSState>other;
return (other instanceof CSState) && (this.getModeId() === otherCSState.getModeId()) && (this.name === otherCSState.name) && ((this.parent === null && otherCSState.parent === null) || (this.parent !== null && this.parent.equals(otherCSState.parent)));
}
}
class CSString extends CSState {
private isAtBeginning:boolean;
private punctuation:string;
constructor(modeId:string, parent:AbstractState, punctuation:string) {
super(modeId, 'string', parent);
this.isAtBeginning = true;
this.punctuation = punctuation;
}
public makeClone():CSString {
return new CSString(this.getModeId(), this.parent ? <AbstractState>this.parent.clone() : null, this.punctuation);
}
public equals(other:CSString):boolean {
return super.equals(other) && this.punctuation === other.punctuation;
}
public tokenize(stream:Modes.IStream):Modes.ITokenizationResult {
var readChars = this.isAtBeginning ? 1 : 0;
this.isAtBeginning = false;
while (!stream.eos()) {
var c = stream.next();
if (c === '\\') {
if (readChars === 0) {
if (stream.eos()) {
return { type: 'string.escape.cs' };
} else {
stream.next();
if (stream.eos()) {
return { type: 'string.escape.cs', nextState: this.parent };
} else {
return { type: 'string.escape.cs' };
}
}
} else {
stream.goBack(1);
return { type: 'string.cs' };
}
} else if (c === this.punctuation) {
break;
}
readChars += 1;
}
return { type: 'string.cs', nextState: this.parent };
}
}
class CSVerbatimString extends CSState {
constructor(modeId:string, parent:AbstractState) {
super(modeId, 'verbatimstring', parent);
}
public makeClone():CSVerbatimString {
return new CSVerbatimString(this.getModeId(), this.parent ? <AbstractState>this.parent.clone() : null);
}
public tokenize(stream:Modes.IStream):Modes.ITokenizationResult {
while (!stream.eos()) {
var token = stream.next();
if (token === '"') {
if (!stream.eos() && stream.peek() === '"') {
stream.next();
} else {
return { type: 'string.cs', nextState: this.parent };
}
}
}
return { type: 'string.cs' };
}
}
class CSNumber extends CSState {
private firstDigit:string;
constructor(modeId:string, parent:AbstractState, firstDigit:string) {
super(modeId, 'number', parent);
this.firstDigit = firstDigit;
}
public makeClone():CSNumber {
return new CSNumber(this.getModeId(), this.parent ? <AbstractState>this.parent.clone() : null, this.firstDigit);
}
public tokenize(stream:Modes.IStream):Modes.ITokenizationResult {
var character = this.firstDigit;
var base = 10, isDecimal = false, isExponent = false;
if (character === '0' && !stream.eos()) {
character = stream.peek();
if (character === 'x') {
base = 16;
} else if (character === '.') {
base = 10;
} else {
return { type: 'number.cs', nextState: this.parent };
}
stream.next();
}
while (!stream.eos()) {
character = stream.peek();
if (isDigit(character, base)) {
stream.next();
} else if (base === 10) {
if (character === '.' && !isExponent && !isDecimal) {
isDecimal = true;
stream.next();
} else if (character.toLowerCase() === 'e' && !isExponent) {
isExponent = true;
stream.next();
if (!stream.eos() && stream.peek() === '-') {
stream.next();
}
} else if (character.toLowerCase() === 'f' || character.toLowerCase() === 'd') {
stream.next();
break;
} else {
break;
}
} else {
break;
}
}
var tokenType = 'number';
if (base === 16) {
tokenType += '.hex';
}
return { type: tokenType + '.cs', nextState: this.parent };
}
}
// the multi line comment
export class CSComment extends CSState {
private commentChar:string;
constructor(modeId:string, parent:AbstractState, commentChar:string) {
super(modeId, 'comment', parent);
this.commentChar = commentChar;
}
public makeClone():CSComment {
return new CSComment(this.getModeId(), this.parent ? <AbstractState>this.parent.clone() : null, this.commentChar);
}
public tokenize(stream:Modes.IStream):Modes.ITokenizationResult {
while (!stream.eos()) {
var token = stream.next();
if (token === '*' && !stream.eos() && !stream.peekWhitespace() && stream.peek() === this.commentChar) {
stream.next();
return { type: 'comment.cs', nextState: this.parent};
}
}
return { type: 'comment.cs' };
}
}
export class CSStatement extends CSState implements VSXML.IVSXMLWrapperState {
private level:number;
private plevel:number;
private razorMode:boolean;
private expression:boolean;
private vsState: VSXML.VSXMLState;
private firstToken: boolean;
private firstTokenWasKeyword: boolean;
constructor(modeId:string, parent: AbstractState, level: number, plevel: number, razorMode: boolean,
expression: boolean, firstToken: boolean, firstTokenWasKeyword: boolean) {
super(modeId, 'expression', parent);
this.level = level;
this.plevel = plevel;
this.razorMode = razorMode;
this.expression = expression;
this.vsState = new VSXML.VSXMLExpression(modeId, null);
this.firstToken = firstToken;
this.firstTokenWasKeyword = firstTokenWasKeyword;
}
public setVSXMLState(newVSState:VSXML.VSXMLState):void {
this.vsState = newVSState;
}
public makeClone():CSStatement {
var st = new CSStatement(this.getModeId(), this.parent ? <AbstractState>this.parent.clone() : null, this.level,
this.plevel, this.razorMode, this.expression, this.firstToken, this.firstTokenWasKeyword);
if (this.vsState !== null) {
st.setVSXMLState(<VSXML.VSXMLState>this.vsState.clone());
}
return st;
}
public equals(other:Modes.IState):boolean {
return super.equals(other) &&
(other instanceof CSStatement) &&
((this.vsState === null && (<CSStatement>other).vsState === null) ||
(this.vsState !== null && this.vsState.equals((<CSStatement>other).vsState)));
}
public tokenize(stream:Modes.IStream):Modes.ITokenizationResult {
stream.setTokenRules(separators, whitespace);
if (stream.skipWhitespace().length > 0) {
return { type: '' };
}
return this.stateTokenize(stream);
}
public stateTokenize(stream:Modes.IStream):Modes.ITokenizationResult {
if (isDigit(stream.peek(), 10)) {
this.firstToken = false;
return { nextState: new CSNumber(this.getModeId(), this, stream.next()) };
}
var token = stream.nextToken();
var acceptNestedModes = !this.firstTokenWasKeyword;
var nextStateAtEnd = (this.level <= 0 && this.plevel <= 0 && stream.eos() ? this.parent : undefined);
if (stream.eos()) {
this.firstTokenWasKeyword = false; // Set this for the state starting on the next line.
}
if (isKeyword(token)) {
if (this.level <= 0) { // if we find a keyword outside of a block, we know that we are outside of an expression
this.expression = false;
}
if (this.firstToken) {
this.firstTokenWasKeyword = true;
}
return { type: 'keyword.cs' };
}
this.firstToken = false;
if (this.razorMode && token === '<' && acceptNestedModes) {
if (!stream.eos() && /[_:!\/\w]/.test(stream.peek())) {
return { nextState: new CSSimpleHTML(this.getModeId(), this, htmlMode.States.Content) };
}
}
// exit expressions on anything that doesn't look like part of the same expression
if (this.razorMode && this.expression && this.level <= 0 && this.plevel <= 0&& !stream.eos()) {
if (!/^(\.|\[|\(|\{\w+)$/.test(stream.peekToken())) {
nextStateAtEnd = this.parent;
}
}
if (token === '/') {
if (!stream.eos() && !stream.peekWhitespace()) {
switch(stream.peekToken()) {
case '/':
stream.nextToken();
if (!stream.eos() && stream.peekToken() === '/') {
stream.nextToken();
if (stream.eos()) {
return {
type: 'comment.vs'
};
}
if (stream.peekToken() !== '/') {
return {
type: 'comment.vs',
nextState: new VSXML.VSXMLEmbeddedState(this.getModeId(), this.vsState, this)
};
}
}
stream.advanceToEOS();
return { type: 'comment.cs' };
case '*':
stream.nextToken();
return { nextState: new CSComment(this.getModeId(), this, '/') };
}
}
return { type: 'punctuation.cs', nextState: nextStateAtEnd };
}
if (token === '@') { // a verbatim string (or a razor construct)
if (!stream.eos()) {
switch(stream.peekToken()) {
case '"':
stream.nextToken();
return { nextState: new CSVerbatimString(this.getModeId(), this) };
case '*':
stream.nextToken();
return { nextState: new CSComment(this.getModeId(), this, '@') };
}
}
}
if (/@?\w+/.test(token)) {
return { type: 'ident.cs', nextState: nextStateAtEnd };
}
if (token === '"' || token === '\'') { // string or character
return { nextState: new CSString(this.getModeId(), this, token) };
}
if (brackets.stringIsBracket(token)) {
var tr: Modes.ITokenizationResult = {
type: brackets.tokenTypeFromString(token),
nextState: nextStateAtEnd
};
if (this.razorMode) {
if (token === '{') {
this.expression = false; // whenever we enter a block, we exit expression mode
this.level++;
if (this.level === 1) {
tr.type = razorTokenTypes.EMBED_CS;
tr.nextState = undefined;
}
}
if (token === '}') {
this.level--;
if (this.level <= 0) {
tr.type = razorTokenTypes.EMBED_CS;
tr.nextState = this.parent;
}
}
if (this.expression) {
if (token === '(') {
this.plevel++;
if (this.plevel === 1) {
tr.type = razorTokenTypes.EMBED_CS;
tr.nextState = undefined;
}
}
if (token === ')') {
this.plevel--;
if (this.expression && this.plevel <= 0) { // we only leave csharp mode if we are in expression mode
tr.type = razorTokenTypes.EMBED_CS;
tr.nextState = this.parent;
}
}
if (token === '[') {
this.plevel++;
tr.nextState = undefined;
}
if (token === ']') {
this.plevel--;
}
}
}
return tr;
}
if (ispunctuation(token)) {
return { type: 'punctuation.cs', nextState: nextStateAtEnd };
}
if (this.razorMode && this.expression && this.plevel <= 0) { // in razor mode exit on non-keywords in expressions
return { type: '', nextState: this.parent };
}
return { type: '', nextState: nextStateAtEnd };
}
}
// this state always returns to parent state if it leaves a html tag
class CSSimpleHTML extends CSState {
private state:htmlMode.States;
constructor(modeId:string, parent:AbstractState, state:htmlMode.States) {
super(modeId, 'number', parent);
this.state = state;
}
public makeClone():CSSimpleHTML {
return new CSSimpleHTML(this.getModeId(), this.parent ? <AbstractState>this.parent.clone() : null, this.state);
}
private nextName(stream:Modes.IStream):string {
return stream.advanceIfRegExp(/^[_:\w][_:\w-.\d]*/);
}
private nextAttrValue(stream:Modes.IStream):string {
return stream.advanceIfRegExp(/^('|').*?\1/);
}
public tokenize(stream:Modes.IStream):Modes.ITokenizationResult {
switch (this.state) {
case htmlMode.States.WithinComment:
if (stream.advanceUntil('-->', false).length > 0) {
return { type: htmlTokenTypes.COMMENT};
}
if (stream.advanceIfString('-->').length > 0) {
this.state = htmlMode.States.Content;
return { type: htmlTokenTypes.DELIM_COMMENT, nextState: this.parent };
}
break;
case htmlMode.States.WithinDoctype:
if (stream.advanceUntil('>', false).length > 0) {
return { type: htmlTokenTypes.DOCTYPE };
}
if (stream.advanceIfString('>').length > 0) {
this.state = htmlMode.States.Content;
return { type: htmlTokenTypes.DELIM_DOCTYPE, nextState: this.parent };
}
break;
case htmlMode.States.Content:
if (stream.advanceIfString('!--').length > 0){
this.state = htmlMode.States.WithinComment;
return { type: htmlTokenTypes.DELIM_COMMENT };
}
if (stream.advanceIfRegExp(/!DOCTYPE/i).length > 0) {
this.state = htmlMode.States.WithinDoctype;
return { type: htmlTokenTypes.DELIM_DOCTYPE };
}
if (stream.advanceIfString('/').length > 0){
this.state = htmlMode.States.OpeningEndTag;
return { type: htmlTokenTypes.DELIM_END };
}
this.state = htmlMode.States.OpeningStartTag;
return { type: htmlTokenTypes.DELIM_START };
case htmlMode.States.OpeningEndTag: {
let tagName = this.nextName(stream);
if (tagName.length > 0) {
return {
type: htmlTokenTypes.getTag(tagName)
};
}
if (stream.advanceIfString('>').length > 0) {
this.state = htmlMode.States.Content;
return { type: htmlTokenTypes.DELIM_END, nextState: this.parent };
}
stream.advanceUntil('>', false);
return { type: '' };
}
case htmlMode.States.OpeningStartTag: {
let tagName = this.nextName(stream);
if (tagName.length > 0) {
this.state = htmlMode.States.WithinTag;
return {
type: htmlTokenTypes.getTag(tagName)
};
}
break;
}
case htmlMode.States.WithinTag:
if (stream.skipWhitespace().length > 0) {
return { type: '' };
}
var name:string = this.nextName(stream);
if (name.length > 0) {
this.state = htmlMode.States.AttributeName;
return { type: htmlTokenTypes.ATTRIB_NAME };
}
if (stream.advanceIfRegExp(/^\/?>/).length > 0) {
this.state = htmlMode.States.Content;
return { type: htmlTokenTypes.DELIM_START, nextState: this.parent };
}
stream.next();
return { type: '' };
case htmlMode.States.AttributeName:
if (stream.skipWhitespace().length > 0 || stream.eos()) {
return { type: '' };
}
if (stream.peek() === '=') {
stream.next();
this.state = htmlMode.States.AttributeValue;
return { type: '' };
}
this.state = htmlMode.States.WithinTag;
return this.tokenize(stream); // no advance yet - jump to WithinTag
case htmlMode.States.AttributeValue:
if (stream.skipWhitespace().length > 0 || stream.eos()) {
return { type: '' };
}
var value = this.nextAttrValue(stream);
if (value.length > 0) {
this.state = htmlMode.States.WithinTag;
return { type: htmlTokenTypes.ATTRIB_VALUE };
}
this.state = htmlMode.States.WithinTag;
return this.tokenize(stream); // no advance yet - jump to WithinTag
}
stream.next();
this.state = htmlMode.States.Content;
return { type: '', nextState: this.parent };
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 {ModesRegistry} from 'vs/editor/common/modes/modesRegistry';
ModesRegistry.registerCompatMode({
id: 'razor',
extensions: ['.cshtml'],
aliases: ['Razor', 'razor'],
mimetypes: ['text/x-cshtml'],
moduleId: 'vs/languages/razor/common/razor',
ctorName: 'RAZORMode'
});
/*---------------------------------------------------------------------------------------------
* 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 modes = require('vs/editor/common/modes');
import htmlMode = require('vs/languages/html/common/html');
import csharpTokenization = require('vs/languages/razor/common/csharpTokenization');
import {createWordRegExp, ModeWorkerManager} from 'vs/editor/common/modes/abstractMode';
import razorTokenTypes = require('vs/languages/razor/common/razorTokenTypes');
import {RAZORWorker} from 'vs/languages/razor/common/razorWorker';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IModeService} from 'vs/editor/common/services/modeService';
import {LanguageConfigurationRegistry, LanguageConfiguration} from 'vs/editor/common/modes/languageConfigurationRegistry';
import {wireCancellationToken} from 'vs/base/common/async';
import {ICompatWorkerService} from 'vs/editor/common/services/compatWorkerService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {TokenizationSupport, ILeavingNestedModeData} from 'vs/editor/common/modes/supports/tokenizationSupport';
// for a brief description of the razor syntax see http://www.mikesdotnetting.com/Article/153/Inline-Razor-Syntax-Overview
class RAZORState extends htmlMode.State {
constructor(modeId:string, kind:htmlMode.States, lastTagName:string, lastAttributeName:string, embeddedContentType:string, attributeValueQuote:string, attributeValueLength:number) {
super(modeId, kind, lastTagName, lastAttributeName, embeddedContentType, attributeValueQuote, attributeValueLength);
}
public makeClone():RAZORState {
return new RAZORState(this.getModeId(), this.kind, this.lastTagName, this.lastAttributeName, this.embeddedContentType, this.attributeValueQuote, this.attributeValueLength);
}
public equals(other:modes.IState):boolean {
if (other instanceof RAZORState) {
return (
super.equals(other)
);
}
return false;
}
public tokenize(stream:modes.IStream):modes.ITokenizationResult {
if (!stream.eos() && stream.peek() === '@') {
stream.next();
if (!stream.eos() && stream.peek() === '*') {
return { nextState: new csharpTokenization.CSComment(this.getModeId(), this, '@') };
}
if (stream.eos() || stream.peek() !== '@') {
return { type: razorTokenTypes.EMBED_CS, nextState: new csharpTokenization.CSStatement(this.getModeId(), this, 0, 0, true, true, true, false) };
}
}
return super.tokenize(stream);
}
}
export class RAZORMode extends htmlMode.HTMLMode<RAZORWorker> {
public static LANG_CONFIG:LanguageConfiguration = {
wordPattern: createWordRegExp('#?%'),
comments: {
blockComment: ['<!--', '-->']
},
brackets: [
['<!--', '-->'],
['{', '}'],
['(', ')']
],
__electricCharacterSupport: {
embeddedElectricCharacters: ['*', '}', ']', ')']
},
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: '\'', close: '\'' }
],
surroundingPairs: [
{ open: '"', close: '"' },
{ open: '\'', close: '\'' }
],
onEnterRules: [
{
beforeText: new RegExp(`<(?!(?:${htmlMode.EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
afterText: /^<\/(\w[\w\d]*)\s*>$/i,
action: { indentAction: modes.IndentAction.IndentOutdent }
},
{
beforeText: new RegExp(`<(?!(?:${htmlMode.EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
action: { indentAction: modes.IndentAction.Indent }
}
],
};
constructor(
descriptor:modes.IModeDescriptor,
@IInstantiationService instantiationService: IInstantiationService,
@IModeService modeService: IModeService,
@ICompatWorkerService compatWorkerService: ICompatWorkerService,
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService,
@IConfigurationService configurationService: IConfigurationService
) {
super(descriptor, instantiationService, modeService, compatWorkerService, workspaceContextService, configurationService);
}
protected _registerSupports(): void {
modes.SuggestRegistry.register(this.getId(), {
triggerCharacters: ['.', ':', '<', '"', '=', '/'],
provideCompletionItems: (model, position, token): Thenable<modes.ISuggestResult> => {
return wireCancellationToken(token, this._provideCompletionItems(model.uri, position));
}
}, true);
modes.DocumentHighlightProviderRegistry.register(this.getId(), {
provideDocumentHighlights: (model, position, token): Thenable<modes.DocumentHighlight[]> => {
return wireCancellationToken(token, this._provideDocumentHighlights(model.uri, position));
}
}, true);
modes.LinkProviderRegistry.register(this.getId(), {
provideLinks: (model, token): Thenable<modes.ILink[]> => {
return wireCancellationToken(token, this.provideLinks(model.uri));
}
}, true);
LanguageConfigurationRegistry.register(this.getId(), RAZORMode.LANG_CONFIG);
modes.TokenizationRegistry.register(this.getId(), new TokenizationSupport(this._modeService, this.getId(), this, true));
}
protected _createModeWorkerManager(descriptor:modes.IModeDescriptor, instantiationService: IInstantiationService): ModeWorkerManager<RAZORWorker> {
return new ModeWorkerManager<RAZORWorker>(descriptor, 'vs/languages/razor/common/razorWorker', 'RAZORWorker', 'vs/languages/html/common/htmlWorker', instantiationService);
}
public getInitialState(): modes.IState {
return new RAZORState(this.getId(), htmlMode.States.Content, '', '', '', '', 0);
}
public getLeavingNestedModeData(line:string, state:modes.IState): ILeavingNestedModeData {
var leavingNestedModeData = super.getLeavingNestedModeData(line, state);
if (leavingNestedModeData) {
leavingNestedModeData.stateAfterNestedMode = new RAZORState(this.getId(), htmlMode.States.Content, '', '', '', '', 0);
}
return leavingNestedModeData;
}
}
/*---------------------------------------------------------------------------------------------
* 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 const EMBED_CS = 'support.function.cshtml';
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import htmlWorker = require('vs/languages/html/common/htmlWorker');
import htmlTags = require('vs/languages/html/common/htmlTags');
export function getRazorTagProvider() : htmlTags.IHTMLTagProvider {
var customTags : { [tag:string]: string[]} = {
a: ['asp-action', 'asp-controller', 'asp-fragment', 'asp-host', 'asp-protocol', 'asp-route'],
div: ['asp-validation-summary'],
form: ['asp-action', 'asp-controller', 'asp-anti-forgery'],
input: ['asp-for', 'asp-format'],
label: ['asp-for'],
select: ['asp-for', 'asp-items'],
span: ['asp-validation-for']
};
return {
getId: () => 'razor',
collectTags: (collector: (tag: string) => void) => {
// no extra tags
},
collectAttributes: (tag: string, collector: (attribute: string, type: string) => void) => {
if (tag) {
var attributes = customTags[tag];
if (attributes) {
attributes.forEach(a => collector(a, null));
}
}
},
collectValues: (tag: string, attribute: string, collector: (value: string) => void) => {
// no values
}
};
}
export class RAZORWorker extends htmlWorker.HTMLWorker {
protected addCustomTagProviders(providers: htmlTags.IHTMLTagProvider[]): void {
// don't call super and don't add the angular provider for now
providers.push(getRazorTagProvider());
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* In order to use VSXML in your own modes, you need to have an IState
* which implements IVSXMLWrapperState. Upon a START token such as '///',
* the wrapper state can return a new VSXMLEmbeddedState as the nextState in
* the tokenization result.
*/
'use strict';
import objects = require('vs/base/common/objects');
import Modes = require('vs/editor/common/modes');
import {AbstractState} from 'vs/editor/common/modes/abstractState';
import vsxmlTokenTypes = require('vs/languages/razor/common/vsxmlTokenTypes');
var separators = '<>"=/';
var whitespace = '\t ';
var isEntity = objects.createKeywordMatcher(['summary', 'reference', 'returns', 'param', 'loc']);
var isAttribute = objects.createKeywordMatcher(['type', 'path', 'name', 'locid', 'filename', 'format', 'optional']);
var isSeparator = objects.createKeywordMatcher(separators.split(''));
export interface IVSXMLWrapperState extends Modes.IState {
setVSXMLState(newVSXMLState:VSXMLState):void;
}
export class EmbeddedState extends AbstractState {
private state:Modes.IState;
private parentState:Modes.IState;
constructor(modeId:string, state:Modes.IState, parentState:Modes.IState) {
super(modeId);
this.state = state;
this.parentState = parentState;
}
public getParentState():Modes.IState {
return this.parentState;
}
public makeClone(): EmbeddedState {
return new EmbeddedState(this.getModeId(), AbstractState.safeClone(this.state), AbstractState.safeClone(this.parentState));
}
public equals(other:Modes.IState):boolean {
if (other instanceof EmbeddedState) {
return (
super.equals(other) &&
AbstractState.safeEquals(this.state, other.state) &&
AbstractState.safeEquals(this.parentState, other.parentState)
);
}
return false;
}
public setState(nextState:Modes.IState):void {
this.state = nextState;
}
public postTokenize(result:Modes.ITokenizationResult, stream:Modes.IStream) : Modes.ITokenizationResult {
return result;
}
public tokenize(stream:Modes.IStream) : Modes.ITokenizationResult {
var result = this.state.tokenize(stream);
if (result.nextState !== undefined) {
this.setState(result.nextState);
}
result.nextState = this;
return this.postTokenize(result, stream);
}
}
export class VSXMLEmbeddedState extends EmbeddedState {
constructor(modeId:string, state:Modes.IState, parentState:IVSXMLWrapperState) {
super(modeId, state, parentState);
}
public equals(other:Modes.IState):boolean {
if (other instanceof VSXMLEmbeddedState) {
return (
super.equals(other)
);
}
return false;
}
public setState(nextState:Modes.IState):void{
super.setState(nextState);
(<IVSXMLWrapperState> this.getParentState()).setVSXMLState(<VSXMLState>nextState);
}
public postTokenize(result:Modes.ITokenizationResult, stream:Modes.IStream):Modes.ITokenizationResult {
if (stream.eos()) {
result.nextState = this.getParentState();
}
return result;
}
}
export abstract class VSXMLState extends AbstractState {
public parent:Modes.IState;
public whitespaceTokenType:string;
private name:string;
constructor(modeId:string, name:string, parent:Modes.IState, whitespaceTokenType:string='') {
super(modeId);
this.name = name;
this.parent = parent;
this.whitespaceTokenType = whitespaceTokenType;
}
public equals(other:Modes.IState):boolean {
if (other instanceof VSXMLState) {
return (
super.equals(other) &&
this.whitespaceTokenType === other.whitespaceTokenType &&
this.name === other.name &&
AbstractState.safeEquals(this.parent, other.parent)
);
}
return false;
}
public tokenize(stream:Modes.IStream):Modes.ITokenizationResult {
stream.setTokenRules(separators, whitespace);
if (stream.skipWhitespace().length > 0) {
return { type: this.whitespaceTokenType };
}
return this.stateTokenize(stream);
}
public abstract stateTokenize(stream:Modes.IStream):Modes.ITokenizationResult;
}
export class VSXMLString extends VSXMLState {
constructor(modeId:string, parent:Modes.IState) {
super(modeId, 'string', parent, vsxmlTokenTypes.TOKEN_VALUE);
}
public makeClone():VSXMLString {
return new VSXMLString(this.getModeId(), this.parent ? this.parent.clone() : null);
}
public equals(other:Modes.IState):boolean {
if (other instanceof VSXMLString) {
return (
super.equals(other)
);
}
return false;
}
public stateTokenize(stream:Modes.IStream):Modes.ITokenizationResult {
while (!stream.eos()) {
var token = stream.nextToken();
if (token === '"') {
return { type: vsxmlTokenTypes.TOKEN_VALUE, nextState: this.parent };
}
}
return { type: vsxmlTokenTypes.TOKEN_VALUE, nextState: this.parent };
}
}
export class VSXMLTag extends VSXMLState {
constructor(modeId:string, parent:Modes.IState) {
super(modeId, 'expression', parent, 'vs');
}
public makeClone():VSXMLTag {
return new VSXMLTag(this.getModeId(), this.parent ? this.parent.clone() : null);
}
public equals(other:Modes.IState):boolean {
if (other instanceof VSXMLTag) {
return (
super.equals(other)
);
}
return false;
}
public stateTokenize(stream:Modes.IStream):Modes.ITokenizationResult {
var token = stream.nextToken();
var tokenType = this.whitespaceTokenType;
if (token === '>') {
return { type: 'punctuation.vs', nextState: this.parent };
} else if (token === '"') {
return { type: vsxmlTokenTypes.TOKEN_VALUE, nextState: new VSXMLString(this.getModeId(), this) };
} else if (isEntity(token)) {
tokenType = 'tag.vs';
} else if (isAttribute(token)) {
tokenType = vsxmlTokenTypes.TOKEN_KEY;
} else if (isSeparator(token)) {
tokenType = 'punctuation.vs';
}
return { type:tokenType, nextState: this };
}
}
export class VSXMLExpression extends VSXMLState {
constructor(modeId:string, parent:Modes.IState) {
super(modeId, 'expression', parent, 'vs');
}
public makeClone():VSXMLExpression {
return new VSXMLExpression(this.getModeId(), this.parent ? this.parent.clone() : null);
}
public equals(other:Modes.IState):boolean {
if (other instanceof VSXMLExpression) {
return (
super.equals(other)
);
}
return false;
}
public stateTokenize(stream:Modes.IStream):Modes.ITokenizationResult {
var token = stream.nextToken();
if (token === '<') {
return { type: 'punctuation.vs', nextState: new VSXMLTag(this.getModeId(), this) };
}
return { type: this.whitespaceTokenType, nextState: this};
}
}
/*---------------------------------------------------------------------------------------------
* 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 const TOKEN_VALUE = 'support.property-value.constant.other.json';
export const TOKEN_KEY = 'support.type.property-name.json';
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 modesUtil = require('vs/editor/test/common/modesUtil');
import Modes = require('vs/editor/common/modes');
import razorTokenTypes = require('vs/languages/razor/common/razorTokenTypes');
import {htmlTokenTypes} from 'vs/languages/html/common/html';
import {RAZORMode} from 'vs/languages/razor/common/razor';
import {MockModeService} from 'vs/editor/test/common/mocks/mockModeService';
suite('Syntax Highlighting - Razor', () => {
var tokenizationSupport: Modes.ITokenizationSupport;
suiteSetup(function() {
let mode = new RAZORMode(
{ id: 'razor' },
null,
new MockModeService(),
null,
null,
null
);
tokenizationSupport = Modes.TokenizationRegistry.get(mode.getId());
});
test('', () => {
modesUtil.executeTests(tokenizationSupport,[
// Embedding - embedded html
[{
line: '@{ var x; <b>x</b> }',
tokens: [
{ startIndex: 0, type: razorTokenTypes.EMBED_CS },
{ startIndex: 2, type: '' },
{ startIndex: 3, type: 'keyword.cs' },
{ startIndex: 6, type: '' },
{ startIndex: 7, type: 'ident.cs' },
{ startIndex: 8, type: 'punctuation.cs' },
{ startIndex: 9, type: '' },
{ startIndex: 10, type: htmlTokenTypes.DELIM_START },
{ startIndex: 11, type: htmlTokenTypes.getTag('b') },
{ startIndex: 12, type: htmlTokenTypes.DELIM_START },
{ startIndex: 13, type: 'ident.cs' },
{ startIndex: 14, type: htmlTokenTypes.DELIM_END },
{ startIndex: 16, type: htmlTokenTypes.getTag('b') },
{ startIndex: 17, type: htmlTokenTypes.DELIM_END },
{ startIndex: 18, type: '' },
{ startIndex: 19, type: razorTokenTypes.EMBED_CS }
]}],
// Comments - razor comment inside csharp
[{
line: '@{ var x; @* comment *@ x= 0; }',
tokens: [
{ startIndex: 0, type: razorTokenTypes.EMBED_CS },
{ startIndex: 2, type: '' },
{ startIndex: 3, type: 'keyword.cs' },
{ startIndex: 6, type: '' },
{ startIndex: 7, type: 'ident.cs' },
{ startIndex: 8, type: 'punctuation.cs' },
{ startIndex: 9, type: '' },
{ startIndex: 10, type: 'comment.cs' },
{ startIndex: 23, type: '' },
{ startIndex: 24, type: 'ident.cs' },
{ startIndex: 25, type: 'punctuation.cs' },
{ startIndex: 26, type: '' },
{ startIndex: 27, type: 'number.cs' },
{ startIndex: 28, type: 'punctuation.cs' },
{ startIndex: 29, type: '' },
{ startIndex: 30, type: razorTokenTypes.EMBED_CS }
]}],
// Blocks - simple
[{
line: '@{ var total = 0; }',
tokens: [
{ startIndex: 0, type: razorTokenTypes.EMBED_CS },
{ startIndex: 2, type: '' },
{ startIndex: 3, type: 'keyword.cs' },
{ startIndex: 6, type: '' },
{ startIndex: 7, type: 'ident.cs' },
{ startIndex: 12, type: '' },
{ startIndex: 13, type: 'punctuation.cs' },
{ startIndex: 14, type: '' },
{ startIndex: 15, type: 'number.cs' },
{ startIndex: 16, type: 'punctuation.cs' },
{ startIndex: 17, type: '' },
{ startIndex: 18, type: razorTokenTypes.EMBED_CS }
]}],
[{
line: '@if(true){ var total = 0; }',
tokens: [
{ startIndex: 0, type: razorTokenTypes.EMBED_CS },
{ startIndex: 1, type: 'keyword.cs' },
{ startIndex: 3, type: 'punctuation.parenthesis.cs' },
{ startIndex: 4, type: 'keyword.cs' },
{ startIndex: 8, type: 'punctuation.parenthesis.cs' },
{ startIndex: 9, type: razorTokenTypes.EMBED_CS },
{ startIndex: 10, type: '' },
{ startIndex: 11, type: 'keyword.cs' },
{ startIndex: 14, type: '' },
{ startIndex: 15, type: 'ident.cs' },
{ startIndex: 20, type: '' },
{ startIndex: 21, type: 'punctuation.cs' },
{ startIndex: 22, type: '' },
{ startIndex: 23, type: 'number.cs' },
{ startIndex: 24, type: 'punctuation.cs' },
{ startIndex: 25, type: '' },
{ startIndex: 26, type: razorTokenTypes.EMBED_CS }
]}],
// Expressions - csharp expressions in html
[{
line: 'test@xyz<br>',
tokens: [
{ startIndex:0, type: '' },
{ startIndex:4, type: razorTokenTypes.EMBED_CS },
{ startIndex:5, type: 'ident.cs' },
{ startIndex:8, type: htmlTokenTypes.DELIM_START },
{ startIndex:9, type: htmlTokenTypes.getTag('br') },
{ startIndex:11, type: htmlTokenTypes.DELIM_START }
]}],
[{
line: 'test@xyz',
tokens: [
{ startIndex:0, type: '' },
{ startIndex:4, type: razorTokenTypes.EMBED_CS },
{ startIndex:5, type: 'ident.cs' }
]}],
[{
line: 'test @ xyz',
tokens: [
{ startIndex: 0, type: '' },
{ startIndex: 5, type: razorTokenTypes.EMBED_CS },
{ startIndex: 6, type: '' },
{ startIndex: 7, type: 'ident.cs' }
]}],
[{
line: 'test @(foo) xyz',
tokens: [
{ startIndex:0, type: '' },
{ startIndex:5, type: razorTokenTypes.EMBED_CS },
{ startIndex:7, type: 'ident.cs' },
{ startIndex:10, type: razorTokenTypes.EMBED_CS },
{ startIndex:11, type: '' }
]}],
[{
line: 'test @(foo(\")\")) xyz',
tokens: [
{ startIndex:0, type: '' },
{ startIndex:5, type: razorTokenTypes.EMBED_CS },
{ startIndex:7, type: 'ident.cs' },
{ startIndex:10, type: 'punctuation.parenthesis.cs' },
{ startIndex:11, type: 'string.cs' },
{ startIndex:14, type: 'punctuation.parenthesis.cs' },
{ startIndex:15, type: razorTokenTypes.EMBED_CS },
{ startIndex:16, type: '' }
]}],
// Escaping - escaped at character
[{
line: 'test@@xyz',
tokens: [
{ startIndex:0, type: '' }
]}]
]);
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册