jdaugherty commented on code in PR #16551: URL: https://github.com/apache/grails-core/pull/16551#discussion_r4210768192
########## grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/LogicLineTrimmer.java: ########## @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.grails.gsp.compiler; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Removes the lines of a page that hold only template logic, for a page declaring + * {@code trimLogicLines="true"}: a line holding nothing but page directives, scriptlets and comments, + * besides spaces and tabs, writes neither its indentation nor its line break. A line holding text, an + * expression or a tag is left as it is. + * + * <p>The line break of a removed line is moved inside the line's last construct, just after its + * opening delimiter, rather than dropped, so that every line of the page keeps its number in the + * compiled page and in the errors reported against it.</p> + */ +final class LogicLineTrimmer { + + private static final String CONSTRUCT = "(?:" + + "<%--(?:(?!--%>).)*--%>" + // <%-- comment --%> + "|%\\{--(?:(?!--\\}%).)*--\\}%" + // %{-- comment --}% + "|<%@(?:(?!%>).)*%>" + // <%@ directive %> + "|<%(?![=@]|--)(?:(?!%>).)*%>" + // <% scriptlet %> Review Comment: Fixed in 651f2cde15. A declaration (`<%!`) is no longer read as a scriptlet: its line is left as it is, so the page reports that declarations are not supported, the same as without `trimLogicLines`. Covered by "a declaration on its own line is rejected as it is with trimming" in `GspTrimLogicLinesSpec`, which failed with a `MissingMethodException` before the fix. ########## grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/LogicLineTrimmer.java: ########## @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.grails.gsp.compiler; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Removes the lines of a page that hold only template logic, for a page declaring + * {@code trimLogicLines="true"}: a line holding nothing but page directives, scriptlets and comments, + * besides spaces and tabs, writes neither its indentation nor its line break. A line holding text, an + * expression or a tag is left as it is. + * + * <p>The line break of a removed line is moved inside the line's last construct, just after its + * opening delimiter, rather than dropped, so that every line of the page keeps its number in the + * compiled page and in the errors reported against it.</p> + */ +final class LogicLineTrimmer { + + private static final String CONSTRUCT = "(?:" + + "<%--(?:(?!--%>).)*--%>" + // <%-- comment --%> + "|%\\{--(?:(?!--\\}%).)*--\\}%" + // %{-- comment --}% + "|<%@(?:(?!%>).)*%>" + // <%@ directive %> + "|<%(?![=@]|--)(?:(?!%>).)*%>" + // <% scriptlet %> + "|%\\{(?!--)(?:(?!\\}%).)*\\}%" + // %{ scriptlet }% + ")"; + + private static final Pattern CONSTRUCT_PATTERN = Pattern.compile(CONSTRUCT, Pattern.DOTALL); + + private static final Pattern LOGIC_LINE_PATTERN = Pattern.compile( + "^[ \\t]*(" + CONSTRUCT + "(?:[ \\t]*" + CONSTRUCT + ")*)[ \\t]*(\\r?\\n|\\z)", + Pattern.MULTILINE | Pattern.DOTALL); + + private LogicLineTrimmer() { + } + + static String trim(String gspSource) { + Matcher line = LOGIC_LINE_PATTERN.matcher(gspSource); Review Comment: Fixed in 651f2cde15. `LogicLineTrimmer` no longer runs a regex over the whole page. It walks the page the way `GroovyPageScanner` reads it (expressions through `GroovyPageExpressionParser`, tag attributes, scriptlets, comments), so a logic line can only start in the page's text. Text inside an expression, a tag, a scriptlet or a comment is never trimmed. New specs cover a multi-line `${}` string, a scriptlet string and a tag-attribute expression, and all three failed before the fix. The trimmed output of all 62 Forge GSPs is byte-identical before and after. -- 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]
