@@ -5,6 +5,29 @@ local ui = lazy.require("flutter-tools.ui") ---@module "flutter-tools.ui"
55local config = lazy .require (" flutter-tools.config" ) --- @module " flutter-tools.config"
66local Job = require (" plenary.job" )
77
8+ --- @class flutter.Paths
9+ ---
10+ --- The path to the Flutter CLI.
11+ --- @field flutter_bin string
12+ ---
13+ --- The path to the root directory of the Flutter SDK.
14+ --- @field flutter_sdk string
15+ ---
16+ --- The path to the Dart CLI.
17+ --- @field dart_bin string
18+ ---
19+ --- The path to the root directory of the Dart SDK used by the Flutter SDK.
20+ --- @field dart_sdk string
21+ ---
22+ --- True if fvm provides the Flutter SDK, otherwise nil or false.
23+ --- @field fvm boolean ?
24+
25+ --- @private
26+ --- @class flutter.internal.Paths
27+ --- @field flutter_bin string
28+ --- @field flutter_sdk string
29+ --- @field dart_bin string
30+
831local fn = vim .fn
932local fs = vim .fs
1033local luv = vim .loop
@@ -13,12 +36,15 @@ local M = {}
1336
1437local dart_sdk = path .join (" cache" , " dart-sdk" )
1538
16- local function _flutter_sdk_root (bin_path )
39+ --- @type flutter.Paths ?
40+ local cached_paths = nil
41+
42+ local function flutter_sdk_root (bin_path )
1743 -- convert path/to/flutter/bin/flutter into path/to/flutter
1844 return fn .fnamemodify (bin_path , " :h:h" )
1945end
2046
21- local function _dart_sdk_root (paths )
47+ local function dart_sdk_root (paths )
2248 if paths .flutter_sdk then
2349 -- On Linux installations with snap the dart SDK can be further nested inside a bin directory
2450 -- so it's /bin/cache/dart-sdk whereas else where it is /cache/dart-sdk
@@ -42,131 +68,148 @@ local function _dart_sdk_root(paths)
4268 return " "
4369end
4470
45- local function _flutter_sdk_dart_bin (flutter_sdk )
71+ local function flutter_sdk_dart_bin (flutter_sdk )
4672 -- retrieve the Dart binary from the Flutter SDK
4773 local binary_name = path .is_windows and " dart.bat" or " dart"
4874 return path .join (flutter_sdk , " bin" , binary_name )
4975end
5076
51- --- Get paths for flutter and dart based on the binary locations
52- --- @return table<string , string> ?
77+ --- Get paths for flutter and dart based on the binary locations.
78+ --- @return flutter.internal.Paths ?
5379local function get_default_binaries ()
5480 local flutter_bin = fn .resolve (fn .exepath (" flutter" ))
5581 if # flutter_bin <= 0 then return nil end
5682 return {
5783 flutter_bin = flutter_bin ,
5884 dart_bin = fn .resolve (fn .exepath (" dart" )),
59- flutter_sdk = _flutter_sdk_root (flutter_bin ),
85+ flutter_sdk = flutter_sdk_root (flutter_bin ),
6086 }
6187end
6288
63- --- @type table<string , string>
64- local _paths = nil
65-
66- function M .reset_paths () _paths = nil end
67-
68- --- Execute user's lookup command and pass it to the job callback
89+ --- Execute user's lookup command and pass it to the job callback.
6990--- @param lookup_cmd string
70- --- @param callback fun ( t ?: table<string , string> ?)
71- --- @return table<string , string> ?
91+ --- @param callback fun ( paths : flutter.internal.Paths ): nil
7292local function path_from_lookup_cmd (lookup_cmd , callback )
7393 local paths = {}
7494 local parts = vim .split (lookup_cmd , " " )
7595 local cmd = parts [1 ]
7696 local args = vim .list_slice (parts , 2 , # parts )
7797
7898 local job = Job :new ({ command = cmd , args = args })
99+
79100 job :after_failure (
80101 vim .schedule_wrap (
81102 function ()
82103 ui .notify (string.format (" Error running %s" , lookup_cmd ), ui .ERROR , { timeout = 5000 })
83104 end
84105 )
85106 )
107+
86108 job :after_success (vim .schedule_wrap (function (j , _ )
87109 local result = j :result ()
88110 local flutter_sdk_path = result [1 ]
89111 if flutter_sdk_path then
90- paths .dart_bin = _flutter_sdk_dart_bin (flutter_sdk_path )
112+ paths .dart_bin = flutter_sdk_dart_bin (flutter_sdk_path )
91113 paths .flutter_bin = path .join (flutter_sdk_path , " bin" , " flutter" )
92114 paths .flutter_sdk = flutter_sdk_path
93115 callback (paths )
94116 else
95117 paths = get_default_binaries ()
96118 callback (paths )
97119 end
98- return paths
99120 end ))
121+
100122 job :start ()
101123end
102124
103- local function _flutter_bin_from_fvm ()
125+ local function flutter_bin_from_fvm ()
104126 local fvm_root =
105127 fs .dirname (fs .find (" .fvm" , { path = luv .cwd (), upward = true , type = " directory" })[1 ])
128+
106129 local binary_name = path .is_windows and " flutter.bat" or " flutter"
107130 local flutter_bin_symlink = path .join (fvm_root , " .fvm" , " flutter_sdk" , " bin" , binary_name )
108131 flutter_bin_symlink = fn .exepath (flutter_bin_symlink )
132+
109133 local flutter_bin = luv .fs_realpath (flutter_bin_symlink )
110134 if path .exists (flutter_bin_symlink ) and path .exists (flutter_bin ) then return flutter_bin end
111135end
112136
113- --- Fetch the paths to the users binaries.
114- --- @param callback fun ( paths ?: table<string , string> )
115- --- @return nil
137+ --- Reset the internally cached SDK paths.
138+ function M .reset_paths () cached_paths = nil end
139+
140+ --- Fetch the paths to the users binaries.
141+ --- @param callback fun ( paths : flutter.Paths ): nil
116142function M .get (callback )
117- if _paths then return callback (_paths ) end
143+ if cached_paths then return callback (cached_paths ) end
118144 if config .fvm then
119- local flutter_bin = _flutter_bin_from_fvm ()
145+ local flutter_bin = flutter_bin_from_fvm ()
120146 if flutter_bin then
121- _paths = {
147+ cached_paths = {
122148 flutter_bin = flutter_bin ,
123- flutter_sdk = _flutter_sdk_root (flutter_bin ),
149+ flutter_sdk = flutter_sdk_root (flutter_bin ),
124150 fvm = true ,
151+ -- Provide default values to make the linter happy.
152+ dart_sdk = " " ,
153+ dart_bin = " " ,
125154 }
126- _paths .dart_sdk = _dart_sdk_root ( _paths )
127- _paths .dart_bin = _flutter_sdk_dart_bin ( _paths .flutter_sdk )
128- return callback (_paths )
155+ cached_paths .dart_sdk = dart_sdk_root ( cached_paths )
156+ cached_paths .dart_bin = flutter_sdk_dart_bin ( cached_paths .flutter_sdk )
157+ return callback (cached_paths )
129158 end
130159 end
131160
132161 if config .flutter_path then
133162 local flutter_path = fn .resolve (config .flutter_path )
134- _paths = { flutter_bin = flutter_path , flutter_sdk = _flutter_sdk_root (flutter_path ) }
135- _paths .dart_sdk = _dart_sdk_root (_paths )
136- _paths .dart_bin = _flutter_sdk_dart_bin (_paths .flutter_sdk )
137- return callback (_paths )
163+ cached_paths = {
164+ flutter_bin = flutter_path ,
165+ flutter_sdk = flutter_sdk_root (flutter_path ),
166+ -- Provide default values to make the linter happy.
167+ dart_sdk = " " ,
168+ dart_bin = " " ,
169+ }
170+ cached_paths .dart_sdk = dart_sdk_root (cached_paths )
171+ cached_paths .dart_bin = flutter_sdk_dart_bin (cached_paths .flutter_sdk )
172+ return callback (cached_paths )
138173 end
139174
140175 if config .flutter_lookup_cmd then
141176 return path_from_lookup_cmd (config .flutter_lookup_cmd , function (paths )
142- if not paths then return end
143- _paths = paths
144- _paths .dart_sdk = _dart_sdk_root (_paths )
145- callback (_paths )
177+ paths = {
178+ flutter_bin = paths .flutter_bin ,
179+ flutter_sdk = paths .flutter_sdk ,
180+ dart_bin = paths .dart_bin ,
181+ dart_sdk = dart_sdk_root (paths ),
182+ }
183+ callback (paths )
146184 end )
147185 end
148186
149- local default_paths = get_default_binaries ()
150-
151- if not _paths and default_paths then
152- _paths = default_paths
153- _paths .dart_sdk = _dart_sdk_root (_paths )
154- if _paths .flutter_sdk then _paths .dart_bin = _flutter_sdk_dart_bin (_paths .flutter_sdk ) end
187+ if not cached_paths then
188+ local internal_paths = get_default_binaries ()
189+ if internal_paths then
190+ cached_paths = {
191+ flutter_bin = internal_paths .flutter_bin ,
192+ flutter_sdk = internal_paths .flutter_sdk ,
193+ dart_bin = internal_paths .dart_bin ,
194+ dart_sdk = dart_sdk_root (internal_paths ),
195+ }
196+ if cached_paths .flutter_sdk then
197+ cached_paths .dart_bin = flutter_sdk_dart_bin (cached_paths .flutter_sdk )
198+ end
199+ end
155200 end
156201
157- return callback (_paths )
202+ return callback (cached_paths )
158203end
159204
160- --- Fetch the path to the users flutter installation.
161- --- @param callback fun ( paths : string )
162- --- @return nil
205+ --- Fetch the path to the users flutter installation.
206+ --- @param callback fun ( flutter_bin : string ): nil
163207function M .flutter (callback )
164208 M .get (function (paths ) callback (paths .flutter_bin ) end )
165209end
166210
167- --- Fetch the path to the users dart installation.
168- --- @param callback fun ( paths : table<string , string> )
169- --- @return nil
211+ --- Fetch the path to the users dart installation.
212+ --- @param callback fun ( dart_bin : string ): nil
170213function M .dart (callback )
171214 M .get (function (paths ) callback (paths .dart_bin ) end )
172215end
0 commit comments