From 3989e2d7f611019abacfe5ded5662ac3b11bd034 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 31 May 2018 11:25:26 +0200 Subject: [PATCH] Fixes #48758: Do not import standalone editor modules --- build/lib/tslint/noStandaloneEditorRule.js | 72 +++++++++++++++++++ build/lib/tslint/noStandaloneEditorRule.ts | 65 +++++++++++++++++ .../electron-browser/terminalPanel.ts | 3 +- .../electron-browser/textFileService.ts | 3 +- .../parts/views/contributableViews.test.ts | 4 +- .../quickopen.perf.integrationTest.ts | 4 +- .../textsearch.perf.integrationTest.ts | 4 +- tslint.json | 3 +- 8 files changed, 147 insertions(+), 11 deletions(-) create mode 100644 build/lib/tslint/noStandaloneEditorRule.js create mode 100644 build/lib/tslint/noStandaloneEditorRule.ts diff --git a/build/lib/tslint/noStandaloneEditorRule.js b/build/lib/tslint/noStandaloneEditorRule.js new file mode 100644 index 0000000000000..4bb57bbc322be --- /dev/null +++ b/build/lib/tslint/noStandaloneEditorRule.js @@ -0,0 +1,72 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ts = require("typescript"); +var Lint = require("tslint"); +var path_1 = require("path"); +var Rule = /** @class */ (function (_super) { + __extends(Rule, _super); + function Rule() { + return _super !== null && _super.apply(this, arguments) || this; + } + Rule.prototype.apply = function (sourceFile) { + if (/vs(\/|\\)editor/.test(sourceFile.fileName)) { + // the vs/editor folder is allowed to use the standalone editor + return []; + } + return this.applyWithWalker(new NoStandaloneEditorRuleWalker(sourceFile, this.getOptions())); + }; + return Rule; +}(Lint.Rules.AbstractRule)); +exports.Rule = Rule; +var NoStandaloneEditorRuleWalker = /** @class */ (function (_super) { + __extends(NoStandaloneEditorRuleWalker, _super); + function NoStandaloneEditorRuleWalker(file, opts) { + return _super.call(this, file, opts) || this; + } + NoStandaloneEditorRuleWalker.prototype.visitImportEqualsDeclaration = function (node) { + if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { + this._validateImport(node.moduleReference.expression.getText(), node); + } + }; + NoStandaloneEditorRuleWalker.prototype.visitImportDeclaration = function (node) { + this._validateImport(node.moduleSpecifier.getText(), node); + }; + NoStandaloneEditorRuleWalker.prototype.visitCallExpression = function (node) { + _super.prototype.visitCallExpression.call(this, node); + // import('foo') statements inside the code + if (node.expression.kind === ts.SyntaxKind.ImportKeyword) { + var path = node.arguments[0]; + this._validateImport(path.getText(), node); + } + }; + NoStandaloneEditorRuleWalker.prototype._validateImport = function (path, node) { + // remove quotes + path = path.slice(1, -1); + // resolve relative paths + if (path[0] === '.') { + path = path_1.join(this.getSourceFile().fileName, path); + } + if (/vs(\/|\\)editor(\/|\\)standalone/.test(path) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.api/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.main/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.worker/.test(path)) { + this.addFailure(this.createFailure(node.getStart(), node.getWidth(), "Not allowed to import standalone editor modules. See https://github.com/Microsoft/vscode/wiki/Code-Organization")); + } + }; + return NoStandaloneEditorRuleWalker; +}(Lint.RuleWalker)); diff --git a/build/lib/tslint/noStandaloneEditorRule.ts b/build/lib/tslint/noStandaloneEditorRule.ts new file mode 100644 index 0000000000000..b85e2da037a7b --- /dev/null +++ b/build/lib/tslint/noStandaloneEditorRule.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as ts from 'typescript'; +import * as Lint from 'tslint'; +import { join } from 'path'; + +export class Rule extends Lint.Rules.AbstractRule { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + if (/vs(\/|\\)editor/.test(sourceFile.fileName)) { + // the vs/editor folder is allowed to use the standalone editor + return []; + } + return this.applyWithWalker(new NoStandaloneEditorRuleWalker(sourceFile, this.getOptions())); + } +} + +class NoStandaloneEditorRuleWalker extends Lint.RuleWalker { + + constructor(file: ts.SourceFile, opts: Lint.IOptions) { + super(file, opts); + } + + protected visitImportEqualsDeclaration(node: ts.ImportEqualsDeclaration): void { + if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { + this._validateImport(node.moduleReference.expression.getText(), node); + } + } + + protected visitImportDeclaration(node: ts.ImportDeclaration): void { + this._validateImport(node.moduleSpecifier.getText(), node); + } + + protected visitCallExpression(node: ts.CallExpression): void { + super.visitCallExpression(node); + + // import('foo') statements inside the code + if (node.expression.kind === ts.SyntaxKind.ImportKeyword) { + const [path] = node.arguments; + this._validateImport(path.getText(), node); + } + } + + private _validateImport(path: string, node: ts.Node): void { + // remove quotes + path = path.slice(1, -1); + + // resolve relative paths + if (path[0] === '.') { + path = join(this.getSourceFile().fileName, path); + } + + if ( + /vs(\/|\\)editor(\/|\\)standalone/.test(path) + || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.api/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.main/.test(path) + || /vs(\/|\\)editor(\/|\\)editor.worker/.test(path) + ) { + this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Not allowed to import standalone editor modules. See https://github.com/Microsoft/vscode/wiki/Code-Organization`)); + } + } +} diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 7b194643901c5..09e090d2b5c7a 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -26,9 +26,8 @@ import { PANEL_BACKGROUND, PANEL_BORDER } from 'vs/workbench/common/theme'; import { TERMINAL_BACKGROUND_COLOR, TERMINAL_BORDER_COLOR } from 'vs/workbench/parts/terminal/common/terminalColorRegistry'; import { DataTransfers } from 'vs/base/browser/dnd'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; -import { Severity } from 'vs/editor/editor.api'; export class TerminalPanel extends Panel { diff --git a/src/vs/workbench/services/textfile/electron-browser/textFileService.ts b/src/vs/workbench/services/textfile/electron-browser/textFileService.ts index 102689704fdbe..fcb157c88074e 100644 --- a/src/vs/workbench/services/textfile/electron-browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/electron-browser/textFileService.ts @@ -28,9 +28,8 @@ import { IWindowsService, IWindowService } from 'vs/platform/windows/common/wind import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IModelService } from 'vs/editor/common/services/modelService'; -import { INotificationService } from 'vs/platform/notification/common/notification'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { getConfirmMessage, IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { Severity } from 'vs/editor/common/standalone/standaloneBase'; export class TextFileService extends AbstractTextFileService { diff --git a/src/vs/workbench/test/browser/parts/views/contributableViews.test.ts b/src/vs/workbench/test/browser/parts/views/contributableViews.test.ts index 4153fce6fc125..98f7e160276cd 100644 --- a/src/vs/workbench/test/browser/parts/views/contributableViews.test.ts +++ b/src/vs/workbench/test/browser/parts/views/contributableViews.test.ts @@ -8,7 +8,7 @@ import { ContributableViewsModel } from 'vs/workbench/browser/parts/views/contri import { ViewLocation, ViewsRegistry, IViewDescriptor } from 'vs/workbench/common/views'; import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { SimpleConfigurationService } from 'vs/editor/standalone/browser/simpleServices'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { move } from 'vs/base/common/arrays'; @@ -35,7 +35,7 @@ suite('ContributableViewsModel', () => { let contextKeyService: IContextKeyService; setup(() => { - const configurationService = new SimpleConfigurationService(); + const configurationService = new TestConfigurationService(); contextKeyService = new ContextKeyService(configurationService); }); diff --git a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts index 23f83bea217f2..c049422b043cf 100644 --- a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts @@ -26,7 +26,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; -import { SimpleConfigurationService } from 'vs/editor/standalone/browser/simpleServices'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -69,7 +69,7 @@ suite.skip('QuickOpen performance (integration)', () => { const telemetryService = new TestTelemetryService(); const experimentService = new TestExperimentService(); - const configurationService = new SimpleConfigurationService(); + const configurationService = new TestConfigurationService(); const instantiationService = new InstantiationService(new ServiceCollection( [ITelemetryService, telemetryService], [IExperimentService, experimentService], diff --git a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts index 11fe299a61899..0af7279142bc3 100644 --- a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts @@ -24,7 +24,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; -import { SimpleConfigurationService } from 'vs/editor/standalone/browser/simpleServices'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -58,7 +58,7 @@ suite.skip('TextSearch performance (integration)', () => { } const telemetryService = new TestTelemetryService(); - const configurationService = new SimpleConfigurationService(); + const configurationService = new TestConfigurationService(); const instantiationService = new InstantiationService(new ServiceCollection( [ITelemetryService, telemetryService], [IConfigurationService, configurationService], diff --git a/tslint.json b/tslint.json index 6e26e8166d0ed..1fcafd325b6f3 100644 --- a/tslint.json +++ b/tslint.json @@ -459,7 +459,8 @@ } ], "duplicate-imports": true, - "translation-remind": true + "translation-remind": true, + "no-standalone-editor": true }, "defaultSeverity": "warning" } \ No newline at end of file