@ledsun blog

Hのキーがhellで、Sのキーがslaveだ、と彼は思った。そしてYのキーがyouだ。

JSDocでVSCodeにヒントを与えてGo To Definition

JavaScriptでプログラミングをしていて、ある程度規模が大きくなると、扱っている変数にはいるオブジェクトがどんなメソッドやプロパティをもっているのかを、静的に(プログラムを動かさずに)知りたくなります。

すわTypeScriptとなるところですが

  • すでに組んでいるツールチェーンにTypeScriptのトランスパイルを追加したくない(できれば薄くしていきたい)
  • (性格的に)型をつけるために工夫することが楽しくなってきて、夢中になっちゃう

ので、もう少し軽量な方法が欲しいなあと思っていました。

JSDocの@typeでクラス名を書くとVSCodeがそれをヒントに定義を見つけてくれることを知りました。

ipmort文があって、型を定義するファイルが特定されている場合

ややこしいクラスのオブジェクトが入っている変数に/** @type {DefinedTypeContainer} */のようなJSDoc形式のコメントを書きます。

import getUrlMatches from '../../getUrlMatches'
import formatForPallet from './formatForPallet'
import DefinedTypeContainer from './DefinedTypeContainer'
import sortByCountAndName from './sortByCountAndName'
import countUsage from './countUsage'

export default class DefinitionContainer {
  constructor(eventEmitter, annotationType, getAllInstanceFunc, defaultColor) {
    this._eventEmitter = eventEmitter
    this._annotationType = annotationType
    /** @type {DefinedTypeContainer} */
    this._definedTypes = null
    this._getAllInstanceFunc = getAllInstanceFunc
    this._defaultColor = defaultColor
  }

すると、次のようにVSCodeは_definedTypesプロパティの型を認識するようになります。

f:id:ledsun:20211223072152p:plain
VSCodeが_definedTypesプロパティの型をDefinedTypeContainerクラスと認識してるところ

すると、_defindeTypes.mapの定義を表示できるようになります。

f:id:ledsun:20211223072437p:plain
VSCodeが_definedTypes.mapの定義をポップアップしているところ

これが欲しかったのです。

import文がないとき

ところが、import文でコメントで指示したクラスを読み込んでいないとときは上手く行きません。

import delegate from 'delegate'
import Pallet from '../Pallet'
import bindAttributeEvent from './bindAttributeEvent'
import createContentHtml from './createContentHtml'
import enableDrag from './enableDrag'

export default class TypeValuesPallet extends Pallet {
  constructor(
    editorHTMLElement,
    eventEmitter,
    annotationData,
    definitionContainer,
    selectionModelEntity,
    commander,
    title,
    buttonController
  ) {
    super(editorHTMLElement, title)

    this._eventEmitter = eventEmitter
    /** @type AnnotationData */
    this._annotationData = annotationData
    this._definitionContainer = definitionContainer
    this._selectionModelItems = selectionModelEntity
    this._buttonController = buttonController

と書くと、型は認識ます。

f:id:ledsun:20211223072921p:plain
AnnotatioDataクラスを認識している

しかし、この状態ではVSCodeはAnnotationDataの定義を見つけられません。 名前空間もクラスローダーもないプログラミング言語で、「型名だけで定義ファイルをみつけろ」が無茶なのはわかります。 でも、見つけて欲しいんです。

ここでコメントを

/** @type {import('../../editorize/AnnotationData').default} */

と、import文風に書きます。

f:id:ledsun:20211223073352p:plain
VSCodeがAnnotationDataの定義を表示しているところ

すごい!VSCode便利!! しかも、VSCode上でファイル名を変更すると、コメント中のファイル名も直してくれます。 すごい!VSCode便利!!!

参考