Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lint): add type-aware rules #12497

Open
wants to merge 27 commits into
base: minor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
30e4d3b
test(lint): use tsslint
johnsoncodehk Dec 3, 2024
c93ecb0
chore: update tsslint to 1.3.0
johnsoncodehk Dec 4, 2024
196d4ea
test(lint): add type-aware rule "no-unnecessary-type-assertion"
johnsoncodehk Dec 4, 2024
7f27d1c
fix(lint): enable type-aware rules in IDE
johnsoncodehk Dec 4, 2024
b288c66
Merge branch 'minor' into tsslint
johnsoncodehk Dec 4, 2024
50418ae
chore: bump tsslint
johnsoncodehk Dec 5, 2024
2404539
test(lint): add type-aware rules "await-thenable", "require-await"
johnsoncodehk Dec 5, 2024
aa17d35
test(lint): add type-aware rule "consistent-type-exports"
johnsoncodehk Dec 5, 2024
f7412e5
test(lint): add type-aware rule "no-unnecessary-type-arguments"
johnsoncodehk Dec 5, 2024
187801b
test(lint): add rule "no-unnecessary-type-arguments"
johnsoncodehk Dec 5, 2024
155ad8c
test(lint): add type-aware rule "non-nullable-type-assertion-style"
johnsoncodehk Dec 5, 2024
1206756
Update tsslint.config.ts
johnsoncodehk Dec 5, 2024
3b7d649
test(lint): remove "require-await"
johnsoncodehk Dec 5, 2024
f543161
test(lint): add "require-await" as a suggestion rule
johnsoncodehk Dec 6, 2024
b732cc5
Update package.json
johnsoncodehk Dec 6, 2024
579430c
chore: bump tsslint
johnsoncodehk Dec 8, 2024
69b0e19
chore: bump tsslint
johnsoncodehk Dec 8, 2024
2c7404b
Merge branch 'minor' into tsslint
johnsoncodehk Dec 8, 2024
2e93661
Update pnpm-lock.yaml
johnsoncodehk Dec 8, 2024
2f0575b
chore: bump tsslint
johnsoncodehk Dec 10, 2024
df8a929
chore: update imports
johnsoncodehk Dec 10, 2024
b51ac72
chore: bump tsslint
johnsoncodehk Dec 15, 2024
6b419e1
chore: bump tsslint
johnsoncodehk Dec 15, 2024
d0cb983
chore: bump tsslint
johnsoncodehk Dec 16, 2024
f1f8faa
chore: bump tsslint
johnsoncodehk Dec 16, 2024
3c2b7fa
chore: update package.json
johnsoncodehk Dec 16, 2024
f82ef98
chore: bump tsslint
johnsoncodehk Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 9 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
"size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
"check": "tsc --incremental --noEmit",
"lint": "eslint --cache .",
"lint": "tsslint --project tsconfig.json",
"lint-types": "npm run lint -- --type-aware",
"format": "prettier --write --cache .",
"format-check": "prettier --check --cache .",
"test": "vitest",
Expand Down Expand Up @@ -54,7 +55,7 @@
"prettier --write"
],
"*.ts?(x)": [
"eslint --fix",
"npm run lint -- --fix",
"prettier --parser=typescript --write"
]
},
Expand All @@ -70,19 +71,22 @@
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-replace": "5.0.4",
"@swc/core": "^1.9.3",
"@tsslint/cli": "~1.4.6",
"@tsslint/config": "~1.4.6",
"@tsslint/eslint": "~1.4.6",
"@types/hash-sum": "^1.0.2",
"@types/node": "^22.10.1",
"@types/semver": "^7.5.8",
"@types/serve-handler": "^6.1.4",
"@typescript-eslint/eslint-plugin": "^8.17.0",
"@vitest/coverage-v8": "^2.1.5",
"@vitest/eslint-plugin": "^1.1.14",
"@vue/consolidate": "1.0.0",
"conventional-changelog-cli": "^5.0.0",
"enquirer": "^2.4.1",
"esbuild": "^0.24.0",
"esbuild-plugin-polyfill-node": "^0.3.0",
"eslint": "^9.15.0",
"eslint-plugin-import-x": "^4.4.2",
"@vitest/eslint-plugin": "^1.1.10",
"eslint-plugin-import-x": "^4.4.3",
"estree-walker": "catalog:",
"jsdom": "^25.0.1",
"lint-staged": "^15.2.10",
Expand All @@ -108,19 +112,7 @@
"todomvc-app-css": "^2.4.3",
"tslib": "^2.8.1",
"typescript": "~5.6.2",
"typescript-eslint": "^8.14.0",
"vite": "catalog:",
"vitest": "^2.1.5"
},
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"typescript-eslint>eslint": "^9.0.0",
"@typescript-eslint/eslint-plugin>eslint": "^9.0.0",
"@typescript-eslint/parser>eslint": "^9.0.0",
"@typescript-eslint/type-utils>eslint": "^9.0.0",
"@typescript-eslint/utils>eslint": "^9.0.0"
}
}
}
}
2 changes: 1 addition & 1 deletion packages/compiler-core/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ describe('compiler: parse', () => {
test('text with mix of tags and interpolations', () => {
const ast = baseParse('some <span>{{ foo < bar + foo }} text</span>')
const text1 = ast.children[0] as TextNode
const text2 = (ast.children[1] as ElementNode).children![1] as TextNode
const text2 = (ast.children[1] as ElementNode).children[1] as TextNode

expect(text1).toStrictEqual({
type: NodeTypes.TEXT,
Expand Down
7 changes: 3 additions & 4 deletions packages/compiler-core/__tests__/transforms/vIf.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ describe('compiler: v-if', () => {
// #2058 since a component may fail to resolve and fallback to a plain
// element, it still needs to be made a block
expect(
((node.branches[0].children[0] as ElementNode)!
.codegenNode as VNodeCall)!.isBlock,
((node.branches[0].children[0] as ElementNode).codegenNode as VNodeCall)
.isBlock,
).toBe(true)
})

Expand Down Expand Up @@ -702,8 +702,7 @@ describe('compiler: v-if', () => {
expect(b1b1.children[0].type).toBe(NodeTypes.COMMENT)
expect((b1b1.children[0] as CommentNode).content).toBe('comment2')

const b1b2: IfBranchNode = (b1.children[1] as IfNode)
.branches[1] as IfBranchNode
const b1b2: IfBranchNode = (b1.children[1] as IfNode).branches[1]
expect(b1b2.children[0].type).toBe(NodeTypes.COMMENT)
expect((b1b2.children[0] as CommentNode).content).toBe(`comment3`)
expect(b1b2.children[1].type).toBe(NodeTypes.ELEMENT)
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-core/src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -768,8 +768,8 @@ function genCompoundExpression(
node: CompoundExpressionNode,
context: CodegenContext,
) {
for (let i = 0; i < node.children!.length; i++) {
const child = node.children![i]
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i]
if (isString(child)) {
context.push(child, NewlineType.Unknown)
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-core/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,15 @@ const tokenizer = new Tokenizer(stack, {
// assign value

// condense whitespaces in class
if (currentProp!.name === 'class') {
if (currentProp.name === 'class') {
currentAttrValue = condense(currentAttrValue).trim()
}

if (quote === QuoteType.Unquoted && !currentAttrValue) {
emitError(ErrorCodes.MISSING_ATTRIBUTE_VALUE, end)
}

currentProp!.value = {
currentProp.value = {
type: NodeTypes.TEXT,
content: currentAttrValue,
loc:
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-core/src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ export function createTransformContext(
if (identifiers[id] === undefined) {
identifiers[id] = 0
}
identifiers[id]!++
identifiers[id]++
}

function removeId(id: string) {
Expand Down
15 changes: 5 additions & 10 deletions packages/compiler-core/src/transforms/transformExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,7 @@ import {
makeMap,
} from '@vue/shared'
import { ErrorCodes, createCompilerError } from '../errors'
import type {
AssignmentExpression,
Identifier,
Node,
UpdateExpression,
} from '@babel/types'
import type { Identifier, Node } from '@babel/types'
import { validateBrowserExpression } from '../validateExpression'
import { parseExpression } from '@babel/parser'
import { IS_REF, UNREF } from '../runtimeHelpers'
Expand Down Expand Up @@ -169,7 +164,7 @@ export function processExpression(
// let is a local non-ref value, and we need to replicate the
// right hand side value.
// x = y --> isRef(x) ? x.value = y : x = y
const { right: rVal, operator } = parent as AssignmentExpression
const { right: rVal, operator } = parent
const rExp = rawExp.slice(rVal.start! - 1, rVal.end! - 1)
const rExpString = stringifyExpression(
processExpression(
Expand All @@ -186,9 +181,9 @@ export function processExpression(
} else if (isUpdateArg) {
// make id replace parent in the code range so the raw update operator
// is removed
id!.start = parent!.start
id!.end = parent!.end
const { prefix: isPrefix, operator } = parent as UpdateExpression
id.start = parent.start
id.end = parent.end
const { prefix: isPrefix, operator } = parent
const prefix = isPrefix ? operator : ``
const postfix = isPrefix ? `` : operator
// let binding.
Expand Down
3 changes: 1 addition & 2 deletions packages/compiler-core/src/transforms/vFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
type PlainElementNode,
type RenderSlotCall,
type SimpleExpressionNode,
type SlotOutletNode,
type VNodeCall,
createBlockStatement,
createCallExpression,
Expand Down Expand Up @@ -159,7 +158,7 @@ export const transformFor: NodeTransform = createStructuralDirectiveTransform(
: isTemplate &&
node.children.length === 1 &&
isSlotOutlet(node.children[0])
? (node.children[0] as SlotOutletNode) // api-extractor somehow fails to infer this
? node.children[0] // api-extractor somehow fails to infer this
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this comment referring to the now removed assertion?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what this comment means. This comment was added in b685805, I reset to that commit and confirmed that the type of children[0] is not SlotOutletNode, so I think this comment may be not related to the removed assertion.

image

: null

if (slotOutlet) {
Expand Down
4 changes: 1 addition & 3 deletions packages/compiler-core/src/transforms/vIf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,7 @@ function createChildrenCodegenNode(
)
}
} else {
const ret = (firstChild as ElementNode).codegenNode as
| BlockCodegenNode
| MemoExpression
const ret = firstChild.codegenNode as BlockCodegenNode | MemoExpression
const vnodeCall = getMemoedVNodeCall(ret)
// Change createVNode to createBlock.
if (vnodeCall.type === NodeTypes.VNODE_CALL) {
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-dom/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ describe('DOM parser', () => {

test('CDATA', () => {
const ast = parse('<svg><![CDATA[some text]]></svg>', parserOptions)
const text = (ast.children[0] as ElementNode).children![0] as TextNode
const text = (ast.children[0] as ElementNode).children[0] as TextNode

expect(text).toStrictEqual({
type: NodeTypes.TEXT,
Expand Down
3 changes: 1 addition & 2 deletions packages/compiler-dom/src/decodeHtmlBrowser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/* eslint-disable no-restricted-globals */

let decoder: HTMLDivElement

export function decodeHtmlBrowser(raw: string, asAttr = false): string {
if (!decoder) {
// eslint-disable-next-line no-restricted-globals
decoder = document.createElement('div')
}
if (asAttr) {
Expand Down
4 changes: 1 addition & 3 deletions packages/compiler-dom/src/transforms/vOn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ const resolveModifiers = (
// runtimeModifiers: modifiers that needs runtime guards
if (maybeKeyModifier(modifier)) {
if (isStaticExp(key)) {
if (
isKeyboardEvent((key as SimpleExpressionNode).content.toLowerCase())
) {
if (isKeyboardEvent(key.content.toLowerCase())) {
keyModifiers.push(modifier)
} else {
nonKeyModifiers.push(modifier)
Expand Down
10 changes: 5 additions & 5 deletions packages/compiler-sfc/__tests__/compileTemplate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
type SFCTemplateCompileOptions,
compileTemplate,
} from '../src/compileTemplate'
import { type SFCTemplateBlock, parse } from '../src/parse'
import { parse } from '../src/parse'
import { compileScript } from '../src'

function compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {
Expand Down Expand Up @@ -52,7 +52,7 @@ body
</template>
`,
{ filename: 'example.vue', sourceMap: true },
).descriptor.template as SFCTemplateBlock
).descriptor.template!

const result = compile({
filename: 'example.vue',
Expand All @@ -76,7 +76,7 @@ test('preprocess pug with indents and blank lines', () => {
</template>
`,
{ filename: 'example.vue', sourceMap: true },
).descriptor.template as SFCTemplateBlock
).descriptor.template!

const result = compile({
filename: 'example.vue',
Expand All @@ -94,7 +94,7 @@ test('warn missing preprocessor', () => {
const template = parse(`<template lang="unknownLang">hi</template>\n`, {
filename: 'example.vue',
sourceMap: true,
}).descriptor.template as SFCTemplateBlock
}).descriptor.template!

const result = compile({
filename: 'example.vue',
Expand Down Expand Up @@ -337,7 +337,7 @@ test('preprocessor errors', () => {
</template>
`,
{ filename: 'example.vue', sourceMap: true },
).descriptor.template as SFCTemplateBlock
).descriptor.template!

const result = compile({
filename: 'example.vue',
Expand Down
12 changes: 6 additions & 6 deletions packages/compiler-sfc/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ font-weight: bold;

const consumer = new SourceMapConsumer(script!.map!)
consumer.eachMapping(mapping => {
expect(mapping.originalLine - mapping.generatedLine).toBe(padding)
expect(mapping.originalLine! - mapping.generatedLine).toBe(padding)
})
})

Expand All @@ -100,8 +100,8 @@ font-weight: bold;

const consumer = new SourceMapConsumer(template.map!)
consumer.eachMapping(mapping => {
expect(mapping.originalLine - mapping.generatedLine).toBe(padding)
expect(mapping.originalColumn - mapping.generatedColumn).toBe(2)
expect(mapping.originalLine! - mapping.generatedLine).toBe(padding)
expect(mapping.originalColumn! - mapping.generatedColumn).toBe(2)
})
})

Expand All @@ -111,11 +111,11 @@ font-weight: bold;
`${'\n'.repeat(padding)}<i18n>\n{\n "greeting": "hello"\n}\n</i18n>\n`,
).descriptor.customBlocks[0]

expect(custom!.map).not.toBeUndefined()
expect(custom.map).not.toBeUndefined()

const consumer = new SourceMapConsumer(custom!.map!)
const consumer = new SourceMapConsumer(custom.map!)
consumer.eachMapping(mapping => {
expect(mapping.originalLine - mapping.generatedLine).toBe(padding)
expect(mapping.originalLine! - mapping.generatedLine).toBe(padding)
})
})
})
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/compileScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ function walkDeclaration(
isAllLiteral = node.members.every(
member => !member.initializer || isStaticNode(member.initializer),
)
bindings[node.id!.name] = isAllLiteral
bindings[node.id.name] = isAllLiteral
? BindingTypes.LITERAL_CONST
: BindingTypes.SETUP_CONST
} else if (
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-sfc/src/compileTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ function mapLines(oldMap: RawSourceMap, newMap: RawSourceMap): RawSourceMap {

const origPosInOldMap = oldMapConsumer.originalPositionFor({
line: m.originalLine,
column: m.originalColumn,
column: m.originalColumn!,
})

if (origPosInOldMap.source == null) {
Expand All @@ -305,7 +305,7 @@ function mapLines(oldMap: RawSourceMap, newMap: RawSourceMap): RawSourceMap {
line: origPosInOldMap.line, // map line
// use current column, since the oldMap produced by @vue/compiler-sfc
// does not
column: m.originalColumn,
column: m.originalColumn!,
},
source: origPosInOldMap.source,
name: origPosInOldMap.name,
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/script/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class ScriptCompileContext {

this.scriptSetupAst =
descriptor.scriptSetup &&
parse(descriptor.scriptSetup!.content, this.startOffset!)
parse(descriptor.scriptSetup.content, this.startOffset!)
}

getString(node: Node, scriptSetup = true): string {
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/script/definePropsDestructure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export function transformDestructuredProps(

if (node.type === 'Identifier') {
if (
isReferencedIdentifier(node, parent!, parentStack) &&
isReferencedIdentifier(node, parent, parentStack) &&
!excludedIds.has(node)
) {
if (currentScope[node.name]) {
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/script/resolveType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@ function recordType(
if (existing) {
if (node.type === 'TSModuleDeclaration') {
if (existing.type === 'TSModuleDeclaration') {
mergeNamespaces(existing as typeof node, node)
mergeNamespaces(existing, node)
} else {
attachNamespace(existing, node)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/style/preprocessors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const scss: StylePreprocessor = (source, map, options, load = require) => {
code: css,
errors: [],
dependencies,
map: merge(map, sourceMap!),
map: merge(map, sourceMap),
}
}
return { code: css, errors: [], dependencies }
Expand Down
6 changes: 3 additions & 3 deletions packages/reactivity/__tests__/collections/Set.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('reactivity/collections', () => {

it('should observe for of iteration', () => {
let dummy
const set = reactive(new Set() as Set<number>)
const set = reactive(new Set<number>())
effect(() => {
dummy = 0
for (let num of set) {
Expand Down Expand Up @@ -82,7 +82,7 @@ describe('reactivity/collections', () => {

it('should observe values iteration', () => {
let dummy
const set = reactive(new Set() as Set<number>)
const set = reactive(new Set<number>())
effect(() => {
dummy = 0
for (let num of set.values()) {
Expand All @@ -102,7 +102,7 @@ describe('reactivity/collections', () => {

it('should observe keys iteration', () => {
let dummy
const set = reactive(new Set() as Set<number>)
const set = reactive(new Set<number>())
effect(() => {
dummy = 0
for (let num of set.keys()) {
Expand Down
Loading
Loading