diff --git a/.eslintignore b/.eslintignore index 7037c1d793bd..c9779062d713 100644 --- a/.eslintignore +++ b/.eslintignore @@ -21,9 +21,6 @@ build/webpack/loaders/remarkLoader.js build/webpack/loaders/jsonloader.js build/webpack/loaders/externalizeDependencies.js -build/tslint-rules/messagesMustBeLocalizedRule.js -build/tslint-rules/baseRuleWalker.js - src/test/mocks/mementos.ts src/test/mocks/process.ts src/test/mocks/moduleInstaller.ts diff --git a/.github/workflows/insiders.yml b/.github/workflows/insiders.yml index 820d3975f0eb..070a7afbc8e4 100644 --- a/.github/workflows/insiders.yml +++ b/.github/workflows/insiders.yml @@ -78,8 +78,9 @@ jobs: - name: Check dependencies run: npm run checkDependencies - - name: Run linting on TypeScript code - run: npx tslint --project tsconfig.json + # TODO: Uncomment once we are ready to rely on eslint. + # - name: Run linting on TypeScript code + # run: npm run lint - name: Run prettier on TypeScript code run: npx prettier 'src/**/*.ts*' --check diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 0cf96637f11f..ee7ff2861b6c 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -78,8 +78,9 @@ jobs: - name: Check dependencies run: npm run checkDependencies - - name: Run linting on TypeScript code - run: npx tslint --project tsconfig.json + # TODO: Uncomment once we are ready to rely on eslint. + # - name: Run linting on TypeScript code + # run: npm run lint - name: Run prettier on TypeScript code run: npx prettier 'src/**/*.ts*' --check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6b62d0cccd3..d5871a64e530 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,8 +78,9 @@ jobs: - name: Check dependencies run: npm run checkDependencies - - name: Run linting on TypeScript code - run: npx tslint --project tsconfig.json + # TODO: Uncomment once we are ready to rely on eslint. + # - name: Run linting on TypeScript code + # run: npm run lint ### Non-smoke tests tests: diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f27b792c337d..9bede31b6433 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,7 +2,6 @@ // See https://go.microsoft.com/fwlink/?LinkId=827846 // for the documentation about the extensions.json format "recommendations": [ - "ms-vscode.vscode-typescript-tslint-plugin", "editorconfig.editorconfig", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint" diff --git a/.vscode/settings.json b/.vscode/settings.json index 9f729bd8127e..87f4fe0c61e1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -31,7 +31,6 @@ "editor.formatOnSave": true }, "typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version - "tslint.enable": true, "python.linting.enabled": false, "python.testing.promptToConfigure": false, "python.workspaceSymbols.enabled": false, @@ -42,8 +41,7 @@ "prettier.printWidth": 120, "prettier.singleQuote": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, - "source.fixAll.tslint": true + "source.fixAll.eslint": true }, "python.languageServer": "Pylance", "python.analysis.logLevel": "Trace", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 10322a98187d..ddab6a202525 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -12,13 +12,7 @@ "type": "npm", "script": "compile", "isBackground": true, - "problemMatcher": [ - "$tsc-watch", - { - "base": "$tslint5", - "fileLocation": "relative" - } - ], + "problemMatcher": ["$tsc-watch"], "group": { "kind": "build", "isDefault": true @@ -33,10 +27,7 @@ "kind": "build", "isDefault": true }, - "problemMatcher": [ - "$tsc-watch", - "$ts-checker-webpack-watch" - ] + "problemMatcher": ["$tsc-watch"] }, { "label": "Run Unit Tests", diff --git a/.vscodeignore b/.vscodeignore index 94742708a1c7..7c5cb570ab04 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -21,7 +21,6 @@ sprint-planning.github-issues test.ipynb tsconfig*.json tsfmt.json -tslint.json vscode-python-signing.* .github/** diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b80bc9d3c6a8..0370780f6837 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ The following projects have their own repositories: 1. Windows, macOS, or Linux 1. [Visual Studio Code](https://code.visualstudio.com/) 1. The following VS Code extensions: - - [TSLint](https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-tslint-plugin) + - [ESlint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) 1. Have an issue which has a "needs PR" label (feel free to indicate you would like to provide a PR for the issue so others don't work on it as well) @@ -49,7 +49,7 @@ If you see warnings that `The engine "vscode" appears to be invalid.`, you can i ### Incremental Build -Run the `Compile` and `Hygiene` build Tasks from the [Run Build Task...](https://code.visualstudio.com/docs/editor/tasks) command picker (short cut `CTRL+SHIFT+B` or `⇧⌘B`). This will leave build and hygiene tasks running in the background and which will re-run as files are edited and saved. You can see the output from either task in the Terminal panel (use the selector to choose which output to look at). +Run the `Compile` build task from the [Run Build Task...](https://code.visualstudio.com/docs/editor/tasks) command picker (short cut `CTRL+SHIFT+B` or `⇧⌘B`). This will leave build task running in the background and which will re-run as files are edited and saved. You can see the output from either task in the Terminal panel (use the selector to choose which output to look at). You can also compile from the command-line. For a full compile you can use: diff --git a/build/tslint-rules/baseRuleWalker.js b/build/tslint-rules/baseRuleWalker.js deleted file mode 100644 index b8ce93d4179d..000000000000 --- a/build/tslint-rules/baseRuleWalker.js +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -'use strict'; - -const path = require('path'); -const Lint = require('tslint'); -const util = require('../util'); -class BaseRuleWalker extends Lint.RuleWalker { - shouldIgnoreCurrentFile(node, filesToIgnore) { - const sourceFile = node.getSourceFile(); - if (sourceFile && sourceFile.fileName) { - const filename = path.resolve(util.ExtensionRootDir, sourceFile.fileName); - if (filesToIgnore.indexOf(filename.replace(/\//g, path.sep)) >= 0) { - return true; - } - } - return false; - } -} -exports.BaseRuleWalker = BaseRuleWalker; diff --git a/build/tslint-rules/messagesMustBeLocalizedRule.js b/build/tslint-rules/messagesMustBeLocalizedRule.js deleted file mode 100644 index acf4beaba811..000000000000 --- a/build/tslint-rules/messagesMustBeLocalizedRule.js +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -'use strict'; - -const path = require('path'); -const Lint = require('tslint'); -const ts = require('typescript'); -const util = require('../util'); -const baseRuleWalker = require('./baseRuleWalker'); -const methodNames = [ - // From IApplicationShell (vscode.window): - 'showErrorMessage', - 'showInformationMessage', - 'showWarningMessage', - 'setStatusBarMessage', - // From IOutputChannel (vscode.OutputChannel): - 'appendLine', - 'appendLine' -]; -// tslint:ignore-next-line:no-suspicious-comments -// TODO: Ideally we would not ignore any files. -const ignoredFiles = util.getListOfFiles('unlocalizedFiles.json'); -const ignoredPrefix = path.normalize('src/test'); -const failureMessage = 'Messages must be localized in the Python Extension (use src/client/common/utils/localize.ts)'; -class NoStringLiteralsInMessages extends baseRuleWalker.BaseRuleWalker { - visitCallExpression(node) { - if (!this.shouldIgnoreNode(node)) { - node.arguments - .filter((arg) => ts.isStringLiteral(arg) || ts.isTemplateLiteral(arg)) - .forEach((arg) => { - this.addFailureAtNode(arg, failureMessage); - }); - } - super.visitCallExpression(node); - } - shouldIgnoreCurrentFile(node) { - //console.log(''); - //console.log(node.getSourceFile().fileName); - //console.log(ignoredFiles); - if (super.shouldIgnoreCurrentFile(node, ignoredFiles)) { - return true; - } - const sourceFile = node.getSourceFile(); - if (sourceFile && sourceFile.fileName) { - if (sourceFile.fileName.startsWith(ignoredPrefix)) { - return true; - } - } - return false; - } - shouldIgnoreNode(node) { - if (this.shouldIgnoreCurrentFile(node)) { - return true; - } - if (!ts.isPropertyAccessExpression(node.expression)) { - return true; - } - const prop = node.expression; - if (methodNames.indexOf(prop.name.text) < 0) { - return true; - } - return false; - } -} -class Rule extends Lint.Rules.AbstractRule { - apply(sourceFile) { - return this.applyWithWalker(new NoStringLiteralsInMessages(sourceFile, this.getOptions())); - } -} -Rule.FAILURE_STRING = failureMessage; -exports.Rule = Rule; diff --git a/gulpfile.js b/gulpfile.js index 24afd73e1eba..c619a59e3e0e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,18 +9,10 @@ 'use strict'; const gulp = require('gulp'); -const filter = require('gulp-filter'); -const es = require('event-stream'); -const tsfmt = require('typescript-formatter'); -const tslint = require('tslint'); -const relative = require('relative'); const ts = require('gulp-typescript'); -const cp = require('child_process'); const spawn = require('cross-spawn'); -const colors = require('colors/safe'); const path = require('path'); const del = require('del'); -const sourcemaps = require('gulp-sourcemaps'); const fs = require('fs-extra'); const fsExtra = require('fs-extra'); const glob = require('glob'); @@ -33,69 +25,21 @@ const rmrf = require('rimraf'); const isCI = process.env.TRAVIS === 'true' || process.env.TF_BUILD !== undefined; -const noop = function () {}; -/** - * Hygiene works by creating cascading subsets of all our files and - * passing them through a sequence of checks. Here are the current subsets, - * named according to the checks performed on them. Each subset contains - * the following one, as described in mathematical notation: - * - * all ⊃ indentation ⊃ typescript - */ - -const all = ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.d.ts', 'src/**/*.js', 'src/**/*.jsx']; - -const tsFilter = ['src/**/*.ts*', '!out/**/*']; - -const indentationFilter = ['src/**/*.ts*', '!**/typings/**/*']; - -const tslintFilter = [ - 'src/**/*.ts*', - 'test/**/*.ts*', - '!**/node_modules/**', - '!out/**/*', - '!images/**/*', - '!.vscode/**/*', - '!pythonFiles/**/*', - '!resources/**/*', - '!syntaxes/**/*', - '!**/typings/**/*', - '!**/*.d.ts', -]; - gulp.task('compile', (done) => { let failed = false; const tsProject = ts.createProject('tsconfig.json'); tsProject .src() .pipe(tsProject()) - .on('error', () => (failed = true)) + .on('error', () => { + failed = true; + }) .js.pipe(gulp.dest('out')) .on('finish', () => (failed ? done(new Error('TypeScript compilation errors')) : done())); }); gulp.task('precommit', (done) => run({ exitOnError: true, mode: 'staged' }, done)); -gulp.task('hygiene-watch', () => gulp.watch(tsFilter, gulp.series('hygiene-modified'))); - -gulp.task('hygiene', (done) => run({ mode: 'compile', skipFormatCheck: true, skipIndentationCheck: true }, done)); - -gulp.task( - 'hygiene-modified', - gulp.series('compile', (done) => run({ mode: 'changes' }, done)), -); - -gulp.task('watch', gulp.parallel('hygiene-modified', 'hygiene-watch')); - -// Duplicate to allow duplicate task in tasks.json (one ith problem matching, and one without) -gulp.task('watchProblems', gulp.parallel('hygiene-modified', 'hygiene-watch')); - -gulp.task('hygiene-watch-branch', () => gulp.watch(tsFilter, gulp.series('hygiene-branch'))); - -gulp.task('hygiene-all', (done) => run({ mode: 'all' }, done)); - -gulp.task('hygiene-branch', (done) => run({ mode: 'diffMain' }, done)); - gulp.task('output:clean', () => del(['coverage'])); gulp.task('clean:cleanExceptTests', () => del(['clean:vsix', 'out/client', 'out/startPage-ui', 'out/server'])); @@ -200,7 +144,7 @@ async function buildWebPack(webpackConfigName, args, env) { const warnings = stdOutLines .filter((item) => item.startsWith('WARNING in ')) .filter( - (item) => allowedWarnings.findIndex((allowedWarning) => item.toLowerCase().startsWith(allowedWarning.toLowerCase())) == -1, + (item) => allowedWarnings.findIndex((allowedWarning) => item.toLowerCase().startsWith(allowedWarning.toLowerCase())) === -1, ); const errors = stdOutLines.some((item) => item.startsWith('ERROR in')); if (errors) { @@ -253,7 +197,7 @@ gulp.task('renameSourceMaps', async () => { gulp.task('verifyBundle', async () => { const matches = await glob.sync(path.join(__dirname, '*.vsix')); - if (!matches || matches.length == 0) { + if (!matches || matches.length === 0) { throw new Error('Bundle does not exist'); } else { console.log(`Bundle ${matches[0]} exists.`); @@ -337,24 +281,6 @@ gulp.task('installDebugpy', async () => { gulp.task('installPythonLibs', gulp.series('installPythonRequirements', 'installDebugpy')); -function uploadExtension(uploadBlobName) { - const azure = require('gulp-azure-storage'); - const rename = require('gulp-rename'); - return gulp - .src('*python*.vsix') - .pipe(rename(uploadBlobName)) - .pipe( - azure.upload({ - account: process.env.AZURE_STORAGE_ACCOUNT, - key: process.env.AZURE_STORAGE_ACCESS_KEY, - container: process.env.AZURE_STORAGE_CONTAINER, - }), - ); -} - -gulp.task('uploadDeveloperExtension', () => uploadExtension('ms-python-insiders.vsix')); -gulp.task('uploadReleaseExtension', () => uploadExtension(`ms-python-${process.env.TRAVIS_BRANCH || process.env.BUILD_SOURCEBRANCHNAME}.vsix`)); - function spawnAsync(command, args, env, rejectOnStdErr = false) { env = env || {}; env = { ...process.env, ...env }; @@ -399,441 +325,3 @@ function hasNativeDependencies() { } return false; } - -/** - * @typedef {Object} hygieneOptions - creates a new type named 'SpecialType' - * @property {'changes'|'staged'|'all'|'compile'|'diffMain'} [mode=] - Mode. - * @property {boolean=} skipIndentationCheck - Skip indentation checks. - * @property {boolean=} skipFormatCheck - Skip format checks. - * @property {boolean=} skipLinter - Skip linter. - */ - -/** - * - * @param {hygieneOptions} options - */ -function getTsProject(options) { - return ts.createProject('tsconfig.json'); -} - -let configuration; -/** - * - * @param {hygieneOptions} options - */ -function getLinter(options) { - configuration = configuration || tslint.Configuration.findConfiguration(null, '.'); - const program = tslint.Linter.createProgram('./tsconfig.json'); - const linter = new tslint.Linter({ formatter: 'json' }, program); - return { linter, configuration }; -} -let compilationInProgress = false; -let reRunCompilation = false; -/** - * - * @param {hygieneOptions} options - * @returns {NodeJS.ReadWriteStream} - */ -const hygiene = (options, done) => { - done = done || noop; - if (compilationInProgress) { - reRunCompilation = true; - return done(); - } - const fileListToProcess = options.mode === 'compile' ? undefined : getFileListToProcess(options); - if ( - Array.isArray(fileListToProcess) - && fileListToProcess !== all - && fileListToProcess.filter((item) => item.endsWith('.ts')).length === 0 - ) { - return done(); - } - - const started = new Date().getTime(); - compilationInProgress = true; - options = options || {}; - let errorCount = 0; - - const indentation = es.through(function (file) { - file.contents - .toString('utf8') - .split(/\r\n|\r|\n/) - .forEach((line, i) => { - if (/^\s*$/.test(line) || /^\S+.*$/.test(line)) { - // Empty or whitespace lines are OK. - } else if (/^(\s\s\s\s)+.*/.test(line)) { - // Good indent. - } else if (/^[\t]+.*/.test(line)) { - console.error( - `${file.relative - }(${ - i + 1 - },1): Bad whitespace indentation (use 4 spaces instead of tabs or other)`, - ); - errorCount++; - } - }); - - this.emit('data', file); - }); - - const formatOptions = { - verify: true, tsconfig: true, tslint: true, editorconfig: true, tsfmt: true, - }; - const formatting = es.map((file, cb) => { - tsfmt - .processString(file.path, file.contents.toString('utf8'), formatOptions) - .then((result) => { - if (result.error) { - let message = result.message.trim(); - let formattedMessage = ''; - if (message.startsWith(__dirname)) { - message = message.substr(__dirname.length); - message = message.startsWith(path.sep) ? message.substr(1) : message; - const index = message.indexOf('.ts '); - if (index === -1) { - formattedMessage = colors.red(message); - } else { - const file = message.substr(0, index + 3); - const errorMessage = message.substr(index + 4).trim(); - formattedMessage = `${colors.red(file)} ${errorMessage}`; - } - } else { - formattedMessage = colors.red(message); - } - console.error(formattedMessage); - errorCount++; - } - cb(null, file); - }) - .catch(cb); - }); - - let reportedLinterFailures = []; - /** - * Report the linter failures - * @param {any[]} failures - */ - function reportLinterFailures(failures) { - return ( - failures - .map((failure) => { - const name = failure.name || failure.fileName; - const position = failure.startPosition; - const line = position.lineAndCharacter ? position.lineAndCharacter.line : position.line; - const character = position.lineAndCharacter - ? position.lineAndCharacter.character - : position.character; - - // Output in format similar to tslint for the linter to pickup. - const message = `ERROR: (${failure.ruleName}) ${relative(__dirname, name)}[${line + 1}, ${ - character + 1 - }]: ${failure.failure}`; - if (reportedLinterFailures.indexOf(message) === -1) { - console.error(message); - reportedLinterFailures.push(message); - return true; - } - return false; - }) - .filter((reported) => reported === true).length > 0 - ); - } - - const { linter, configuration } = getLinter(options); - const tsl = es.through(function (file) { - const contents = file.contents.toString('utf8'); - if (isCI) { - // Don't print anything to the console, we'll do that. - console.log('.'); - } - // Yes this is a hack, but tslinter doesn't provide an option to prevent this. - const oldWarn = console.warn; - console.warn = () => {}; - linter.failures = []; - linter.fixes = []; - linter.lint(file.relative, contents, configuration.results); - console.warn = oldWarn; - const result = linter.getResult(); - if (result.failureCount > 0 || result.errorCount > 0) { - const reported = reportLinterFailures(result.failures); - if (result.failureCount && reported) { - errorCount += result.failureCount; - } - if (result.errorCount && reported) { - errorCount += result.errorCount; - } - } - this.emit('data', file); - }); - - const tsFiles = []; - const tscFilesTracker = es.through(function (file) { - tsFiles.push(file.path.replace(/\\/g, '/')); - tsFiles.push(file.path); - this.emit('data', file); - }); - - const tsProject = getTsProject(options); - - const tsc = function () { - function customReporter() { - return { - error(error, typescript) { - const fullFilename = error.fullFilename || ''; - const relativeFilename = error.relativeFilename || ''; - if (tsFiles.findIndex((file) => fullFilename === file || relativeFilename === file) === -1) { - return; - } - console.error(`Error: ${error.message}`); - errorCount += 1; - }, - finish() { - // forget the summary. - console.log('Finished compilation'); - }, - }; - } - const reporter = customReporter(); - return tsProject(reporter); - }; - - const files = options.mode === 'compile' ? tsProject.src() : getFilesToProcess(fileListToProcess); - const dest = options.mode === 'compile' ? './out' : '.'; - let result = files.pipe(filter((f) => f && f.stat && !f.stat.isDirectory())); - - if (!options.skipIndentationCheck) { - result = result.pipe(filter(indentationFilter)).pipe(indentation); - } - - result = result.pipe(filter(tslintFilter)); - - if (!options.skipFormatCheck) { - // result = result - // .pipe(formatting); - } - - if (!options.skipLinter) { - result = result.pipe(tsl); - } - const totalTime = 0; - result = result - .pipe(tscFilesTracker) - .pipe(sourcemaps.init()) - .pipe(tsc()) - .pipe( - sourcemaps.mapSources((sourcePath, file) => { - let tsFileName = path.basename(file.path).replace(/js$/, 'ts'); - const qualifiedSourcePath = path.dirname(file.path).replace('out/', 'src/').replace('out\\', 'src\\'); - if (!fs.existsSync(path.join(qualifiedSourcePath, tsFileName))) { - const tsxFileName = path.basename(file.path).replace(/js$/, 'tsx'); - if (!fs.existsSync(path.join(qualifiedSourcePath, tsxFileName))) { - console.error(`ERROR: (source-maps) ${file.path}[1,1]: Source file not found`); - } else { - tsFileName = tsxFileName; - } - } - return path.join(path.relative(path.dirname(file.path), qualifiedSourcePath), tsFileName); - }), - ) - .pipe(sourcemaps.write('.', { includeContent: false })) - .pipe(gulp.dest(dest)) - .pipe( - es.through(null, function () { - if (errorCount > 0) { - const errorMessage = `Hygiene failed with errors 👎 . Check 'gulpfile.js' (completed in ${ - new Date().getTime() - started - }ms).`; - console.error(colors.red(errorMessage)); - exitHandler(options); - } else { - console.log( - colors.green( - `Hygiene passed with 0 errors 👍 (completed in ${new Date().getTime() - started}ms).`, - ), - ); - } - // Reset error counter. - errorCount = 0; - reportedLinterFailures = []; - compilationInProgress = false; - if (reRunCompilation) { - reRunCompilation = false; - setTimeout(() => { - hygiene(options, done); - }, 10); - } - done(); - this.emit('end'); - }), - ) - .on('error', (ex) => { - exitHandler(options, ex); - done(); - }); - - return result; -}; - -/** - * @typedef {Object} runOptions - * @property {boolean=} exitOnError - Exit on error. - * @property {'changes'|'staged'|'all'} [mode=] - Mode. - * @property {string[]=} files - Optional list of files to be modified. - * @property {boolean=} skipIndentationCheck - Skip indentation checks. - * @property {boolean=} skipFormatCheck - Skip format checks. - * @property {boolean=} skipLinter - Skip linter. - * @property {boolean=} watch - Watch mode. - */ - -/** - * Run the linters. - * @param {runOptions} options - * @param {Error} ex - */ -function exitHandler(options, ex) { - console.error(); - if (ex) { - console.error(ex); - console.error(colors.red(ex)); - } - if (options.exitOnError) { - console.log('exit'); - process.exit(1); - } -} - -/** - * Run the linters. - * @param {runOptions} options - */ -function run(options, done) { - done = done || noop; - options = options || {}; - options.exitOnError = typeof options.exitOnError === 'undefined' ? isCI : options.exitOnError; - process.once('unhandledRejection', (reason, p) => { - console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); - exitHandler(options); - }); - - // Clear screen each time - console.log('\x1Bc'); - const startMessage = 'Hygiene starting'; - console.log(colors.blue(startMessage)); - - hygiene(options, done); -} - -function git(args) { - const result = cp.spawnSync('git', args, { encoding: 'utf-8' }); - return result.output.join('\n'); -} - -function getStagedFilesSync() { - const out = git(['diff', '--cached', '--name-only']); - return out.split(/\r?\n/).filter((l) => !!l); -} -function getAddedFilesSync() { - const out = git(['status', '-u', '-s']); - return out - .split(/\r?\n/) - .filter((l) => !!l) - .filter((l) => _.intersection(['A', '?', 'U'], l.substring(0, 2).trim().split('')).length > 0) - .map((l) => path.join(__dirname, l.substring(2).trim())); -} -function getAzureDevOpsVarValue(varName) { - return process.env[varName.replace(/\./g, '_').toUpperCase()]; -} -function getModifiedFilesSync() { - if (isCI) { - const isAzurePR = getAzureDevOpsVarValue('System.PullRequest.SourceBranch') !== undefined; - const isTravisPR = process.env.TRAVIS_PULL_REQUEST !== undefined && process.env.TRAVIS_PULL_REQUEST !== 'true'; - if (!isAzurePR && !isTravisPR) { - return []; - } - const targetBranch = process.env.TRAVIS_BRANCH || getAzureDevOpsVarValue('System.PullRequest.TargetBranch'); - if (targetBranch !== 'main') { - return []; - } - - const repo = process.env.TRAVIS_REPO_SLUG || getAzureDevOpsVarValue('Build.Repository.Name'); - const originOrUpstream = repo.toUpperCase() === 'MICROSOFT/VSCODE-PYTHON' - ? 'origin' - : 'upstream'; - - // If on CI, get a list of modified files comparing against - // PR branch and main of current (assumed 'origin') repo. - try { - cp.execSync(`git remote set-branches --add ${originOrUpstream} main`, { - encoding: 'utf8', - cwd: __dirname, - }); - cp.execSync('git fetch', { encoding: 'utf8', cwd: __dirname }); - } catch (ex) { - return []; - } - const cmd = `git diff --name-only HEAD ${originOrUpstream}/main`; - console.info(cmd); - const out = cp.execSync(cmd, { encoding: 'utf8', cwd: __dirname }); - return out - .split(/\r?\n/) - .filter((l) => !!l) - .filter((l) => l.length > 0) - .map((l) => l.trim().replace(/\//g, path.sep)) - .map((l) => path.join(__dirname, l)); - } - const out = cp.execSync('git status -u -s', { encoding: 'utf8' }); - return out - .split(/\r?\n/) - .filter((l) => !!l) - .filter( - (l) => _.intersection(['M', 'A', 'R', 'C', 'U', '?'], l.substring(0, 2).trim().split('')).length > 0, - ) - .map((l) => path.join(__dirname, l.substring(2).trim().replace(/\//g, path.sep))); -} - -function getDifferentFromMainFilesSync() { - const out = git(['diff', '--name-status', 'main']); - return out - .split(/\r?\n/) - .filter((l) => !!l) - .map((l) => path.join(__dirname, l.substring(2).trim())); -} - -/** - * @param {hygieneOptions} options - */ -function getFilesToProcess(fileList) { - const gulpSrcOptions = { base: '.' }; - return gulp.src(fileList, gulpSrcOptions); -} - -/** - * @param {hygieneOptions} options - */ -function getFileListToProcess(options) { - const mode = options ? options.mode : 'all'; - const gulpSrcOptions = { base: '.' }; - - // If we need only modified files, then filter the glob. - if (options && options.mode === 'changes') { - return getModifiedFilesSync().filter((f) => fs.existsSync(f)); - } - - if (options && options.mode === 'staged') { - return getStagedFilesSync().filter((f) => fs.existsSync(f)); - } - - if (options && options.mode === 'diffMain') { - return getDifferentFromMainFilesSync().filter((f) => fs.existsSync(f)); - } - - return all; -} - -exports.hygiene = hygiene; - -// this allows us to run hygiene via CLI (e.g. `node gulfile.js`). -if (require.main === module) { - run({ exitOnError: true, mode: 'staged' }, () => {}); -} diff --git a/package.json b/package.json index 8ffabfe38be1..acb2270c5068 100644 --- a/package.json +++ b/package.json @@ -1976,7 +1976,7 @@ "testSmoke": "cross-env INSTALL_JUPYTER_EXTENSION=true \"node ./out/test/smokeTest.js\"", "testInsiders": "cross-env VSC_PYTHON_CI_TEST_VSC_CHANNEL=insiders INSTALL_PYLANCE_EXTENSION=true TEST_FILES_SUFFIX=insiders.test CODE_TESTS_WORKSPACE=src/testMultiRootWkspc/smokeTests \"node ./out/test/standardTest.js\"", "lint-staged": "node gulpfile.js", - "lint": "tslint src/**/*.ts -t verbose", + "lint": "eslint --ext .ts,.tsx src", "prettier-fix": "prettier 'src/**/*.ts*' --write && prettier 'build/**/*.js' --write", "clean": "gulp clean", "addExtensionDependencies": "gulp addExtensionDependencies", @@ -2099,7 +2099,6 @@ "chai-as-promised": "^7.1.1", "chai-http": "^4.3.0", "codecov": "^3.7.1", - "colors": "^1.2.1", "copy-webpack-plugin": "^5.1.1", "cors": "^2.8.5", "cross-env": "^6.0.3", @@ -2119,7 +2118,6 @@ "eslint-plugin-prettier": "^3.1.2", "eslint-plugin-react": "^7.20.3", "eslint-plugin-react-hooks": "^4.0.0", - "event-stream": "3.3.4", "expose-loader": "^0.7.5", "express": "^4.17.1", "extract-zip": "^1.6.7", @@ -2131,7 +2129,6 @@ "gulp": "^4.0.0", "gulp-azure-storage": "^0.11.1", "gulp-chmod": "^2.0.0", - "gulp-filter": "^5.1.0", "gulp-gunzip": "^1.1.0", "gulp-rename": "^1.4.0", "gulp-sourcemaps": "^2.6.4", @@ -2173,7 +2170,6 @@ "react-dev-utils": "^5.0.2", "react-dom": "^16.5.2", "react-svgmt": "^1.1.8", - "relative": "^3.0.2", "remove-files-webpack-plugin": "^1.4.0", "requirejs": "^2.3.6", "rewiremock": "^3.13.0", @@ -2195,11 +2191,6 @@ "ts-mockito": "^2.5.0", "ts-node": "^8.3.0", "tsconfig-paths-webpack-plugin": "^3.2.0", - "tslint": "^5.20.1", - "tslint-config-prettier": "^1.18.0", - "tslint-eslint-rules": "^5.1.0", - "tslint-microsoft-contrib": "^5.0.3", - "tslint-plugin-prettier": "^2.1.0", "typed-react-markdown": "^0.1.0", "typemoq": "^2.1.0", "typescript": "^4.0.2", diff --git a/tslint.json b/tslint.json deleted file mode 100644 index c7085f82e361..000000000000 --- a/tslint.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "rulesDirectory": ["./build/tslint-rules"], - "extends": ["tslint-eslint-rules", "tslint-microsoft-contrib", "tslint-plugin-prettier", "tslint-config-prettier"], - "rules": { - "prettier": true, - "messages-must-be-localized": true, - "no-unused-expression": true, - "no-duplicate-variable": true, - "curly": true, - "non-literal-fs-path": false, - "newline-per-chained-call": false, - "class-name": true, - "semicolon": [true, "always", "strict-bound-class-methods"], - "triple-equals": true, - "no-relative-imports": false, - "max-line-length": false, - "max-func-body-length": false, - "typedef": false, - "no-string-throw": true, - "missing-jsdoc": false, - "one-line": [true, "check-catch", "check-finally", "check-else"], - "no-parameter-properties": false, - "no-parameter-reassignment": false, - "no-reserved-keywords": false, - "newline-before-return": false, - "export-name": false, - "align": false, - "linebreak-style": false, - "strict-boolean-expressions": false, - "await-promise": [true, "Thenable", "PromiseLike"], - "completed-docs": false, - "no-unsafe-any": false, - "no-backbone-get-set-outside-model": false, - "underscore-consistent-invocation": false, - "no-void-expression": false, - "no-non-null-assertion": false, - "prefer-type-cast": false, - "promise-function-async": false, - "function-name": false, - "variable-name": false, - "no-import-side-effect": false, - "no-string-based-set-timeout": false, - "no-floating-promises": true, - "no-empty-interface": false, - "no-bitwise": false, - "eofline": true, - "switch-final-break": false, - "no-implicit-dependencies": ["vscode"], - "no-unnecessary-type-assertion": false, - "no-submodule-imports": false, - "no-redundant-jsdoc": false, - "binary-expression-operand-order": false - } -}