Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
Parse all ESM import types
  • Loading branch information
philipp-spiess committed Oct 14, 2024
commit dc793f176897dbaa94ab3b18e0cfc2c02e79b76f
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,23 @@ import { extractStaticImportMap, findSimplePlugins } from './extract-static-impo

const js = dedent

test('extracts different kind of imports from a source file', () => {
test('extracts different kind of imports from an ESM file', () => {
let extracted = extractStaticImportMap(js`
import plugin1 from './plugin1'
// import * as plugin2 from './plugin2'
import * as plugin2 from './plugin2'
import plugin6, { plugin3, plugin4, default as plugin5 } from './plugin3'
// import * as plugin7, { plugin8, foo as plugin9 } from './plugin7'

// const plugin6 = require('plugin6')
// const {plugin7} = require('plugin7')
// const {foo: plugin8} = require('plugin8')
// let plugin9 = require('plugin9')
// let {plugin10} = require('plugin10')
// let {foo: plugin11} = require('plugin11')
// let plugin12 = require('plugin12')
// let {plugin13} = require('plugin13')
// let {foo: plugin14} = require('plugin14')
import plugin8, * as plugin7 from './plugin7'
`)

expect(extracted).toEqual({
plugin1: { module: './plugin1', export: null },
// plugin2: { module: './plugin2', export: 'plugin2' },
plugin2: { module: './plugin2', export: '*' },
plugin3: { module: './plugin3', export: 'plugin3' },
plugin4: { module: './plugin3', export: 'plugin4' },
plugin5: { module: './plugin3', export: 'default' },
plugin6: { module: './plugin3', export: null },
plugin7: { module: './plugin7', export: '*' },
plugin8: { module: './plugin7', export: null },

// plugin6: { module: 'plugin6', export: null },
// plugin7: { module: 'plugin7', export: 'plugin7' },
Expand All @@ -46,12 +38,13 @@ test('find simple plugins', () => {
expect(
findSimplePlugins(js`
import plugin1 from './plugin1'
import * as plugin2 from './plugin2'

export default {
plugins: [plugin1, 'plugin2']
plugins: [plugin1, plugin2, 'plugin3']
}
`),
).toEqual(['./plugin1', 'plugin2'])
).toEqual(['./plugin1', './plugin2', 'plugin3'])

expect(
findSimplePlugins(js`
Expand Down
61 changes: 20 additions & 41 deletions packages/@tailwindcss-upgrade/src/utils/extract-static-imports.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,70 @@
import Parser from 'tree-sitter'
import TS from 'tree-sitter-typescript'

console.log({ TS })
let parser = new Parser()
parser.setLanguage(TS.typescript)
const treesitter = String.raw

const IMPORT_QUERY = new Parser.Query(
const ESM_IMPORT_QUERY = new Parser.Query(
TS.typescript,
treesitter`
; import foo, {foo as bar} from './foo'
(import_statement
(import_clause
(identifier)? @default
(named_imports
(import_specifier
name: (identifier) @imported-name
alias: (identifier)? @imported-alias
)
)?
(named_imports
(import_specifier
name: (identifier) @imported-name
alias: (identifier)? @imported-alias
)
)?
(namespace_import (identifier) @imported-namespace)?
)
(string
(string_fragment) @imported-from)
)`,

// ; import * as foo from './foo'
// (import_statement
// (import_clause
// (namespace_import
// (identifier) @imported-name))
// (string
// (string_fragment) @imported-from)
// )
// `,
)

export function extractStaticImportMap(source: string) {
let tree = parser.parse(source)
let root = tree.rootNode

let captures = IMPORT_QUERY.matches(root)
let captures = ESM_IMPORT_QUERY.matches(root)

let imports: Record<string, { module: string; export: string | null }> = {}
for (let match of captures) {
let toImport: { name: string; source: null | string }[] = []
let toImport: { name: string; export: null | string }[] = []
let from = ''
for (let i = 0; i < match.captures.length; i++) {
let capture = match.captures[i]

switch (capture.name) {
case 'default':
toImport.push({ name: capture.node.text, source: null })
toImport.push({ name: capture.node.text, export: null })
break
case 'imported-name':
toImport.push({ name: capture.node.text, source: capture.node.text })
toImport.push({ name: capture.node.text, export: capture.node.text })
break
case 'imported-from':
from = capture.node.text
break
case 'imported-namespace':
toImport.push({ name: capture.node.text, export: '*' })
break
case 'imported-alias':
if (toImport.length < 1) {
throw new Error()
throw new Error('Unexpected alias: ' + JSON.stringify(captures, null, 2))
}
let prevImport = toImport[toImport.length - 1]
let name = prevImport.name
prevImport.source = name
prevImport.export = name
prevImport.name = capture.node.text
break
}
}

for (let { name, source } of toImport) {
imports[name] = { module: from, export: source }
for (let { name, export: exportSource } of toImport) {
imports[name] = { module: from, export: exportSource }
}

// console.log({ imported, from })

// console.log(match.captures.map((c) => ({ name: c.name, text: c.node.text })))
// console.log('+++++++++++++++++++++++++==')
// let name = match.captures.find((c) => c.name === 'imported-name')
// let from = match.captures.find((c) => c.name === 'imported-from')

// if (!name || !from) continue

// imports[name.node.text] = { module: from.node.text, export: null }
}

return imports
Expand Down Expand Up @@ -122,8 +103,6 @@ export function findSimplePlugins(source: string): string[] | null {
let imports = extractStaticImportMap(source)
let captures = PLUGINS_QUERY.matches(root)

console.dir({ captures }, { depth: 4 })

let plugins = []
for (let match of captures) {
for (let capture of match.captures) {
Expand All @@ -140,7 +119,7 @@ export function findSimplePlugins(source: string): string[] | null {
switch (pluginDefinition.type) {
case 'identifier':
let source = imports[pluginDefinition.text]
if (!source || source.export !== null) {
if (!source || (source.export !== null && source.export !== '*')) {
return null
}
plugins.push(source.module)
Expand Down