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]