Skip to content

Instantly share code, notes, and snippets.

@nachtmaar
Last active April 13, 2023 12:18
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nachtmaar/9579a3ded4a3f3e14afbc427172f8098 to your computer and use it in GitHub Desktop.
Save nachtmaar/9579a3ded4a3f3e14afbc427172f8098 to your computer and use it in GitHub Desktop.
Debug Flutter Apps in Neovim

How to debug a Dart or Flutter app with vim

I just got the debug integration for Flutter in vim running using vimspector. In order to not forget the config, I decided to quickly compile this readme.

The following manual uses Neovim v0.4.4 and vim-plug plugin manager.

Install

Install vimspector vim plugin by putting it into your neovim config:

~/.config/nvim/init.vim:

Plug 'puremourning/vimspector'

Install it:

nvim +PlugInstall

Install Requirements

brew install node # for running Dart-Code
brew install python3
pip3 install neovim

Dart-Code

Download Dart-Code debug adapter (this brings the debugging capabilities for Dart & Flutter):

git clone https://github.com/Dart-Code/Dart-Code
cd Dart-Code

Now we will build the debug extension. The goal is that the following file out/dist/debug.js is available after the build.

npm run build
file out/dist/debug.js

Configure Dart-Code Debug Gadget

Place this file in your vimspector directory (path might be different for you):

cd ~/.vim/plugged/vimspector

NOTE:

I was not able to install the gadget using install_gadget.py, so I wrote the .gadgets.json file instead directly by following this ticket.

./gadgets/macos/.gadgets.json:

{
  "adapters": {
    "dart-code-flutter-test": {
      "command": [
        "node",
        "${root}/out/dist/debug.js", // check that this file exists, if not go back to Dart-Code section
        "flutter_test"
      ],
      "type": "flutter_test",
      "variables": {
        "root": "/Users/nachtmaar/dev/repos/installed/Dart-Code" // change this
      }
    },
    "dart-code-flutter": {
      "command": [
        "node",
        "${root}/out/dist/debug.js", // check that this file exists, if not go back to Dart-Code 
        "flutter"
      ],
      "type": "flutter",
      "variables": {
        "root": "/Users/nachtmaar/dev/repos/installed/Dart-Code" // change this
      }
    },
    "dart-code-dart": {
      "command": [
        "node",
        "${root}/out/dist/debug.js",  // check that this file exists, if not go back to Dart-Code 
        "dart"
      ],
      "type": "dart",
      "variables": {
        "root": "/Users/nachtmaar/dev/repos/installed/Dart-Code" // change this
      }
    },
    "multi-session": {
      "host": "${host}",
      "port": "${port}"
    }
  }
}

The file contains two adapters. flutter_test is for debugging a flutter test and flutter is for debugging the actual application. You can refer to this in your .vimspector.json.

Vimspector Config

Put this config in your flutter app directory.

Flutter App

For debugging a flutter app use this config:

.vimspector.json:

{
 "configurations": {
   "launch": {
     "adapter": "dart-code-flutter",
     "configuration": {
       "request": "launch",
       "type": "flutter",
       "flutterSdkPath": "/Users/nachtmaar/dev/ext/flutter",
       "dartSdkPath": "/Users/nachtmaar/dev/ext/flutter/bin/cache/dart-sdk/bin/",
       "program": "./lib/main.dart",
       "cwd": "${workspaceRoot}"
     }
   }
 }
}

Flutter Test

For debugging a flutter test use this config:

.vimspector.json:

{
 "configurations": {
   "launch": {
     "adapter": "dart-code-flutter-test",
     "configuration": {
       "request": "launch",
       "type": "flutter_test",
       "flutterSdkPath": "/Users/nachtmaar/dev/ext/flutter",
       "dartSdkPath": "/Users/nachtmaar/dev/ext/flutter/bin/cache/dart-sdk/bin/",
       "program": "test/unit/locale_test.dart",
       "cwd": "${workspaceRoot}"
     }
   }
 }
}

Dart App

For debugging a dart app use this config:

.vimspector.json:

{
 "configurations": {
   "launch": {
     "adapter": "dart-code-dart",
     "configuration": {
       "request": "launch",
       "type": "dart",
       "dartSdkPath": "/Users/nachtmaar/dev/ext/flutter/bin/cache/dart-sdk",
       "program": "./test.dart",
       "cwd": "${workspaceRoot}"
     }
   }
 }
}

