finishParsingFunctionCall parses a function call assuming that the function name was already read, and so the peeker should be pointing at the opening parenthesis after the name, or at the double-colon after the initial function scope name.
(name Token)
| 1155 | // parenthesis after the name, or at the double-colon after the initial |
| 1156 | // function scope name. |
| 1157 | func (p *parser) finishParsingFunctionCall(name Token) (Expression, hcl.Diagnostics) { |
| 1158 | var diags hcl.Diagnostics |
| 1159 | |
| 1160 | openTok := p.Read() |
| 1161 | if openTok.Type != TokenOParen && openTok.Type != TokenDoubleColon { |
| 1162 | // should never happen if callers behave |
| 1163 | panic("finishParsingFunctionCall called with unsupported next token") |
| 1164 | } |
| 1165 | |
| 1166 | nameStr := string(name.Bytes) |
| 1167 | nameEndPos := name.Range.End |
| 1168 | for openTok.Type == TokenDoubleColon { |
| 1169 | nextName := p.Read() |
| 1170 | if nextName.Type != TokenIdent { |
| 1171 | diag := hcl.Diagnostic{ |
| 1172 | Severity: hcl.DiagError, |
| 1173 | Summary: "Missing function name", |
| 1174 | Detail: "Function scope resolution symbol :: must be followed by a function name in this scope.", |
| 1175 | Subject: &nextName.Range, |
| 1176 | Context: hcl.RangeBetween(name.Range, nextName.Range).Ptr(), |
| 1177 | } |
| 1178 | diags = append(diags, &diag) |
| 1179 | p.recoverOver(TokenOParen) |
| 1180 | return &ExprSyntaxError{ |
| 1181 | ParseDiags: hcl.Diagnostics{&diag}, |
| 1182 | Placeholder: cty.DynamicVal, |
| 1183 | SrcRange: hcl.RangeBetween(name.Range, nextName.Range), |
| 1184 | }, diags |
| 1185 | } |
| 1186 | |
| 1187 | // Initial versions of HCLv2 didn't support function namespaces, and |
| 1188 | // so for backward compatibility we just treat namespaced functions |
| 1189 | // as weird names with "::" separators in them, saved as a string |
| 1190 | // to keep the API unchanged. FunctionCallExpr also has some special |
| 1191 | // handling of names containing :: when referring to a function that |
| 1192 | // doesn't exist in EvalContext, to return better error messages |
| 1193 | // when namespaces are used incorrectly. |
| 1194 | nameStr = nameStr + "::" + string(nextName.Bytes) |
| 1195 | nameEndPos = nextName.Range.End |
| 1196 | |
| 1197 | openTok = p.Read() |
| 1198 | } |
| 1199 | |
| 1200 | nameRange := hcl.Range{ |
| 1201 | Filename: name.Range.Filename, |
| 1202 | Start: name.Range.Start, |
| 1203 | End: nameEndPos, |
| 1204 | } |
| 1205 | |
| 1206 | if openTok.Type != TokenOParen { |
| 1207 | diag := hcl.Diagnostic{ |
| 1208 | Severity: hcl.DiagError, |
| 1209 | Summary: "Missing open parenthesis", |
| 1210 | Detail: "Function selector must be followed by an open parenthesis to begin the function call.", |
| 1211 | Subject: &openTok.Range, |
| 1212 | Context: hcl.RangeBetween(name.Range, openTok.Range).Ptr(), |
| 1213 | } |
| 1214 |
no test coverage detected