Skip to content

Commit

Permalink
TypeScript is not a compat mode
Browse files Browse the repository at this point in the history
  • Loading branch information
alexdima committed Apr 7, 2016
1 parent 3af5cc7 commit 3e16b9b
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 150 deletions.
23 changes: 22 additions & 1 deletion src/vs/editor/browser/standalone/standaloneCodeEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ export function createCustomMode(language:ILanguage): TPromise<IMode> {
return modeService.getOrCreateMode(modeId);
}

export function registerStandaloneLanguage(language:ILanguageExtensionPoint, defModule:string): void {
export function registerMonarchStandaloneLanguage(language:ILanguageExtensionPoint, defModule:string): void {
ModesRegistry.registerLanguage(language);

ExtensionsRegistry.registerOneTimeActivationEventListener('onLanguage:' + language.id, () => {
Expand All @@ -463,6 +463,27 @@ export function registerStandaloneLanguage(language:ILanguageExtensionPoint, def
});
}

export function registerStandaloneLanguage(language:ILanguageExtensionPoint, defModule:string): void {
ModesRegistry.registerLanguage(language);

ExtensionsRegistry.registerOneTimeActivationEventListener('onLanguage:' + language.id, () => {
require([defModule], (value:{activate:()=>void}) => {
if (!value.activate) {
console.error('Expected ' + defModule + ' to export an `activate` function');
return;
}

startup.initStaticServicesIfNecessary();
let staticPlatformServices = ensureStaticPlatformServices(null);
let instantiationService = staticPlatformServices.instantiationService;

instantiationService.invokeFunction(value.activate);
}, (err) => {
console.error('Cannot find module ' + defModule, err);
});
});
}

export function registerStandaloneSchema(uri:string, schema:IJSONSchema) {
let schemaRegistry = <IJSONContributionRegistry>Registry.as(Extensions.JSONContribution);
schemaRegistry.registerSchema(uri, schema);
Expand Down
7 changes: 6 additions & 1 deletion src/vs/editor/browser/standalone/standaloneEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,16 @@ Monaco.Editor.OverlayWidgetPositionPreference = OverlayWidgetPositionPreference;
// Register all built-in standalone languages
let MonacoEditorLanguages: ILanguageDef[] = this.MonacoEditorLanguages || [];
MonacoEditorLanguages.forEach((language) => {
standaloneCodeEditor.registerStandaloneLanguage(language, language.defModule);
standaloneCodeEditor.registerMonarchStandaloneLanguage(language, language.defModule);
});

// Register all built-in standalone JSON schemas
let MonacoEditorSchemas: { [url:string]: IJSONSchema } = this.MonacoEditorSchemas || {};
for (var uri in MonacoEditorSchemas) {
standaloneCodeEditor.registerStandaloneSchema(uri, MonacoEditorSchemas[uri]);
}

if (!Monaco.Languages) {
Monaco.Languages = {};
}
Monaco.Languages.register = standaloneCodeEditor.registerStandaloneLanguage;
228 changes: 108 additions & 120 deletions src/vs/languages/typescript/common/mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,143 +6,131 @@

import * as modes from 'vs/editor/common/modes';
import * as lifecycle from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {createTokenizationSupport, Language} from 'vs/languages/typescript/common/tokenization';
import {AbstractMode, createWordRegExp} from 'vs/editor/common/modes/abstractMode';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
import {createWordRegExp} from 'vs/editor/common/modes/abstractMode';
import {RichEditSupport, IRichEditConfiguration} from 'vs/editor/common/modes/supports/richEditSupport';
import {IModelService} from 'vs/editor/common/services/modelService';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IMarkerService} from 'vs/platform/markers/common/markers';
import {IThreadService} from 'vs/platform/thread/common/thread';
import {LanguageServiceDefaults, typeScriptDefaults, javaScriptDefaults, LanguageServiceMode, TypeScriptWorkerProtocol} from './typescript';
import {LanguageServiceDefaults, typeScriptDefaults, javaScriptDefaults, LanguageServiceMode} from './typescript';
import {register} from './languageFeatures';
import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation';

export abstract class Mode extends AbstractMode implements lifecycle.IDisposable, LanguageServiceMode {
function setupMode(modelService:IModelService, markerService:IMarkerService, modeService:IModeService, defaults:LanguageServiceDefaults, modeId:string, language:Language): void {

public tokenizationSupport: modes.ITokenizationSupport;
public richEditSupport: modes.IRichEditSupport;
let disposables: lifecycle.IDisposable[] = [];
let languageServiceMode: LanguageServiceMode;

private _languageServiceMode: LanguageServiceMode;
private _disposables: lifecycle.IDisposable[] = [];
require(['vs/languages/typescript/common/workerManager'], workerManager => {

constructor(
descriptor: modes.IModeDescriptor,
defaults:LanguageServiceDefaults,
@IThreadService threadService: IThreadService,
@IModelService private _modelService: IModelService,
@IMarkerService private _markerService: IMarkerService
) {
super(descriptor.id);
const client = <LanguageServiceMode & lifecycle.IDisposable>workerManager.create(defaults, modelService);

if (threadService.isInMainThread && _modelService && _markerService) {
languageServiceMode = client;
disposables.push(client);

// this is needed as long as this mode is also instantiated in the worker
require(['vs/languages/typescript/common/workerManager'], workerManager => {
const registration = register(
modelService,
markerService,
modeId,
defaults,
(first, ...more) => client.getLanguageServiceWorker(...[first].concat(more))
);
disposables.push(registration);

const client = <LanguageServiceMode & lifecycle.IDisposable>workerManager.create(defaults, this._modelService);
this._languageServiceMode = client;
this._disposables.push(client);
}, err => {
console.error(err);
});

const registration = register(this._modelService, this._markerService,
this.getId(), defaults,
(first, ...more) => client.getLanguageServiceWorker(...[first].concat(more)));
this._disposables.push(registration);
modeService.registerRichEditSupport(modeId, richEditConfiguration);
modeService.registerTokenizationSupport(modeId, (mode) => {
return createTokenizationSupport(mode, language);
});
}

}, err => {
console.error(err);
});
const richEditConfiguration:IRichEditConfiguration = {
wordPattern: createWordRegExp('$'),

comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},

brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],

onEnterRules: [
{
// e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: { indentAction: modes.IndentAction.IndentOutdent, appendText: ' * ' }
},
{
// e.g. /** ...|
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: { indentAction: modes.IndentAction.None, appendText: ' * ' }
},
{
// e.g. * ...|
beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: { indentAction: modes.IndentAction.None, appendText: '* ' }
},
{
// e.g. */|
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: { indentAction: modes.IndentAction.None, removeText: 1 }
}

this.richEditSupport = new RichEditSupport(this.getId(), null, {
wordPattern: createWordRegExp('$'),

comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},

brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],

onEnterRules: [
{
// e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: { indentAction: modes.IndentAction.IndentOutdent, appendText: ' * ' }
},
{
// e.g. /** ...|
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: { indentAction: modes.IndentAction.None, appendText: ' * ' }
},
{
// e.g. * ...|
beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: { indentAction: modes.IndentAction.None, appendText: '* ' }
},
{
// e.g. */|
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: { indentAction: modes.IndentAction.None, removeText: 1 }
}
],

__electricCharacterSupport: {
docComment: {scope:'comment.doc', open:'/**', lineStart:' * ', close:' */'}
},

__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
{ open: '`', close: '`' }
]
}
});
}

