func CandidatesAtPos()

in internal/langserver/handlers/complete/complete.go [18:82]


func CandidatesAtPos(data []byte, filename string, pos hcl.Pos, logger *log.Logger) []lsp.CompletionItem {
	file, _ := hclsyntax.ParseConfig(data, filename, hcl.InitialPos)

	body, isHcl := file.Body.(*hclsyntax.Body)
	if !isHcl {
		logger.Printf("file is not hcl")
		return nil
	}
	block := parser.BlockAtPos(body, pos)
	candidateList := make([]lsp.CompletionItem, 0)
	if block != nil && len(block.Labels) != 0 && strings.HasPrefix(block.Labels[0], "azapi") {
		resourceName := fmt.Sprintf("%s.%s", block.Type, block.Labels[0])
		resource := tfschema.GetResourceSchema(resourceName)
		if resource == nil {
			return candidateList
		}
		if attribute := parser.AttributeAtPos(block, pos); attribute != nil {
			property := resource.GetProperty(attribute.Name)
			if property != nil {
				if property.GenericCandidatesFunc != nil {
					candidateList = append(candidateList, property.GenericCandidatesFunc(data, filename, block, attribute, pos, property)...)
				} else if property.ValueCandidatesFunc != nil {
					prefix := parser.ToLiteral(attribute.Expr)
					candidateList = append(candidateList, property.ValueCandidatesFunc(prefix, editRangeFromExprRange(attribute.Expr, pos))...)
				}
			}
		} else {
			if subBody := parser.BlockAtPos(block.Body, pos); subBody != nil {
				property := resource.GetProperty(subBody.Type)
				if property == nil {
					return nil
				}
				if attribute := parser.AttributeAtPos(subBody, pos); attribute != nil {
					for _, p := range property.NestedProperties {
						if p.Name == attribute.Name && p.ValueCandidatesFunc != nil {
							candidateList = append(candidateList, p.ValueCandidatesFunc(nil, editRangeFromExprRange(attribute.Expr, pos))...)
							break
						}
					}
				}
			} else {
				//input a top level property
				editRange := lsp.Range{
					Start: ilsp.HCLPosToLSP(pos),
					End:   ilsp.HCLPosToLSP(pos),
				}
				editRange.Start.Character = 2
				candidateList = append(candidateList, tfschema.PropertiesCandidates(resource.Properties, editRange)...)
				candidateList = append(candidateList, snippets.CodeSampleCandidates(block, editRange)...)
			}
		}
	}
	// the cursor is not in a block
	if block == nil {
		editRange := lsp.Range{
			Start: ilsp.HCLPosToLSP(pos),
			End:   ilsp.HCLPosToLSP(pos),
		}
		editRange.Start.Character = 0
		candidateList = append(candidateList, snippets.TemplateCandidates(editRange)...)
	}

	sort.Slice(candidateList, func(i, j int) bool { return candidateList[i].SortText < candidateList[j].SortText })
	return candidateList
}