UnrefinedBrain / vue-metamorph

Codemod Framework for Vue projects
https://vue-metamorph.dev/
MIT License
72 stars 1 forks source link

Cannot split a chunk that has already been edited #113

Closed haoliangwu closed 2 weeks ago

haoliangwu commented 2 weeks ago

hi again, it me. 😂

recently, I met a issue about this message, it seems a bug I think.

the plugin I implemented is try to refactor code based on guideline: https://v3-migration.vuejs.org/breaking-changes/v-bind.html

the testcase is following:

  test.only('case 2', () => {
    const source = `<template>
  <SitemapItem :id="!isShow" v-bind="passProps" />
</template>`

    const expected = `<template>
  <SitemapItem v-bind="passProps" :id="!isShow" />
</template>`

    expect(
      transform(source, 'file.vue', [compatibleVBindCodemod], baseOptions).code
    ).toBe(expected)
  })

the plugin souce is:

import { namedTypes as n } from 'ast-types'
import { CodemodPlugin } from 'vue-metamorph'

const cwd = process.cwd()

export const compatibleVBindCodemod: CodemodPlugin = {
  type: 'codemod',
  name: 'compatible-v-bind',
  transform({
    scriptASTs,
    sfcAST,
    utils: { traverseScriptAST, traverseTemplateAST, astHelpers, builders },
    opts,
  }) {
    let transformCount = 0

    if (sfcAST) {
      const templateElement = astHelpers.findFirst(sfcAST, {
        type: 'VElement',
        name: 'template',
      })

      if (templateElement) {
        const elements = astHelpers.findAll(templateElement, {
          type: 'VElement',
        })

        elements.forEach(({ startTag: { attributes } }) => {
          const idx = attributes.findIndex((attr) => {
            return (
              attr.key.type === 'VDirectiveKey' && attr.key.name.rawName === 'bind'
            )
          })

          if (idx > 0) {
            // @ts-expect-error ignore the type checking
            ;[attributes[0], attributes[idx]] = [attributes[idx], attributes[0]]

            transformCount++
          }
        })
      }
    }

    return transformCount
  },
}

the plugin resulted in error like this:

image

after debug and testing, I found as long as I update the testcase to(removing the ! before isShow):

  test.only('case 2', () => {
    const source = `<template>
  <SitemapItem :id="isShow" v-bind="passProps" />
</template>`

    const expected = `<template>
  <SitemapItem v-bind="passProps" :id="isShow" />
</template>`

    expect(
      transform(source, 'file.vue', [compatibleVBindCodemod], baseOptions).code
    ).toBe(expected)
  })

then the plugin works as expected:

image

with my debug of vue-metamorph, the issue seems like related to eslint-vue-parser and maybe is same issue of https://github.com/UnrefinedBrain/vue-metamorph/issues/102.

UnrefinedBrain commented 2 weeks ago

thanks for reporting. I had an off-by-one error in the transform code 😅

should be fixed in v3.1.11