Skip to content

Commit 33e214a

Browse files
committed
feat: use Related metadata for autocomplete API discovery
1 parent 76df16c commit 33e214a

1 file changed

Lines changed: 69 additions & 16 deletions

File tree

cli/completer.go

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -214,29 +214,33 @@ func findAutocompleteAPI(arg *config.APIArg, apiFound *config.API, apiMap map[st
214214
}
215215

216216
var autocompleteAPI *config.API
217+
217218
argName := strings.Replace(arg.Name, "=", "", -1)
218-
relatedNoun := argName
219+
220+
// Build the noun we expect from the existing heuristic rules.
221+
expectedNoun := argName
219222
switch {
220223
case argName == "id" || argName == "ids":
221-
// Heuristic: user is trying to autocomplete for id/ids arg for a list API
222-
relatedNoun = apiFound.Noun
224+
expectedNoun = apiFound.Noun
223225
if apiFound.Verb != "list" {
224-
relatedNoun += "s"
226+
expectedNoun += "s"
225227
}
228+
226229
case argName == "account":
227-
// Heuristic: user is trying to autocomplete for accounts
228-
relatedNoun = "accounts"
230+
expectedNoun = "accounts"
231+
229232
case argName == "ipaddressid":
230-
// Heuristic: user is trying to autocomplete for ip addresses
231-
relatedNoun = "publicipaddresses"
233+
expectedNoun = "publicipaddresses"
234+
232235
case argName == "storageid":
233-
relatedNoun = "storagepools"
236+
expectedNoun = "storagepools"
237+
234238
case argName == "associatednetworkid":
235-
relatedNoun = "networks"
239+
expectedNoun = "networks"
240+
236241
default:
237-
// Heuristic: autocomplete for the arg for which a list<Arg without id/ids>s API exists
238-
// For example, for zoneid arg, listZones API exists
239242
base := argName
243+
240244
if strings.HasSuffix(argName, "id") {
241245
base = strings.TrimSuffix(argName, "id")
242246
} else if strings.HasSuffix(argName, "ids") {
@@ -249,15 +253,61 @@ func findAutocompleteAPI(arg *config.APIArg, apiFound *config.API, apiMap map[st
249253
}
250254
}
251255
}
252-
// Handle common cases where base ends with a vowel and needs "es"
253-
if strings.HasSuffix(base, "s") || strings.HasSuffix(base, "x") || strings.HasSuffix(base, "z") || strings.HasSuffix(base, "ch") || strings.HasSuffix(base, "sh") {
254-
relatedNoun = base + "es"
256+
257+
if strings.HasSuffix(base, "s") ||
258+
strings.HasSuffix(base, "x") ||
259+
strings.HasSuffix(base, "z") ||
260+
strings.HasSuffix(base, "ch") ||
261+
strings.HasSuffix(base, "sh") {
262+
expectedNoun = base + "es"
255263
} else {
256-
relatedNoun = base + "s"
264+
expectedNoun = base + "s"
265+
}
266+
}
267+
268+
// FIRST: prefer Related APIs whose noun matches the expected noun.
269+
for _, relatedAPI := range arg.Related {
270+
if !strings.HasPrefix(strings.ToLower(relatedAPI), "list") {
271+
continue
272+
}
273+
274+
for _, listAPI := range apiMap["list"] {
275+
if strings.EqualFold(listAPI.Name, relatedAPI) &&
276+
strings.EqualFold(listAPI.Noun, expectedNoun) {
277+
278+
config.Debug(
279+
"Autocomplete: API found using Related metadata: ",
280+
listAPI.Name,
281+
)
282+
283+
return listAPI
284+
}
285+
}
286+
}
287+
288+
// SECOND: fallback to any list API from Related.
289+
for _, relatedAPI := range arg.Related {
290+
if !strings.HasPrefix(strings.ToLower(relatedAPI), "list") {
291+
continue
292+
}
293+
294+
for _, listAPI := range apiMap["list"] {
295+
if strings.EqualFold(listAPI.Name, relatedAPI) {
296+
297+
config.Debug(
298+
"Autocomplete: API found using Related metadata fallback: ",
299+
listAPI.Name,
300+
)
301+
302+
return listAPI
303+
}
257304
}
258305
}
259306

307+
relatedNoun := expectedNoun
308+
260309
config.Debug("Possible related noun for the arg: ", relatedNoun, " and type: ", arg.Type)
310+
261311
autocompleteAPI = findAPI(apiMap, relatedNoun)
262312

263313
if autocompleteAPI == nil {
@@ -278,13 +328,16 @@ func findAutocompleteAPI(arg *config.APIArg, apiFound *config.API, apiMap map[st
278328
// Heuristic: find any list API that contains the arg name
279329
if autocompleteAPI == nil {
280330
config.Debug("Finding possible API that have: ", argName, " related APIs: ", arg.Related)
331+
281332
possibleAPIs := []*config.API{}
333+
282334
for _, listAPI := range apiMap["list"] {
283335
if strings.Contains(listAPI.Noun, argName) {
284336
config.Debug("Found possible API: ", listAPI.Name)
285337
possibleAPIs = append(possibleAPIs, listAPI)
286338
}
287339
}
340+
288341
if len(possibleAPIs) == 1 {
289342
autocompleteAPI = possibleAPIs[0]
290343
}

0 commit comments

Comments
 (0)