codeconsole commented on code in PR #16139:
URL: https://github.com/apache/grails-core/pull/16139#discussion_r3827315976


##########
grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java:
##########
@@ -1235,6 +1430,67 @@ private void flushBufferedWhiteSpace() {
         currentlyBufferingWhitespace = false;
     }
 
+    /**
+     * Declares the variable a {@code <g:set type="...">} names, so that the 
rest of the page reads it
+     * with a type rather than through the page binding.
+     *
+     * <p>The tag keeps doing what it did: the declaration is written first 
and the tag is then called
+     * with the declared variable as its value, so the write into the scope 
still happens and
+     * {@code scope} still decides where. What it adds is that the page itself 
no longer has to look
+     * the name up to read it.</p>
+     *
+     * <p>Only a {@code value} can be typed. Where the value is the tag's body 
or a {@code bean}, there
+     * is no expression to declare the variable from -- both are produced when 
the tag runs -- so
+     * asking for a type there is rejected rather than quietly ignored.</p>
+     */
+    private void writeTypedSetDeclaration(String ns, String tagName, 
Map<String, String> attrs) {
+        if (!GroovyPage.DEFAULT_NAMESPACE.equals(ns) || 
!SET_TAG_NAME.equals(tagName)) {
+            return;
+        }
+        String type = attributeText(attrs, TYPE_ATTRIBUTE);
+        if (type == null) {
+            return;
+        }
+        String var = attributeText(attrs, VAR_ATTRIBUTE);
+        if (GrailsStringUtils.isBlank(var)) {
+            throw new GrailsTagException("Tag [set] with a [type] needs a 
[var] naming what to declare",
+                    pageName, getCurrentOutputLineNumber());
+        }
+        Object value = attrs.get("\"value\"");
+        if (value == null) {
+            throw new GrailsTagException("Tag [set] can only be given a [type] 
together with a [value]; " +
+                    "the body and the [bean] attribute are produced when the 
tag runs, so there is nothing " +
+                    "to declare the variable from", pageName, 
getCurrentOutputLineNumber());
+        }
+        attrs.remove("\"" + TYPE_ATTRIBUTE + "\"");
+        // A name typed once is declared; typing it again assigns to what was 
declared. Declaring it
+        // twice would not compile, where the untyped tag simply writes the 
scope again.
+        String declaration = declareTypedSetVariable(var) ? type + " " + var : 
var;
+        out.println(declaration + " = " + castingTypeFor(type) + ".cast(" + 
getExpressionText(value.toString()) + ")");

Review Comment:
   Confirmed and fixed in 16c7624 — all four of your cases threw at render, 
exactly as listed. Both tags emit a Groovy cast now, which is what 
`writeFrameworkSuppliedAccessors` already did.
   
   Three of the four render correctly. `List` from `String[]` is now reported 
at compile time as `Inconvertible types` rather than throwing at render — 
better, but not silently coerced; a page wanting that writes `as List` in the 
value.
   
   You were right about the tests agreeing with the bug: `${2L}` and `${1.5d}` 
are gone, replaced with `${2}` for both, plus GString and multi-expression 
cases.



##########
grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyDefTag.java:
##########
@@ -59,10 +71,18 @@ public void doStartTag() {
         if (typeName.equals("def") || typeName.equals("Object")) {
             out.println(expr);
         } else {
-            out.println(typeName + ".cast(" + expr + ")");
+            // Cast through the wrapper for a primitive: Class.cast on a 
primitive class throws
+            // whatever it is handed, so int.cast(1) fails where 
Integer.cast(1) is what was meant.
+            // The declared type stays primitive, and the result unboxes into 
it.
+            out.println(castingTypeFor(typeName) + ".cast(" + expr + ")");

Review Comment:
   Fixed in the same commit. Both the cast and the parenthesisation.
   
   On the pre-existing one: parenthesising alone was not enough — 
`calculateExpression` returns the raw text for a mixed value, so it was not 
Groovy to begin with. The value is emitted as a GString literal where it is 
neither a lone `${...}` nor plain text, which leaves `<g:def var="x" 
value="someVariable"/>` reading a variable as before. `${a} and ${b}` was 
broken the same way and is covered too.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to