Debug It

Now everything is in place. Open the main dart file and start debugging by pressing F5:

vim lib/main.dart

Troubleshooting

If you see this error Request for initialize aborted: Closing down in the debugger, you are proably using the wrong debug.js from Dart-Code. Try to execute the file. You should get an output like this:

$ node "/Users/nachtmaar/dev/repos/installed/Dart-Code/out/dist/debug.js" flutter
(node:58379) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

More tips:

  • Check vimspector log file: ~/.vimspector.log

See all debug subcommands for Dart-Code: $DART_CODE_REPO/out/src/shared/utils/debug.js

Links

All the links I followed while trying to get vimspector running:

Dart-Code

vim-plug

vimspector github

Neovim

Vimspector custom languages wiki

Vimspector Dart Language ticket

@joshpetit
Copy link

Great step by step explanation! Could you also add the fact that you can debug just dart by adding another adapter, something like:

    "dart-code-dart": {
      "command": [
        "node",
        "${root}/out/dist/debug.js",
        "dart"
      ],
      "type": "dart",
      "variables": {
        "root": "/pathto/Dart-Code" 
      }
    }

@nachtmaar
Copy link
Author

@joshpetit, thanks! I will integrate it.

@nachtmaar
Copy link
Author

@joshpetit done. Tested shortly with a dart file.

@joshpetit
Copy link

🥳

@joshpetit
Copy link

Hey, are you able to get hot reloading while debugging? I've been trying to configure that and haven't been able to get it to work

@nachtmaar
Copy link
Author

Good question, did not try it out yet. I will come back to you :)

@joshpetit
Copy link

@nachtmaar looks like it's not possible, see this issue I made. Hopefully one day we can get it to work! Thanks :).

@nachtmaar
Copy link
Author

Thanks for sharing :)

@AdrienLemaire
Copy link

Hi @nachtmaar and thanks for sharing this gist.
Now, when pressing F5, split windows are being opened, but I'm seeing a permanent "Initializing debug adapter..." message on the middle of the screen, and the bottom window shows an error "please specify a device with the '-d ' flag".

This seems to be the output of "flutter run", as if vimspector executed this command, although I have already run it through coc-flutter. I can't figure out how the debug.js script works.

Here's the content of .vimspector.log

