Windows上のVSCodeでのD言語のdebug表示


  • 20191210 dmdを改造する例を追記

Windows上の vscode で D言語をデバッグするとこんな感じで、

変数の表示が見やすくありません。
文字列がスライスで \0 で終端していなかったりもします。
(c++用のデバッガ cppvsdbg なのでそりゃそう)

vcnatvis でカスタマイズできないか試してみた。

実験コード

string は natvis できた

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "with natvis",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/d_natvis.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "visualizerFile": "${workspaceFolder}/d.natvis" // これ
        }
    ]
}
d.natvis
<?xml version="1.0" encoding="utf-8" ?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
    <Type Name="string"><!-- この Name が型名とマッチして表示される -->
        <DisplayString>"{ptr,[length]s8b}"</DisplayString>
        <StringView>ptr,length</StringView>
        <Expand>
            <Item Name="[size]">length</Item>
            <ArrayItems>
                <Size>length</Size>
                <ValuePointer>ptr</ValuePointer>
            </ArrayItems>
        </Expand>
    </Type>
</AutoVisualizer>

sliceはできなかったが

alias string = immutable(char)[] なのでスライスもできないかと思って試したのだけどできなかった。

auto array = [1, 2, 3];

などは、

<Type Name="int[]">

になっているらしく、 natvis 的には型名として不適合でマッチさせることができないらしい。

妥協してstructに代入してみる

自前のstructはnatvisをマッチさせることができたので以下のようなヘルパーを書いてみた。

struct SliceView(T)
{
    T* ptr;
    ulong size;

    this(T[] src)
    {
        ptr = src.ptr;
        size = src.length;
    }
}

SliceView!T makeView(T)(T[] slice)
{
    return SliceView!T(slice);
}
d.natvis
    <Type Name="app.SliceView">
        <DisplayString>{{size = {size}}}</DisplayString>
        <Expand>
            <Item Name="[size]">size</Item>
            <ArrayItems>
                <Size>size</Size>
                <ValuePointer>ptr</ValuePointer>
            </ArrayItems>
        </Expand>
    </Type>

デバッグプリントするよりはいいんでないか。

DMDを改造したらarrayをデバッグ表示できるようになった

の記事の通りにやるだけ。
話が立ち消えになっているような気がするが、
pull request 出さなかったんだろうか。
もったいない。

clone する

コードを修正する

src/dmd/hdrgen.d
    void visitDArray(TypeDArray t)
    {
        Type ut = t.castMod(0);
        if (hgs.declstring)
            goto L1;
        if (ut.equals(Type.tstring))
            buf.writestring("string");
        else if (ut.equals(Type.twstring))
            buf.writestring("wstring");
        else if (ut.equals(Type.tdstring))
            buf.writestring("dstring");
        else
        {
        L1:
            buf.writestring("__dlang::__darray<"); // ここから
            visitWithMask(t.next, t.mod, buf, hgs);
            //buf.writestring("[]");
            buf.writestring(">"); // ここまで。
        }
    }

T[] から __dlang::__darray<T> という C++ で合法的な名前に変えてあげるのがよいらしい。

Tconst(char) とかになり得るみたいなので、もう少し改造が要るかもしれない(Natvisが丸かっこを許すかよくわからない)。

build する

src\vcbuild\dmd.sln

を開いてビルドするだけ。
コンパイラなのですごい時間かかるかと思いきや、わりとすぐに終わる。

exe を dub から呼べるようにする。

ビルドされた

generated\windows\release\64\dmd.exe

をPATHを通すなり、

C:\D\dmd2\windows\bin\dmd.exe

にコピーするなり(元のファイルはバックアップ)する。

natvis

改造版のarrayにマッチするnatvis
    <Type Name="__dlang::__darray&lt;*&gt;">
        <DisplayString>{{size = {length}}}</DisplayString>
        <Expand>
            <Item Name="[size]">length</Item>
            <ArrayItems>
                <Size>length</Size>
                <ValuePointer>ptr</ValuePointer>
            </ArrayItems>
        </Expand>
    </Type>

試しに使ってみた

gltf.meshes[0].primitives[0] のようにネストしたコレクションの中にずんずん潜っていけてデバッグしやすい。
DMDの自前ビルドは簡単なので、WindowsでDするときはやってみるとよいかも。