Add eslint rule for disallowing dangerous type assertions (#211669)
This adds a new (off by default) eslint rule that disables two specific types of dangerous type assertions: ```ts <Type>{...}; {...} as Type; ``` These are bad because they can easily hide missing properties and strictness errors Right now just adding this rule but will assign out fixes to owners in different areas of the code
This commit is contained in:
Родитель
431afbe459
Коммит
001929db91
|
@ -0,0 +1,40 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as eslint from 'eslint';
|
||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
||||
|
||||
export = new class NoDangerousTypeAssertions implements eslint.Rule.RuleModule {
|
||||
|
||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||
// Disable in tests for now
|
||||
if (context.getFilename().includes('.test')) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
// Disallow type assertions on object literals: <T>{ ... } or {} as T
|
||||
['TSTypeAssertion > ObjectExpression, TSAsExpression > ObjectExpression']: (node: any) => {
|
||||
const objectNode = node as TSESTree.Node;
|
||||
|
||||
const parent = objectNode.parent as TSESTree.TSTypeAssertion | TSESTree.TSAsExpression;
|
||||
if (
|
||||
// Allow `as const` assertions
|
||||
(parent.typeAnnotation.type === 'TSTypeReference' && parent.typeAnnotation.typeName.type === 'Identifier' && parent.typeAnnotation.typeName.name === 'cost')
|
||||
|
||||
// For also now still allow `any` casts
|
||||
|| (parent.typeAnnotation.type === 'TSAnyKeyword')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
message: "Don't use type assertions for creating objects as this can hide type errors."
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
|
@ -73,6 +73,7 @@
|
|||
"local/code-parameter-properties-must-have-explicit-accessibility": "warn",
|
||||
"local/code-no-nls-in-standalone-editor": "warn",
|
||||
"local/code-no-potentially-unsafe-disposables": "warn",
|
||||
"local/code-no-dangerous-type-assertions": "off",
|
||||
"local/code-no-standalone-editor": "warn",
|
||||
"local/code-no-unexternalized-strings": "warn",
|
||||
"local/code-must-use-super-dispose": "warn",
|
||||
|
|
|
@ -246,7 +246,7 @@ export class FoldingRegions {
|
|||
}
|
||||
|
||||
public toFoldRange(index: number): FoldRange {
|
||||
return <FoldRange>{
|
||||
return {
|
||||
startLineNumber: this._startIndexes[index] & MAX_LINE_NUMBER,
|
||||
endLineNumber: this._endIndexes[index] & MAX_LINE_NUMBER,
|
||||
type: this._types ? this._types[index] : undefined,
|
||||
|
|
|
@ -370,7 +370,7 @@ export function registerChatCodeBlockActions() {
|
|||
const editorService = accessor.get(IEditorService);
|
||||
const chatService = accessor.get(IChatService);
|
||||
|
||||
editorService.openEditor(<IUntitledTextResourceEditorInput>{ contents: context.code, languageId: context.languageId, resource: undefined });
|
||||
editorService.openEditor({ contents: context.code, languageId: context.languageId, resource: undefined } satisfies IUntitledTextResourceEditorInput);
|
||||
|
||||
if (isResponseVM(context.element)) {
|
||||
chatService.notifyUserAction({
|
||||
|
|
|
@ -59,7 +59,7 @@ export class MarkersFilters extends Disposable {
|
|||
set excludedFiles(filesExclude: boolean) {
|
||||
if (this._excludedFiles.get() !== filesExclude) {
|
||||
this._excludedFiles.set(filesExclude);
|
||||
this._onDidChange.fire(<IMarkersFiltersChangeEvent>{ excludedFiles: true });
|
||||
this._onDidChange.fire({ excludedFiles: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ export class MarkersFilters extends Disposable {
|
|||
set activeFile(activeFile: boolean) {
|
||||
if (this._activeFile.get() !== activeFile) {
|
||||
this._activeFile.set(activeFile);
|
||||
this._onDidChange.fire(<IMarkersFiltersChangeEvent>{ activeFile: true });
|
||||
this._onDidChange.fire({ activeFile: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ export class MarkersFilters extends Disposable {
|
|||
set showWarnings(showWarnings: boolean) {
|
||||
if (this._showWarnings.get() !== showWarnings) {
|
||||
this._showWarnings.set(showWarnings);
|
||||
this._onDidChange.fire(<IMarkersFiltersChangeEvent>{ showWarnings: true });
|
||||
this._onDidChange.fire({ showWarnings: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче