Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: respect cwd when detecting is it flutter project, handle running dart-only projects #384

Merged
merged 1 commit into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading