importUsageCheck.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { SFCDescriptor } from '../parse'
  2. import {
  3. NodeTypes,
  4. SimpleExpressionNode,
  5. parserOptions,
  6. walkIdentifiers,
  7. TemplateChildNode,
  8. ExpressionNode
  9. } from '@vue/compiler-dom'
  10. import { createCache } from '../cache'
  11. import { camelize, capitalize, isBuiltInDirective } from '@vue/shared'
  12. /**
  13. * Check if an import is used in the SFC's template. This is used to determine
  14. * the properties that should be included in the object returned from setup()
  15. * when not using inline mode.
  16. */
  17. export function isImportUsed(local: string, sfc: SFCDescriptor): boolean {
  18. return resolveTemplateUsageCheckString(sfc).has(local)
  19. }
  20. const templateUsageCheckCache = createCache<Set<string>>()
  21. function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
  22. const { content, ast } = sfc.template!
  23. const cached = templateUsageCheckCache.get(content)
  24. if (cached) {
  25. return cached
  26. }
  27. const ids = new Set<string>()
  28. ast!.children.forEach(walk)
  29. function walk(node: TemplateChildNode) {
  30. switch (node.type) {
  31. case NodeTypes.ELEMENT:
  32. if (
  33. !parserOptions.isNativeTag!(node.tag) &&
  34. !parserOptions.isBuiltInComponent!(node.tag)
  35. ) {
  36. ids.add(camelize(node.tag))
  37. ids.add(capitalize(camelize(node.tag)))
  38. }
  39. for (let i = 0; i < node.props.length; i++) {
  40. const prop = node.props[i]
  41. if (prop.type === NodeTypes.DIRECTIVE) {
  42. if (!isBuiltInDirective(prop.name)) {
  43. ids.add(`v${capitalize(camelize(prop.name))}`)
  44. }
  45. // process dynamic directive arguments
  46. if (prop.arg && !(prop.arg as SimpleExpressionNode).isStatic) {
  47. extractIdentifiers(ids, prop.arg)
  48. }
  49. if (prop.name === 'for') {
  50. extractIdentifiers(ids, prop.forParseResult!.source)
  51. } else if (prop.exp) {
  52. extractIdentifiers(ids, prop.exp)
  53. }
  54. }
  55. if (
  56. prop.type === NodeTypes.ATTRIBUTE &&
  57. prop.name === 'ref' &&
  58. prop.value?.content
  59. ) {
  60. ids.add(prop.value.content)
  61. }
  62. }
  63. node.children.forEach(walk)
  64. break
  65. case NodeTypes.INTERPOLATION:
  66. extractIdentifiers(ids, node.content)
  67. break
  68. }
  69. }
  70. templateUsageCheckCache.set(content, ids)
  71. return ids
  72. }
  73. function extractIdentifiers(ids: Set<string>, node: ExpressionNode) {
  74. if (node.ast) {
  75. walkIdentifiers(node.ast, n => ids.add(n.name))
  76. } else if (node.ast === null) {
  77. ids.add((node as SimpleExpressionNode).content)
  78. }
  79. }