False positive smells about unused imports when there are 2 script tags in Vue3

When using 2 script tags in Vue3, there are false positive code smells:

Remove unused import ... although they are used. Usecases why 2 script tags are sometimes necessary are described here.

1 Like

Hey there.

Can you include a more complete reproducer? A section of code that raises the issue specifically.

@Colin sure thing, here you go:

<script lang="ts">
import { computed } from 'vue'
import {
  XCircleIcon,
  ExclamationTriangleIcon,
  CheckCircleIcon,
  InformationCircleIcon,
} from '@heroicons/vue/20/solid'

type MessageType = 'error' | 'warning' | 'success' | 'info'

export type Props = {
  id: string
  type: MessageType
  title: string
}
</script>

<script setup lang="ts">
const props = defineProps<Props>()

defineSlots<{
  default: any
}>()

const classes = computed(() => {
  const c = {
    wrapper: '',
    title: '',
    body: '',
  }

  switch (props.type) {
    case 'error':
      c.wrapper = 'bg-red-50'
      c.title = 'text-red-800'
      c.body = 'text-red-700'
      break
    case 'warning':
      c.wrapper = 'bg-yellow-50'
      c.title = 'text-yellow-800'
      c.body = 'text-yellow-700'
      break
    case 'success':
      c.wrapper = 'bg-green-50'
      c.title = 'text-green-800'
      c.body = 'text-green-700'
      break
    case 'info':
      c.wrapper = 'bg-blue-50'
      c.title = 'text-blue-800'
      c.body = 'text-blue-700'
      break
  }
  return c
})
</script>

<template>
  <div :id="id" class="rounded-md p-4" :class="classes.wrapper">
    <div class="flex">
      <div class="flex-shrink-0">
        <XCircleIcon
          v-if="type === 'error'"
          class="h-5 w-5 text-red-400"
          aria-hidden="true"
        />
        <ExclamationTriangleIcon
          v-if="type === 'warning'"
          class="h-5 w-5 text-yellow-400"
          aria-hidden="true"
        />
        <CheckCircleIcon
          v-if="type === 'success'"
          class="h-5 w-5 text-green-400"
          aria-hidden="true"
        />
        <InformationCircleIcon
          v-if="type === 'info'"
          class="h-5 w-5 text-blue-400"
          aria-hidden="true"
        />
      </div>

      <div class="ml-3">
        <h3 class="text-sm font-medium" :class="classes.title">{{ title }}</h3>
        <div class="mt-2 text-sm" :class="classes.body">
          <slot />
        </div>
      </div>
    </div>
  </div>
</template>

Hi @Colin,

did the above snippet help or do you need further info?

Hey there.

Somebody will be here to take a look at this thread soon. In the meantime, thanks for your patience! Don’t forget you can always mark issues as False-Positive in the SonarCloud UI if, for example, they’re failing your Quality Gate.

Hi Florian,

Thank you very much for the code snippet - it does indeed raise S1128 (unused-import) issues on the component imports. However, I think you are using Vue3 in an undocumented way that probably should be avoided.

Vue3 documentation describes exposed component imports in <script setup> only - <script setup> | Vue.js . This is the configuration our rule supports, so if you move your imports to <script setup> they will be correctly processed by the rule (no S1128 issues).

Moreover, the Vue3 documentation specifically warns about using <script> and <script setup> at the same time:

Support for combining <script setup> and <script> in the same component is limited to the scenarios described above. Specifically:

  • Do NOT use a separate <script> section for options that can already be defined using <script setup>, such as props and emits.
  • Variables created inside <script setup> are not added as properties to the component instance, making them inaccessible from the Options API. Mixing APIs in this way is strongly discouraged.

The docs do not specifically mention your use case (exposing component imports from <script> ) but in my view, it should be avoided as well because this works in <script> only if <script setup> is also present (i.e. it is kind of a side-effect and not the feature that you should rely on).

So the right solution in this particular case IMHO would be to move the component imports into the <script setup> section.

2 Likes

Hi Alexander,

I work with Florian. Thank you for detailed response, you are absolutely right and I did as you suggested.

We are using separate script tag for the export and putting import also in there felt more appropriate, since we always have script tags on top of file (coming from “module imports should be on top” best practise). However in this case, moving imports to the <script setup> seems like correct way, as Vue compiler manages to take them out of setup() automatically.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.