diff --git a/decoder/body_candidates.go b/decoder/body_candidates.go index d80b37bc..2b844546 100644 --- a/decoder/body_candidates.go +++ b/decoder/body_candidates.go @@ -77,10 +77,7 @@ func (d *Decoder) bodySchemaCandidates(body *hclsyntax.Body, schema *schema.Body candidates.IsComplete = true - // TODO: sort by more metadata, such as IsRequired or IsDeprecated - sort.Slice(candidates.List, func(i, j int) bool { - return candidates.List[i].Label < candidates.List[j].Label - }) + sort.Sort(candidates) return candidates } diff --git a/decoder/label_candidates.go b/decoder/label_candidates.go index 87bd3263..5f56cefb 100644 --- a/decoder/label_candidates.go +++ b/decoder/label_candidates.go @@ -12,25 +12,30 @@ import ( func (d *Decoder) labelCandidatesFromDependentSchema(idx int, db map[schema.SchemaKey]*schema.BodySchema, prefixRng, editRng hcl.Range) (lang.Candidates, error) { candidates := lang.NewCandidates() + candidates.IsComplete = true count := 0 foundCandidateNames := make(map[string]bool, 0) prefix, _ := d.bytesFromRange(prefixRng) - for schemaKey, bodySchema := range db { + for _, schemaKey := range sortedSchemaKeys(db) { depKeys, err := decodeSchemaKey(schemaKey) if err != nil { // key undecodable continue } + if uint(count) >= d.maxCandidates { + // reached maximum no of candidates + candidates.IsComplete = false + break + } + + bodySchema := db[schemaKey] + for _, label := range depKeys.Labels { if label.Index == idx { - if uint(count) >= d.maxCandidates { - // reached maximum no of candidates - return candidates, nil - } if len(prefix) > 0 && !strings.HasPrefix(label.Value, string(prefix)) { continue } @@ -71,16 +76,22 @@ func (d *Decoder) labelCandidatesFromDependentSchema(idx int, db map[schema.Sche } } - candidates.IsComplete = true - - // TODO: sort by more metadata, such as IsDeprecated - sort.Slice(candidates.List, func(i, j int) bool { - return candidates.List[i].Label < candidates.List[j].Label - }) + sort.Sort(candidates) return candidates, nil } +func sortedSchemaKeys(m map[schema.SchemaKey]*schema.BodySchema) []schema.SchemaKey { + keys := make([]schema.SchemaKey, 0) + for k := range m { + keys = append(keys, k) + } + sort.SliceStable(keys, func(i, j int) bool { + return string(keys[i]) < string(keys[j]) + }) + return keys +} + func decodeSchemaKey(key schema.SchemaKey) (schema.DependencyKeys, error) { var dk schema.DependencyKeys err := json.Unmarshal([]byte(key), &dk) diff --git a/lang/candidate.go b/lang/candidate.go index 7afc33ae..fe56e82b 100644 --- a/lang/candidate.go +++ b/lang/candidate.go @@ -67,6 +67,19 @@ type Candidates struct { IsComplete bool } +func (ca Candidates) Len() int { + return len(ca.List) +} + +func (ca Candidates) Less(i, j int) bool { + // TODO: sort by more metadata, such as IsRequired or IsDeprecated + return ca.List[i].Label < ca.List[j].Label +} + +func (ca Candidates) Swap(i, j int) { + ca.List[i], ca.List[j] = ca.List[j], ca.List[i] +} + // NewCandidates creates a new (incomplete) list of candidates // to be appended to. func NewCandidates() Candidates {