Skip to content

Commit

Permalink
feat: respect cwd when detecting is it flutter project, handle runnin…
Browse files Browse the repository at this point in the history
…g dart-only projects (#384)

Fixes #375
  • Loading branch information
sidlatau committed Aug 29, 2024
1 parent 99af517 commit cde6625
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 78 deletions.
26 changes: 23 additions & 3 deletions lua/flutter-tools/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local dev_tools = lazy.require("flutter-tools.dev_tools") ---@module "flutter-
local lsp = lazy.require("flutter-tools.lsp") ---@module "flutter-tools.lsp"
local job_runner = lazy.require("flutter-tools.runners.job_runner") ---@module "flutter-tools.runners.job_runner"
local debugger_runner = lazy.require("flutter-tools.runners.debugger_runner") ---@module "flutter-tools.runners.debugger_runner"
local path = lazy.require("flutter-tools.utils.path") ---@module "flutter-tools.utils.path"
local dev_log = lazy.require("flutter-tools.log") ---@module "flutter-tools.log"

local M = {}
Expand All @@ -20,7 +21,7 @@ local current_device = nil

---@class flutter.Runner
---@field is_running fun(runner: flutter.Runner):boolean
---@field run fun(runner: flutter.Runner, paths:table, args:table, cwd:string, on_run_data:fun(is_err:boolean, data:string), on_run_exit:fun(data:string[], args: table))
---@field run fun(runner: flutter.Runner, paths:table, args:table, cwd:string, on_run_data:fun(is_err:boolean, data:string), on_run_exit:fun(data:string[], args: table), is_flutter_project: boolean, project_conf: flutter.ProjectConfig?)
---@field cleanup fun(funner: flutter.Runner)
---@field send fun(runner: flutter.Runner, cmd:string, quiet: boolean?)

Expand Down Expand Up @@ -195,6 +196,17 @@ local function get_cwd(project_conf)
return lsp.get_lsp_root_dir()
end

---@param cwd string
local function has_flutter_dependency_in_pubspec(cwd)
local pubspec = vim.fn.glob(path.join(cwd, "pubspec.yaml"))
if pubspec == "" then return false end
local pubspec_content = vim.fn.readfile(pubspec)
local joined_content = table.concat(pubspec_content, "\n")

local flutter_dependency = string.match(joined_content, "flutter:\n[%s\t]*sdk:[%s\t]*flutter")
return flutter_dependency ~= nil
end

---@param opts RunOpts
---@param project_conf flutter.ProjectConfig?
local function run(opts, project_conf)
Expand All @@ -203,7 +215,6 @@ local function run(opts, project_conf)
local args = opts.cli_args or get_run_args(opts, project_conf)

current_device = opts.device or get_device_from_args(args)
ui.notify("Starting flutter project...")
if project_conf then
if project_conf.pre_run_callback then
local callback_args = {
Expand All @@ -215,8 +226,17 @@ local function run(opts, project_conf)
project_conf.pre_run_callback(callback_args)
end
end
local cwd = get_cwd(project_conf)
-- To determinate if the project is a flutter project we need to check if the pubspec.yaml
-- file has a flutter dependency in it. We need to get cwd first to pick correct pubspec.yaml file.
local is_flutter_project = has_flutter_dependency_in_pubspec(cwd)
if is_flutter_project then
ui.notify("Starting flutter project...")
else
ui.notify("Starting dart project...")
end
runner = use_debugger_runner() and debugger_runner or job_runner
runner:run(paths, args, get_cwd(project_conf), on_run_data, on_run_exit)
runner:run(paths, args, cwd, on_run_data, on_run_exit, is_flutter_project, project_conf)
end)
end

Expand Down
21 changes: 1 addition & 20 deletions lua/flutter-tools/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -84,26 +84,7 @@ local config = {
enabled = false,
exception_breakpoints = nil,
evaluate_to_string_in_debug_views = true,
register_configurations = function(paths)
require("dap").configurations.dart = {
{
type = "dart",
request = "launch",
name = "Launch flutter",
dartSdkPath = paths.dart_sdk,
flutterSdkPath = paths.flutter_sdk,
program = "${workspaceFolder}/lib/main.dart",
},
{
type = "dart",
request = "attach",
name = "Connect flutter",
dartSdkPath = paths.dart_sdk,
flutterSdkPath = paths.flutter_sdk,
program = "${workspaceFolder}/lib/main.dart",
},
}
end,
register_configurations = nil,
},
closing_tags = {
highlight = "Comment",
Expand Down
51 changes: 1 addition & 50 deletions lua/flutter-tools/dap.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
local lazy = require("flutter-tools.lazy")
local path = lazy.require("flutter-tools.utils.path") ---@module "flutter-tools.utils.path"
local ui = lazy.require("flutter-tools.ui") ---@module "flutter-tools.ui"

local success, dap = pcall(require, "dap")
Expand All @@ -10,57 +9,9 @@ end

local M = {}

local function has_flutter_dependency_in_pubspec()
local pubspec = vim.fn.glob("pubspec.yaml")
if pubspec == "" then return false end
local pubspec_content = vim.fn.readfile(pubspec)
local joined_content = table.concat(pubspec_content, "\n")

local flutter_dependency = string.match(joined_content, "flutter:\n[%s\t]*sdk:[%s\t]*flutter")
return flutter_dependency ~= nil
end

function M.setup(config)
local opts = config.debugger
require("flutter-tools.executable").get(function(paths)
local is_flutter_project = has_flutter_dependency_in_pubspec()

if is_flutter_project then
dap.adapters.dart = {
type = "executable",
command = paths.flutter_bin,
args = { "debug-adapter" },
}
if path.is_windows then
-- https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation#dart
-- add this if on windows, otherwise server won't open successfully
dap.adapters.dart.options = {
detached = false,
}
end
local repl = require("dap.repl")
repl.commands = vim.tbl_extend("force", repl.commands, {
custom_commands = {
[".hot-reload"] = function() dap.session():request("hotReload") end,
[".hot-restart"] = function() dap.session():request("hotRestart") end,
},
})
else
dap.adapters.dart = {
type = "executable",
command = paths.dart_bin,
args = { "debug_adapter" },
}
dap.configurations.dart = {
{
type = "dart",
request = "launch",
name = "Launch Dart",
dartSdkPath = paths.dart_sdk,
program = "${workspaceFolder}/bin/main.dart",
},
}
end
require("flutter-tools.executable").get(function(_)
if opts.exception_breakpoints and type(opts.exception_breakpoints) == "table" then
dap.defaults.dart.exception_breakpoints = opts.exception_breakpoints
end
Expand Down
95 changes: 93 additions & 2 deletions lua/flutter-tools/runners/debugger_runner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local ui = lazy.require("flutter-tools.ui") ---@module "flutter-tools.ui"
local dev_tools = lazy.require("flutter-tools.dev_tools") ---@module "flutter-tools.dev_tools"
local config = lazy.require("flutter-tools.config") ---@module "flutter-tools.config"
local utils = lazy.require("flutter-tools.utils") ---@module "flutter-tools.utils"
local path = lazy.require("flutter-tools.utils.path") ---@module "flutter-tools.utils.path"
local vm_service_extensions = lazy.require("flutter-tools.runners.vm_service_extensions") ---@module "flutter-tools.runners.vm_service_extensions"
local _, dap = pcall(require, "dap")

Expand All @@ -23,7 +24,95 @@ local command_requests = {

function DebuggerRunner:is_running() return dap.session() ~= nil end

function DebuggerRunner:run(paths, args, cwd, on_run_data, on_run_exit)
---@param paths table<string, string>
---@param is_flutter_project boolean
local function register_debug_adapter(paths, is_flutter_project)
if is_flutter_project then
dap.adapters.dart = {
type = "executable",
command = paths.flutter_bin,
args = { "debug-adapter" },
}
if path.is_windows then
-- https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation#dart
-- add this if on windows, otherwise server won't open successfully
dap.adapters.dart.options = {
detached = false,
}
end
local repl = require("dap.repl")
repl.commands = vim.tbl_extend("force", repl.commands, {
custom_commands = {
[".hot-reload"] = function() dap.session():request("hotReload") end,
[".hot-restart"] = function() dap.session():request("hotRestart") end,
},
})
else
dap.adapters.dart = {
type = "executable",
command = paths.dart_bin,
args = { "debug_adapter" },
}
end
end

---@param paths table<string, string>
---@param is_flutter_project boolean
---@param project_config flutter.ProjectConfig?
local function register_default_configurations(paths, is_flutter_project, project_config)
local program
if is_flutter_project then
if project_config and project_config.target then
program = project_config.target
else
program = "lib/main.dart"
end
require("dap").configurations.dart = {
{
type = "dart",
request = "launch",
name = "Launch flutter",
dartSdkPath = paths.dart_sdk,
flutterSdkPath = paths.flutter_sdk,
program = program,
},
{
type = "dart",
request = "attach",
name = "Connect flutter",
dartSdkPath = paths.dart_sdk,
flutterSdkPath = paths.flutter_sdk,
program = program,
},
}
else
if project_config and project_config.target then
program = project_config.target
else
local root_dir_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":t")
program = path.join("bin", root_dir_name .. ".dart")
end
require("dap").configurations.dart = {
{
type = "dart",
request = "launch",
name = "Launch dart",
dartSdkPath = paths.dart_sdk,
program = program,
},
}
end
end

function DebuggerRunner:run(
paths,
args,
cwd,
on_run_data,
on_run_exit,
is_flutter_project,
project_config
)
local started = false
local before_start_logs = {}
vm_service_extensions.reset()
Expand Down Expand Up @@ -68,9 +157,11 @@ function DebuggerRunner:run(paths, args, cwd, on_run_data, on_run_exit)
end
end

register_debug_adapter(paths, is_flutter_project)
local launch_configurations = {}
local launch_configuration_count = 0
config.debugger.register_configurations(paths)
register_default_configurations(paths, is_flutter_project, project_config)
if config.debugger.register_configurations then config.debugger.register_configurations(paths) end
local all_configurations = require("dap").configurations.dart
if not all_configurations then
ui.notify("No launch configuration for DAP found", ui.ERROR)
Expand Down
25 changes: 22 additions & 3 deletions lua/flutter-tools/runners/job_runner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,29 @@ local command_keys = {

function JobRunner:is_running() return run_job ~= nil end

function JobRunner:run(paths, args, cwd, on_run_data, on_run_exit)
function JobRunner:run(
paths,
args,
cwd,
on_run_data,
on_run_exit,
is_flutter_project,
project_config
)
local command, command_args
if is_flutter_project then
command = paths.flutter_bin
command_args = args
else
command = paths.dart_bin
command_args = { "run" } ---@type string[]
if project_config and project_config.target then
table.insert(command_args, project_config.target)
end
end
run_job = Job:new({
command = paths.flutter_bin,
args = args,
command = command,
args = command_args,
cwd = cwd,
on_start = function() utils.emit_event(utils.events.APP_STARTED) end,
on_stdout = vim.schedule_wrap(function(_, data, _)
Expand Down

0 comments on commit cde6625

Please sign in to comment.