Skip to content

Commit

Permalink
build: clean generated type file (vitejs#14582)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy authored Oct 12, 2023
1 parent f54e6d8 commit fffe16e
Showing 1 changed file with 92 additions and 3 deletions.
95 changes: 92 additions & 3 deletions packages/vite/rollup.dts.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { findStaticImports } from 'mlly'
import { type Plugin, defineConfig } from 'rollup'
import dts from 'rollup-plugin-dts'

Expand Down Expand Up @@ -28,12 +29,34 @@ const multilineCommentsRE = /\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\//g
const singlelineCommentsRE = /\/\/[^/].*/g
const licenseCommentsRE = /MIT License|MIT license|BSD license/
const consecutiveNewlinesRE = /\n{2,}/g
const identifierWithTrailingDollarRE = /\b(\w+)\$\d+\b/g

/**
* Replace specific identifiers with a more readable name, grouped by
* the module that imports the identifer as a named import alias
*/
const identifierReplacements: Record<string, Record<string, string>> = {
rollup: {
Plugin$1: 'rollup.Plugin',
TransformResult$2: 'rollup.TransformResult',
},
esbuild: {
TransformResult$1: 'esbuild_TransformResult',
TransformOptions$1: 'esbuild_TransformOptions',
BuildOptions$1: 'esbuild_BuildOptions',
},
'node:https': {
Server$1: 'HttpsServer',
ServerOptions$1: 'HttpsServerOptions',
},
}

/**
* Patch the types files before passing to dts plugin
* 1. Resolve `dep-types/*` and `types/*` imports
* 2. Validate unallowed dependency imports
* 3. Clean unnecessary comments
* 3. Replace confusing type names
* 4. Clean unnecessary comments
*/
function patchTypes(): Plugin {
return {
Expand All @@ -56,8 +79,8 @@ function patchTypes(): Plugin {
}
},
renderChunk(code, chunk) {
const deps = new Set(Object.keys(pkg.dependencies))
// Validate that chunk imports do not import dev deps
const deps = new Set(Object.keys(pkg.dependencies))
for (const id of chunk.imports) {
if (
!id.startsWith('./') &&
Expand All @@ -72,13 +95,79 @@ function patchTypes(): Plugin {
}
}

// Rollup deduplicate type names with a trailing `$1` or `$2`, which can be
// confusing when showed in autocompletions. Try to replace with a better name
const imports = findStaticImports(code)
for (const modName in identifierReplacements) {
const imp = imports.find(
(imp) => imp.specifier === modName && imp.imports.includes('{'),
)
// Validate that `identifierReplacements` is not outdated if there's no match
if (!imp) {
this.warn(
`${chunk.fileName} does not import "${modName}" for replacement`,
)
process.exitCode = 1
continue
}

const replacements = identifierReplacements[modName]
for (const id in replacements) {
// Validate that `identifierReplacements` is not outdated if there's no match
if (!imp.imports.includes(id)) {
this.warn(
`${chunk.fileName} does not import "${id}" from "${modName}" for replacement`,
)
process.exitCode = 1
continue
}

const betterId = replacements[id]
const regexEscapedId = escapeRegex(id)
// If the better id accesses a namespace, the existing `Foo as Foo$1`
// named import cannot be replaced with `Foo as Namespace.Foo`, so we
// pre-emptively remove the whole named import
if (betterId.includes('.')) {
code = code.replace(
new RegExp(`\\b\\w+\\b as ${regexEscapedId},?\\s?`),
'',
)
}
code = code.replace(
new RegExp(`\\b${regexEscapedId}\\b`, 'g'),
betterId,
)
}
}
const unreplacedIds = unique(
Array.from(code.matchAll(identifierWithTrailingDollarRE), (m) => m[0]),
)
if (unreplacedIds.length) {
const unreplacedStr = unreplacedIds.map((id) => `\n- ${id}`).join('')
this.warn(
`${chunk.fileName} contains confusing identifier names${unreplacedStr}`,
)
process.exitCode = 1
}

// Clean unnecessary comments
return code
code = code
.replace(singlelineCommentsRE, '')
.replace(multilineCommentsRE, (m) => {
return licenseCommentsRE.test(m) ? '' : m
})
.replace(consecutiveNewlinesRE, '\n\n')

return code
},
}
}

const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g
function escapeRegex(str: string): string {
return str.replace(escapeRegexRE, '\\$&')
}

function unique<T>(arr: T[]): T[] {
return Array.from(new Set(arr))
}

0 comments on commit fffe16e

Please sign in to comment.