2022-10-07 10:24:28,886 - INFO - User requested start debug session with {}
2022-10-07 10:24:28,887 - DEBUG - Reading configurations from: None
2022-10-07 10:24:28,887 - DEBUG - Reading configurations from: /home/dori/Projects/Work/project/.vimspector.json
2022-10-07 10:24:28,888 - DEBUG - Reading gadget config: /home/dori/.vim/plugged/vimspector/gadgets/linux/.gadgets.json
2022-10-07 10:24:28,889 - DEBUG - Reading gadget config: None
2022-10-07 10:24:28,890 - INFO - Configuration: {"adapter": "dart-code-flutter", "configuration": {"request": "launch", "type": "flutter", "flutterSdkPath": "/opt/flutter", "dartSdkPath": "/opt/flutter/bin/cache/dart-sdk/bin", "program": "/home/dori/Projects/Work/project/lib/main.dart", "cwd": "/home/dori/Projects/Work/project"}}
2022-10-07 10:24:28,890 - INFO - Adapter: {"command": ["node", "/home/dori/Projects/3rdpart/flutter/Dart-Code/out/dist/debug.js", "flutter"], "type": "flutter", "variables": {"root": "/home/dori/Projects/3rdpart/flutter/Dart-Code"}}
2022-10-07 10:24:28,892 - DEBUG - min_width/height: 149/50, actual: 213/56 - result: horizontal
2022-10-07 10:24:28,962 - DEBUG - LAUNCH!
2022-10-07 10:24:28,966 - INFO - Starting debug adapter with: {"command": ["node", "/home/dori/Projects/3rdpart/flutter/Dart-Code/out/dist/debug.js", "flutter"], "type": "flutter", "variables": {"root": "/home/dori/Projects/3rdpart/flutter/Dart-Code"}}
2022-10-07 10:24:28,966 - DEBUG - Connection Type: neojob
2022-10-07 10:24:28,968 - INFO - Debug Adapter Started
2022-10-07 10:24:28,968 - DEBUG - Sending Message: {"command": "initialize", "arguments": {"adapterID": "adapter", "clientID": "vimspector", "clientName": "vimspector", "linesStartAt1": true, "columnsStartAt1": true, "locale": "en_GB", "pathFormat": "path", "supportsVariableType": true, "supportsVariablePaging": false, "supportsRunInTerminalRequest": true, "supportsMemoryReferences": true}, "seq": 0, "type": "request"}
2022-10-07 10:24:29,035 - DEBUG - Message received: {'seq': 1, 'type': 'response', 'request_seq': 0, 'command': 'initialize', 'success': True, 'body': {'supportsRestartRequest': True, 'supportsConfigurationDoneRequest': True, 'supportsEvaluateForHovers': True, 'supportsDelayedStackTraceLoading': True, 'supportsConditionalBreakpoints': True, 'supportsLogPoints': True, 'supportsTerminateRequest': True, 'supportsRestartFrame': True, 'supportsClipboardContext': True, 'exceptionBreakpointFilters': [{'filter': 'All', 'label': 'All Exceptions', 'default': False}, {'filter': 'Unhandled', 'label': 'Uncaught Exceptions', 'default': True}]}}
2022-10-07 10:24:29,035 - DEBUG - Sending Message: {"command": "launch", "arguments": {"request": "launch", "type": "flutter", "flutterSdkPath": "/opt/flutter", "dartSdkPath": "/opt/flutter/bin/cache/dart-sdk/bin", "program": "/home/dori/Projects/Work/project/lib/main.dart", "cwd": "/home/dori/Projects/Work/project", "name": "test"}, "seq": 1, "type": "request"}
2022-10-07 10:24:29,037 - DEBUG - Message received: {'seq': 2, 'type': 'event', 'event': 'dart.progressStart', 'body': {'progressId': 'launch', 'message': 'Launching…'}}
2022-10-07 10:24:29,042 - DEBUG - Message received: {'seq': 3, 'type': 'response', 'request_seq': 1, 'command': 'launch', 'success': True}
2022-10-07 10:24:29,044 - DEBUG - Message received: {'seq': 4, 'type': 'event', 'event': 'dart.log', 'body': {'message': 'Spawning /opt/flutter/bin/flutter with args ["run","--machine","--start-paused","--target","lib/main.dart"]', 'severity': 0, 'category': 9}}
2022-10-07 10:24:29,044 - DEBUG - Message received: {'seq': 5, 'type': 'event', 'event': 'dart.log', 'body': {'message': '..  in /home/dori/Projects/Work/project', 'severity': 0, 'category': 9}}
2022-10-07 10:24:29,046 - DEBUG - Message received: {'seq': 6, 'type': 'event', 'event': 'dart.log', 'body': {'message': '    PID: 351477', 'severity': 0, 'category': 9}}
2022-10-07 10:24:29,497 - DEBUG - Message received: {'seq': 7, 'type': 'event', 'event': 'dart.log', 'body': {'message': "<== More than one device connected; please specify a device with the '-d <deviceId>' flag, or use '-d all' to act on all devices.\r\n", 'severity': 0, 'category': 9}}
2022-10-07 10:24:29,499 - DEBUG - Message received: {'seq': 8, 'type': 'event', 'event': 'output', 'body': {'category': 'console', 'output': "More than one device connected; please specify a device with the '-d <deviceId>' flag, or use '-d all' to act on all devices.\n"}}
2022-10-07 10:24:29,529 - DEBUG - Message received: {'seq': 9, 'type': 'event', 'event': 'dart.log', 'body': {'message': '<== Linux (desktop) • linux  • linux-x64      • Arch Linux 5.19.12-arch1-1\r\n', 'severity': 0, 'category': 9}}

My .vimspector.json

{
 "configurations": {
   "launch": {
     "adapter": "dart-code-flutter",
     "configuration": {
       "request": "launch",
       "type": "flutter",
       "flutterSdkPath": "/opt/flutter",
       "dartSdkPath": "/opt/flutter/bin/cache/dart-sdk/bin",
       "program": "${workspaceRoot}/lib/main.dart",
       "cwd": "${workspaceRoot}"
     }
   }
 }
}

Did you get that error too ? How did you resolve it ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment