4747import com .google .template .soy .soytree .PrintNode ;
4848import com .google .template .soy .soytree .SoyFileNode ;
4949import com .google .template .soy .soytree .SoyTreeUtils ;
50+ import com .google .template .soy .types .RecordType ;
5051import com .google .template .soy .types .SanitizedType ;
5152import com .google .template .soy .types .SoyType ;
5253import com .google .template .soy .types .SoyType .Kind ;
@@ -66,7 +67,7 @@ final class RewriteShortFormCallsPass implements CompilerFileSetPass {
6667 Impression .ERROR_REWRITE_SHORT_FORM_CALLS_PASS_OVERFLOW );
6768 static final SoyErrorKind EXPECTED_NAMED_PARAMETERS =
6869 SoyErrorKind .of (
69- "Expected named parameters." ,
70+ "Expected named parameters or a single record parameter ." ,
7071 Impression .ERROR_REWRITE_SHORT_FORM_CALLS_PASS_EXPECTED_NAMED_PARAMETERS );
7172
7273 private final ErrorReporter errorReporter ;
@@ -202,33 +203,43 @@ private CallBasicNode convert(ExprRootNode expr, IdGenerator nodeIdGen) {
202203 return null ;
203204 }
204205
205- if (fnNode .getParamsStyle () == ParamsStyle .POSITIONAL ) {
206+ boolean dataParam = isShortFormDataCall (fnNode );
207+ if (fnNode .getParamsStyle () == ParamsStyle .POSITIONAL && !dataParam ) {
206208 errorReporter .report (fnNode .getSourceLocation (), EXPECTED_NAMED_PARAMETERS );
207209 // Only report error once.
208210 expr .replaceChild (0 , new StringNode ("$error" , QuoteStyle .SINGLE , expr .getSourceLocation ()));
209211 return null ;
210212 }
211213
214+ SourceLocation loc = expr .getSourceLocation ();
215+ ImmutableList <CommandTagAttribute > attrs = ImmutableList .of ();
216+ if (dataParam ) {
217+ CommandTagAttribute attr =
218+ new CommandTagAttribute (
219+ Identifier .create ("data" , loc ),
220+ QuoteStyle .DOUBLE ,
221+ ImmutableList .of (fnNode .getParam (0 )),
222+ loc );
223+ attr .valueAsExprList ().forEach (root -> root .setType (root .getRoot ().getType ()));
224+ attrs = ImmutableList .of (attr );
225+ }
226+
212227 ExprNode callee = nameExpr .copy (new CopyState ());
213228 SoyType type = callee .getType ();
214229 CallBasicNode call =
215230 new CallBasicNode (
216- nodeIdGen .genId (),
217- expr .getSourceLocation (),
218- expr .getSourceLocation (),
219- callee ,
220- ImmutableList .of (),
221- false ,
222- ErrorReporter .exploding ());
231+ nodeIdGen .genId (), loc , loc , callee , attrs , false , ErrorReporter .exploding ());
223232 call .setOriginalShortFormExprEquivalence (exprEquivalence .wrap (expr .copy (new CopyState ())));
224233 call .getCalleeExpr ().setType (type );
225- for (int i = 0 ; i < fnNode .getParamNames ().size (); i ++) {
226- Identifier id = fnNode .getParamNames ().get (i );
227- CallParamValueNode valueNode =
228- new CallParamValueNode (
229- nodeIdGen .genId (), id .location (), id , fnNode .getParam (i ).copy (new CopyState ()));
230- valueNode .getExpr ().setType (fnNode .getParam (i ).getType ());
231- call .addChild (valueNode );
234+ if (!dataParam ) {
235+ for (int i = 0 ; i < fnNode .getParamNames ().size (); i ++) {
236+ Identifier id = fnNode .getParamNames ().get (i );
237+ CallParamValueNode valueNode =
238+ new CallParamValueNode (
239+ nodeIdGen .genId (), id .location (), id , fnNode .getParam (i ).copy (new CopyState ()));
240+ valueNode .getExpr ().setType (fnNode .getParam (i ).getType ());
241+ call .addChild (valueNode );
242+ }
232243 }
233244
234245 // Allow CheckTemplateCallsPass to find stricthtml violations. This will be more strict than if
@@ -237,4 +248,15 @@ private CallBasicNode convert(ExprRootNode expr, IdGenerator nodeIdGen) {
237248
238249 return call ;
239250 }
251+
252+ private static boolean isShortFormDataCall (FunctionNode fnNode ) {
253+ if (fnNode .getParamsStyle () != ParamsStyle .POSITIONAL ) {
254+ return false ;
255+ }
256+ if (fnNode .getParams ().size () != 1 ) {
257+ return false ;
258+ }
259+ ExprNode param = fnNode .getParam (0 );
260+ return RecordType .EMPTY_RECORD .isAssignableFromLoose (param .getType ());
261+ }
240262}
0 commit comments