dispose(): void {
this._disposables = lifecycle.dispose(this._disposables);
],

__electricCharacterSupport: {
docComment: {scope:'comment.doc', open:'/**', lineStart:' * ', close:' */'}
},

__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
{ open: '`', close: '`' }
]
}
};

getLanguageServiceWorker(...resources: URI[]): TPromise<TypeScriptWorkerProtocol> {
if (this._languageServiceMode) {
return this._languageServiceMode.getLanguageServiceWorker(...resources);
}
}
export function createRichEditSupport(modeId:string): RichEditSupport {
return new RichEditSupport(modeId, null, richEditConfiguration);
}

export class TypeScriptMode extends Mode {

constructor(
descriptor: modes.IModeDescriptor,
@IThreadService threadService: IThreadService,
@IModelService modelService: IModelService,
@IMarkerService markerService: IMarkerService
) {
super(descriptor, typeScriptDefaults, threadService, modelService, markerService);

this.tokenizationSupport = createTokenizationSupport(this, Language.TypeScript);
let isActivated = false;
export function activate(ctx:ServicesAccessor): void {
if (isActivated) {
return;
}
isActivated = true;

let modelService = ctx.get(IModelService);
let markerService = ctx.get(IMarkerService);
let modeService = ctx.get(IModeService);

setupMode(
modelService,
markerService,
modeService,
typeScriptDefaults,
'typescript',
Language.TypeScript
);

setupMode(
modelService,
markerService,
modeService,
javaScriptDefaults,
'javascript',
Language.EcmaScript5
);
}

export class JavaScriptMode extends Mode {

constructor(
descriptor: modes.IModeDescriptor,
@IThreadService threadService: IThreadService,
@IModelService modelService: IModelService,
@IMarkerService markerService: IMarkerService
) {
super(descriptor, javaScriptDefaults, threadService, modelService, markerService);

this.tokenizationSupport = createTokenizationSupport(this, Language.EcmaScript5);
}
}
14 changes: 5 additions & 9 deletions src/vs/languages/typescript/common/typescript.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,22 @@
*--------------------------------------------------------------------------------------------*/
'use strict';

import {ModesRegistry} from 'vs/editor/common/modes/modesRegistry';
import {registerStandaloneLanguage} from 'vs/editor/browser/standalone/standaloneCodeEditor';

// ----- Registration and Configuration --------------------------------------------------------

ModesRegistry.registerCompatMode({
registerStandaloneLanguage({
id: 'typescript',
extensions: ['.ts'],
aliases: ['TypeScript', 'ts', 'typescript'],
mimetypes: ['text/typescript'],
moduleId: 'vs/languages/typescript/common/mode',
ctorName: 'TypeScriptMode'
});
}, 'vs/languages/typescript/common/mode');

ModesRegistry.registerCompatMode({
registerStandaloneLanguage({
id: 'javascript',
extensions: ['.js', '.es6'],
firstLine: '^#!.*\\bnode',
filenames: ['jakefile'],
aliases: ['JavaScript', 'javascript', 'js'],
mimetypes: ['text/javascript'],
moduleId: 'vs/languages/typescript/common/mode',
ctorName: 'JavaScriptMode'
});
}, 'vs/languages/typescript/common/mode');
24 changes: 5 additions & 19 deletions src/vs/languages/typescript/test/common/tokenization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,14 @@

import Modes = require('vs/editor/common/modes');
import modesUtil = require('vs/editor/test/common/modesUtil');

import {NULL_THREAD_SERVICE} from 'vs/platform/test/common/nullThreadService';
import {JavaScriptMode} from 'vs/languages/typescript/common/mode';
import {createTokenizationSupport, Language} from 'vs/languages/typescript/common/tokenization';
import {MockMode} from 'vs/editor/test/common/mocks/mockMode';
import {createRichEditSupport} from 'vs/languages/typescript/common/mode';

suite('TS/JS - syntax highlighting', () => {

var tokenizationSupport: Modes.ITokenizationSupport;
var assertOnEnter: modesUtil.IOnEnterAsserter;

setup(() => {
let threadService = NULL_THREAD_SERVICE;

let mode = new JavaScriptMode(
{ id: 'javascript' },
threadService,
null,
null
);

tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
});
var tokenizationSupport = createTokenizationSupport(new MockMode('javascript'), Language.EcmaScript5);
var assertOnEnter = modesUtil.createOnEnterAsserter('javascript', createRichEditSupport('javascript'));

test('onEnter', function() {
assertOnEnter.nothing('', '', 'var f = function() {');
Expand Down

0 comments on commit 3e16b9b

Please sign in to comment.