import { parseFrom, parseWith } from './partParsers.js'; import { addError, getPosition, spacesRegExp, stripComments } from './utils.js'; /** * Adds error of parsing `import` statement. */ export const onImportError = (importsExports, _source, { start, end }) => addError(importsExports, 'Cannot find end of `import` statement', start, end); /** * Parses `import` statement. */ export const onImportParse = (importsExports, source, { start, end: unparsedStart, comments }, { start: unparsedEnd, end: importEnd, match: endMatch, token: endToken }) => { var end = importEnd; var unparsed = stripComments(source, unparsedStart, unparsedEnd, comments); const quoteCharacter = endToken[0]; const { from, index } = parseFrom(quoteCharacter, unparsed); if (index === -1) { return addError(importsExports, 'Cannot find start of `from` string literal of import', start, end); } unparsed = unparsed.slice(0, index).trim().replace(spacesRegExp, ' '); var isType = false; if (unparsed.startsWith('type ')) { isType = true; unparsed = unparsed.slice(5); } if (unparsed.endsWith(' from')) { unparsed = unparsed.slice(0, -5); } var withAttributes; if (endMatch.groups['with'] !== undefined) { if (isType) { return addError(importsExports, `Cannot use import attributes (\`with {...}\`) in \`import type\` statement for import from \`${from}\``, start, end); } const attributes = parseWith(importEnd, source); if (attributes === undefined) { return addError(importsExports, `Cannot find end of import attributes (\`with {...}\`) in \`import\` statement for import from \`${from}\``, start, end); } end = attributes.endIndex; withAttributes = attributes.with; if (withAttributes === undefined) { return addError(importsExports, `Cannot parse import attributes (\`with {...}\`) in \`import\` statement for import from \`${from}\``, start, end); } } const position = getPosition(importsExports, start, end); const parsedImport = withAttributes === undefined ? position : { ...position, with: withAttributes }; const namespaceIndex = unparsed.indexOf('* as '); var key = 'namedImports'; if (namespaceIndex === -1) { const braceIndex = unparsed.indexOf('{'); if (braceIndex !== -1) { let namesString = unparsed.slice(braceIndex + 1); const braceCloseIndex = namesString.lastIndexOf('}'); unparsed = unparsed.slice(0, braceIndex); if (braceCloseIndex === -1) { return addError(importsExports, `Cannot find end of imports list (\`}\`) for import from \`${from}\``, start, end); } namesString = namesString.slice(0, braceCloseIndex).trim(); const namesList = namesString.split(','); let names; let types; for (let name of namesList) { let isTypeName = false; name = name.trim(); if (name === '') { continue; } const nameObject = {}; if (name.startsWith('type ')) { if (isType) { return addError(importsExports, `Cannot use \`type\` modifier in \`import type\` statement for type \`${name.slice(5)}\` for import from \`${from}\``, start, end); } isTypeName = true; name = name.slice(5); } const asIndex = name.indexOf(' as '); if (asIndex !== -1) { nameObject.by = name.slice(0, asIndex); name = name.slice(asIndex + 4); } if (isTypeName) { if (types === undefined) { types = { __proto__: null }; } else if (name in types) { return addError(importsExports, `Duplicate imported type \`${name}\` for import from \`${from}\``, start, end); } types[name] = nameObject; } else { if (names === undefined) { names = { __proto__: null }; } else if (name in names) { return addError(importsExports, `Duplicate imported name \`${name}\` for import from \`${from}\``, start, end); } names[name] = nameObject; } } if (names !== undefined) { parsedImport.names = names; } if (types !== undefined) { parsedImport.types = types; } } } else { parsedImport.namespace = unparsed.slice(namespaceIndex + 5); key = 'namespaceImports'; unparsed = unparsed.slice(0, namespaceIndex); } const commaIndex = unparsed.indexOf(','); if (commaIndex !== -1) { unparsed = unparsed.slice(0, commaIndex).trim(); } else { unparsed = unparsed.trim(); } if (unparsed !== '') { if (isType && key === 'namespaceImports') { return addError(importsExports, `Cannot use default \`${unparsed}\` and namespace \`${parsedImport.namespace}\` together in \`import type\` statement for import from \`${from}\``, start, end); } parsedImport.default = unparsed; } if (isType) { key = key === 'namedImports' ? 'typeNamedImports' : 'typeNamespaceImports'; } var imports = importsExports[key]; imports !== null && imports !== void 0 ? imports : (imports = importsExports[key] = { __proto__: null }); var importsList = imports[from]; if (importsList === undefined) { imports[from] = [parsedImport]; } else { importsList.push(parsedImport); } return end; };