You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/01/06 11:35:28 UTC

[groovy] branch GROOVY_4_0_X updated (ede0116 -> 40b0174)

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a change to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from ede0116  Tweak `NamedValueTest`
     new 8f747af  GROOVY-10433: "sealed" not usable as a restricted identifier
     new be0d0d8  Merge branch 'GROOVY_4_0_X' of https://gitbox.apache.org/repos/asf/groovy into GROOVY_4_0_X
     new cfc340f  documentation: initial placeholder for generics doco plus minor restructure
     new 675cb88  documentation: replac TBD with initial version of info on expressions
     new 40b0174  documentation: replace TBD with initial version of security info

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/antlr/GroovyParser.g4                          |   1 +
 src/spec/doc/core-differences-java.adoc            |   7 +-
 src/spec/doc/core-object-orientation.adoc          | 104 +++++++++----
 src/spec/doc/core-semantics.adoc                   |  53 ++++++-
 src/spec/doc/core-syntax.adoc                      | 112 +++++++------
 src/spec/test/PrimitiveTest.groovy                 |  10 +-
 src/spec/test/SyntaxTest.groovy                    | 173 +++++++++++++++++++++
 subprojects/groovy-binary/src/spec/doc/index.adoc  |  37 ++++-
 .../groovy-sql/src/spec/doc/sql-userguide.adoc     |   1 +
 9 files changed, 402 insertions(+), 96 deletions(-)

[groovy] 05/05: documentation: replace TBD with initial version of security info

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 40b0174dcd39b33c25b32ff2bef963c6fcd046b1
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu Jan 6 20:46:25 2022 +1000

    documentation: replace TBD with initial version of security info
---
 subprojects/groovy-binary/src/spec/doc/index.adoc  | 37 +++++++++++++++++++++-
 .../groovy-sql/src/spec/doc/sql-userguide.adoc     |  1 +
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/subprojects/groovy-binary/src/spec/doc/index.adoc b/subprojects/groovy-binary/src/spec/doc/index.adoc
index 9e096b7..a0ef111 100644
--- a/subprojects/groovy-binary/src/spec/doc/index.adoc
+++ b/subprojects/groovy-binary/src/spec/doc/index.adoc
@@ -55,6 +55,7 @@ include::../../../../../src/spec/doc/core-introduction.adoc[]
 :jmx:
 :tools-groovyc:
 :xml-userguide:
+:sql-userguide:
 
 include::../../../../../src/spec/doc/core-syntax.adoc[leveloffset=+2]
 
@@ -136,7 +137,41 @@ Creating Swing UIs is made easy thanks to the use of <<swingbuilder,SwingBuilder
 
 === Security
 
-(TBD)
+Security is a complex and multi-faceted issue and needs to be addressed in a holistic way.
+Groovy offers some features to improve security, but organisations
+concerned about security should already be addressing other necessary aspects
+such as network security, file-system security, operating sytem security, database security,
+passwords and potentially encryption.
+
+Also, since Groovy runs on the JDK and optionally uses other library dependencies,
+users should ensure their JDK and all depdendencies are up to date with respect to
+the latest security fixes.
+
+With regard to security issues that may affect the Groovy project itself,
+the project follows the Apache http://www.apache.org/security/committers.html[general guidelines for handling security vulnerabilities]. See also the project's
+https://github.com/apache/groovy/security/policy[security policy] and list of
+https://groovy-lang.org/security.html[past vulnerabilities].
+
+By virtue of running on the JVM and following various Java conventions, Groovy programs
+offer some of the same security features as Java programs, including:
+
+* programs cannot access arbitrary memory locations
+* final variables cannot be changed
+* array bounds are checked
+* class loaders perform bytecode verification when loading classes
+* casting cannot be done to an incompatible class
+* access is available to APIs for encryption and authentication
+
+Special security support is provided through:
+
+* gapi:groovy.lang.GroovyShell[], gapi:groovy.lang.GroovyClassLoader[] and other parts of the Groovy runtime fully support the Java security manager which allows you to sandbox script execution with a security policy. (Note: this funtionality might be scaled back in future Groovy versions or when running
+on particular JDK versions in line with https://openjdk.java.net/jeps/411[JEP 411])
+* gapi:org.codehaus.groovy.control.customizers.SecureASTCustomizer[]
+secures source code by controlling what code constructs are permitted or prohibited in a code base
+(or part of a code base)
+* Default <<{xml-userguide}#processing-xml,XML processing>> has secure processing enabled and doctype definitions disabled
+* Groovy's <<{sql-userguide}#processing-sql,SQL processing>> features provide support to guard against SQL injection
+* Temporary directory creation protects against known security vulnerabilities such as privilege escalation if scripts are stored in operating system temp directories
 
 include::../../../../../src/spec/doc/design-patterns-in-groovy.adoc[leveloffset=+2]
 
diff --git a/subprojects/groovy-sql/src/spec/doc/sql-userguide.adoc b/subprojects/groovy-sql/src/spec/doc/sql-userguide.adoc
index 6f44f8e..b9ec839 100644
--- a/subprojects/groovy-sql/src/spec/doc/sql-userguide.adoc
+++ b/subprojects/groovy-sql/src/spec/doc/sql-userguide.adoc
@@ -19,6 +19,7 @@
 
 //////////////////////////////////////////
 
+[[processing-sql]]
 = Interacting with a SQL database
 
 Groovy's `groovy-sql` module provides a higher-level abstraction over Java's JDBC technology. JDBC itself provides

[groovy] 03/05: documentation: initial placeholder for generics doco plus minor restructure

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit cfc340ff5c8d2b46a37691c905b5848c2e4d3ac8
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Jan 4 22:10:48 2022 +1000

    documentation: initial placeholder for generics doco plus minor restructure
---
 src/spec/doc/core-object-orientation.adoc | 104 ++++++++++++++++++++----------
 src/spec/test/PrimitiveTest.groovy        |  10 +--
 2 files changed, 76 insertions(+), 38 deletions(-)

diff --git a/src/spec/doc/core-object-orientation.adoc b/src/spec/doc/core-object-orientation.adoc
index 8ff4535..f936abe 100644
--- a/src/spec/doc/core-object-orientation.adoc
+++ b/src/spec/doc/core-object-orientation.adoc
@@ -23,21 +23,21 @@
 :jls: https://docs.oracle.com/javase/specs/jls/se14/html/
 :javabeans: https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/
 
-This chapter covers the object orientation of the Groovy programming language.
+This chapter covers the object-oriented aspects of the Groovy programming language.
 
 == Types
 
 === Primitive types
 
-Groovy supports the same primitive types as those defined by the {jls}[Java Language Specification]:
+Groovy supports the same primitive types as defined by the {jls}[Java Language Specification]:
 
 * integral types: `byte` (8 bit), `short` (16 bit), `int` (32 bit) and `long` (64 bit)
 * floating-point types: `float` (32 bit) and `double` (64 bit)
-* `boolean` type (exactly `true` or `false`)
-* `char` type (16 bit, usable as a numeric type, representing an UTF-16 code)
+* the `boolean` type (one of `true` or `false`)
+* the `char` type (16 bit, usable as a numeric type, representing a UTF-16 code)
 
-While Groovy declares and stores primitive fields and variables as primitives, because it uses Objects for
-everything, it autowraps references to primitives. Just like Java, the wrappers it uses are
+Also like Java, Groovy uses the respective wrapper classes when objects corresponding to any
+of the primitive types are required:
 
 [cols="1,1" options="header"]
 .primitive wrappers
@@ -67,12 +67,22 @@ everything, it autowraps references to primitives. Just like Java, the wrappers
 | Double
 |====
 
-Here's an example using `int`
+Automatic boxing and unboxing occur when, for instance, calling a method requiring
+the wrapper class and passing it a primitive variable as the parameter, or vice-versa.
+This is similar to Java but Groovy takes the idea further.
+
+In most scenarios, you can treat a primitive just like it was the full object wrapper equivalent.
+For instance, you can call `.toString()` or `.equals(other)` on a primitive.
+Groovy autowraps and unwraps between references and primitives as needed.
+
+Here's an example using `int` which is declared as a static field in a class (discussed shortly):
 
 [source,groovy]
 ----
 include::../test/PrimitiveTest.groovy[tags=primitive_references,indent=0]
 ----
+<1> Primitive type is respected in the bytecode
+<2> Looking at the field at runtime shows it has been autowrapped
 
 Now you may be concerned that this means every time you use a mathematical operator on a reference to a primitive
 that you'll incur the cost of unboxing and reboxing the primitive. But this is not the case, as Groovy will compile
@@ -81,7 +91,40 @@ Additionally, Groovy will automatically unbox to a primitive when calling a Java
 parameter and automatically box primitive method return values from Java. However, be aware there are some
 link:core-differences-java.html#_primitives_and_wrappers[differences] from Java's method resolution.
 
-=== Class
+=== Reference Types
+
+Apart from primitives, everything else is an object and has an associated class defining its type.
+We'll discuss classes, and class-related or class-like things like interfaces, traits and records shortly.
+
+We might declare two variables, of type String and List, as follows:
+[source,groovy]
+----
+String movie = 'The Matrix'
+List actors = ['Keanu Reeves', 'Hugo Weaving']
+----
+
+[[generics]]
+=== Generics
+
+Groovy carries across the same concepts with regard to generics as Java.
+When defining classes and methods, it is possible to use a type parameter and create
+a generic class, interface, method or constructor.
+
+Usage of generic classes and methods, regardless of whether they are defined in Java
+or Groovy, may involve supplying a type argument.
+
+We might declare a variable, of type _"list of string"_, as follows:
+[source,groovy]
+----
+List<String> roles = ['Trinity', 'Morpheus']
+----
+
+Java employs type erasure for backwards compatibility with earlier versions of Java.
+Dynamic Groovy can be thought of as more agressively applying type erasure.
+In general,  less generics type information will be checked at compile time.
+Groovy's static nature employs similar checks to Java with regard to generics information.
+
+== Classes
 
 Groovy classes are very similar to Java classes, and are compatible with Java ones at JVM level.
 They may have methods, fields and properties (think JavaBeans properties but with less boilerplate).
@@ -108,7 +151,7 @@ include::../test/ClassTest.groovy[tags=class_definition,indent=0]
 <3> method definition
 
 
-==== Normal class
+=== Normal class
 
 Normal classes refer to classes which are top level and concrete. This means they can be instantiated without restrictions from any other classes or scripts. This way, they can only be public (even though the `public` keyword may be suppressed). Classes are instantiated by calling their constructors, using the `new` keyword, as in the following snippet.
 
@@ -118,7 +161,7 @@ include::../test/ClassTest.groovy[tags=class_instantiation,indent=0]
 ----
 
 
-==== Inner class
+=== Inner class
 
 Inner classes are defined within another classes. The enclosing class can use the inner class as usual. On the other side, a inner class can access members of its enclosing class, even if they are private. Classes other than the enclosing class are not allowed to access inner classes. Here is an example:
 
@@ -155,7 +198,7 @@ Groovy 3+ also supports Java syntax for non-static inner class instantiation, fo
 include::../test/ClassTest.groovy[tags=inner_instantiation,indent=0]
 --------------------------------------
 
-===== Anonymous inner class
+==== Anonymous inner class
 
 The earlier example of an inner class (`Inner2`) can be simplified with an anonymous inner class.
 The same functionality can be achieved with the following code:
@@ -203,7 +246,14 @@ one or more <<_traits,traits>> is reused by a child class
 * _contract_ inheritance where a class promises to provide particular abstract methods defined in a <<superclass,superclass>>,
 or defined in one or more <<_traits,traits>> or <<_interface,interfaces>>.
 
-=== Interface
+[[superclass]]
+=== Superclasses
+
+Parent classes share visible fields, properties or methods with child classes.
+A child class may have at most one parent class.
+The `extends` keyword is used immediately prior to giving the superclass type.
+
+=== Interfaces
 
 An interface defines a contract that a class needs to conform to.
 An interface only defines a list of methods that need
@@ -270,12 +320,7 @@ TIP: Groovy interfaces do not support default implementation like Java 8 interfa
 similar (but not equal), <<_traits,traits>> are close to interfaces, but allow default implementation as well as other
 important features described in this manual.
 
-[[superclass]]
-=== Superclass
-
-Parent classes share visible fields, properties or methods with child classes.
-A child class may have at most one parent class.
-The `extends` keyword is used immediately prior to giving the superclass type.
+== Class members
 
 === Constructors
 
@@ -594,7 +639,6 @@ Casting can be used to select the desired method:
 include::../test/objectorientation/MethodsTest.groovy[tags=multi_method_ambiguous_cast,indent=0]
 ----
 
-
 ==== Exception declaration
 
 Groovy automatically allows you to treat checked exceptions like unchecked exceptions.
@@ -863,10 +907,10 @@ Inherited accessor methods aren't normally considered but if an inherited
 accessor method is marked final, that will also cause no generation of an
 additional accessor method to honor the `final` requirement of no subclassing of such methods.
 
-=== Annotation
+== Annotations
 
 [[ann-definition]]
-==== Annotation definition
+=== Annotation definition
 
 An annotation is a kind of special interface dedicated at annotating elements of the code. An annotation is a type which
 superinterface is the jdk:java.lang.annotation.Annotation[Annotation] interface. Annotations are declared in a very
@@ -1018,9 +1062,9 @@ Then the runner can be used this way:
 include::../test/ClassTest.groovy[tags=closure_ann_runner_exec,indent=0]
 ----
 
-==== Meta-annotations
+=== Meta-annotations
 
-===== Declaring meta-annotations
+==== Declaring meta-annotations
 
 Meta-annotations, also known as annotation aliases are annotations that
 are replaced at compile time by other annotations (one meta-annotation
@@ -1058,7 +1102,7 @@ include::../test/ClassTest.groovy[tags=metaann_ts,indent=0]
 <3> annotate the meta-annotation with `@AnnotationCollector`
 
 [[meta-ann-behavior]]
-===== Behavior of meta-annotations
+==== Behavior of meta-annotations
 
 Groovy supports both _precompiled_ and _source form_
 meta-annotations. This means that your meta-annotation _may_ be
@@ -1089,7 +1133,7 @@ In addition to replacing the alias with the collected annotations, a meta-annota
 processing them, including arguments.
 
 [[meta-ann-members]]
-===== Meta-annotation parameters
+==== Meta-annotation parameters
 
 Meta-annotations can collect annotations which have parameters. To illustrate this,
 we will imagine two annotations, each of them accepting one argument:
@@ -1146,7 +1190,7 @@ annotations are expanded. We'll look at how to do that shortly but first there i
 processing option to cover.
 
 [[handling_duplicate_annotations]]
-===== Handling duplicate annotations
+==== Handling duplicate annotations in meta-annotations
 
 The `@AnnotationCollector` annotation supports a `mode` parameter which can be used to
 alter how the default processor handles annotation replacement in the presence of
@@ -1177,7 +1221,7 @@ enum value chosen and is summarized in the following table.
 |================================
 
 [[meta-ann-processor]]
-===== Custom annotation processors
+==== Custom meta-annotation processors
 
 A custom annotation processor will let you choose how to expand a
 meta-annotation into collected annotations. The behaviour of the meta-annotation is,
@@ -1236,12 +1280,6 @@ In the example, the `visit` method is the only method which has to be overridden
 annotation nodes that will be added to the node annotated with the meta-annotation. In this example, we return a
 single one corresponding to `@CompileStatic(TypeCheckingMode.SKIP)`.
 
-[[generics]]
-=== Generics
-
-(TBD)
-
-
 include::_traits.adoc[leveloffset=+1]
 
 include::_records.adoc[leveloffset=+1]
diff --git a/src/spec/test/PrimitiveTest.groovy b/src/spec/test/PrimitiveTest.groovy
index d086710..f7b6609 100644
--- a/src/spec/test/PrimitiveTest.groovy
+++ b/src/spec/test/PrimitiveTest.groovy
@@ -24,11 +24,11 @@ class PrimitiveTest extends GroovyTestCase {
         assertScript '''
             // tag::primitive_references[]
             class Foo {
-              static int i
+                static int i
             }
 
-            assert Foo.class.getDeclaredField('i').type == int.class
-            assert Foo.i.class != int.class && Foo.i.class == Integer.class
+            assert Foo.class.getDeclaredField('i').type == int.class           //<1>
+            assert Foo.i.class != int.class && Foo.i.class == Integer.class    //<2>
             // end::primitive_references[]
         '''
     }
@@ -40,11 +40,11 @@ class PrimitiveTest extends GroovyTestCase {
             m(i)
 
             void m(long l) {           //<1>
-              println "in m(long)"
+                println "in m(long)"
             }
 
             void m(Integer i) {        //<2>
-              println "in m(Integer)"
+                println "in m(Integer)"
             }
             // end::widening_vs_boxing[]
         '''

[groovy] 01/05: GROOVY-10433: "sealed" not usable as a restricted identifier

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 8f747afcfd60d5d84a101248c3ae1456834d532c
Author: Paul King <pa...@asert.com.au>
AuthorDate: Fri Dec 31 20:09:19 2021 +1000

    GROOVY-10433: "sealed" not usable as a restricted identifier
---
 src/antlr/GroovyParser.g4               |   1 +
 src/spec/doc/core-differences-java.adoc |   7 +-
 src/spec/doc/core-syntax.adoc           | 112 ++++++++++++---------
 src/spec/test/SyntaxTest.groovy         | 173 ++++++++++++++++++++++++++++++++
 4 files changed, 243 insertions(+), 50 deletions(-)

diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index 6f2b8f9..9d26199 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -1220,6 +1220,7 @@ identifier
     |   AS
     |   YIELD
     |   PERMITS
+    |   SEALED
     |   RECORD
     ;
 
diff --git a/src/spec/doc/core-differences-java.adoc b/src/spec/doc/core-differences-java.adoc
index 5c4a937..cbb5264 100644
--- a/src/spec/doc/core-differences-java.adoc
+++ b/src/spec/doc/core-differences-java.adoc
@@ -22,6 +22,9 @@
 ifndef::core-semantics[]
 :core-semantics: core-semantics.adoc
 endif::[]
+ifndef::core-syntax[]
+:core-syntax: core-syntax.adoc
+endif::[]
 
 = Differences with Java
 
@@ -500,7 +503,7 @@ Other conversions have their behavior defined by `java.lang.Number`.
 
 == Extra keywords
 
-Groovy has many of the same keywords as Java and Groovy 3 also has the same `var` reserved type as Java.
+Groovy has many of the same keywords as Java and Groovy 3 and above also has the same `var` reserved type as Java.
 In addition, Groovy has the following keywords:
 
 * `as`
@@ -514,3 +517,5 @@ e.g. the following is valid: `var var = [def: 1, as: 2, in: 3, trait: 4]`.
 Never-the-less, you are discouraged from using the above keywords in places that might cause confusion even when
 the compiler might be happy. In particular, avoid using them for variable, method and class names,
 so our previous `var var` example would be considered poor style.
+
+Additional documentation is available for <<{core-syntax}#_keywords,keywords>>.
diff --git a/src/spec/doc/core-syntax.adoc b/src/spec/doc/core-syntax.adoc
index 691f3df..a60cff8 100644
--- a/src/spec/doc/core-syntax.adoc
+++ b/src/spec/doc/core-syntax.adoc
@@ -116,60 +116,74 @@ NOTE: The `#` character must be the first character of the file. Any indentation
 
 == Keywords
 
-The following list represents all the keywords of the Groovy language:
+Groovy has the following reserved keywords:
 
 [cols="1,1,1,1"]
-.Keywords
+.Reserved Keywords
 |===
-|as
-|assert
-|break
-|case
-
-|catch
-|class
-|const
-|continue
-
-|def
-|default
-|do
-|else
-
-|enum
-|extends
-|false
-|finally
-
-|for
-|goto
-|if
-|implements
-
-|import
-|in
-|instanceof
-|interface
-
-|new
-|null
-|package
-|return
-
-|super
-|switch
-|this
-|throw
-
-|throws
-|trait
-|true
-|try
-
-|var
-|while | |
+include::../test/SyntaxTest.groovy[tags=reserved_keywords,indent=0]
+|===
+
+Of these, `const`, `goto`, `strictfp`, and `threadsafe` are not currently in use.
+
+The reserved keywords can't in general be used for variable, field and method names.
+
+****
+A trick allows methods to be defined having the same name as a keyword
+by surrounding the name in quotes as shown in the following example:
+
+[source,groovy]
+----
+include::../test/SyntaxTest.groovy[tags=reserved_keywords_example,indent=0]
+----
+
+Using such names might be confusing and is often best to avoid.
+The trick is primarily intended to enable certain Java integration scenarios
+and certain link:core-domain-specific-languages.html[DSL] scenarios where
+having "verbs" and "nouns" with the same name as keywords may be desirable.
+****
 
+In addition, Groovy has the following contextual keywords:
+
+[cols="1,1,1,1"]
+.Contextual Keywords
 |===
+include::../test/SyntaxTest.groovy[tags=contextual_keywords,indent=0]
+|===
+
+These words are only keywords in certain contexts and can be more freely used in some places,
+in particular for variables, fields and method names.
+
+****
+This extra lenience allows using method or variable names that were not keywords in earlier
+versions of Groovy or are not keywords in Java. Examples are shown here:
+
+[source,groovy]
+----
+include::../test/SyntaxTest.groovy[tags=contextual_keywords_examples,indent=0]
+----
+Groovy programmers familiar with these contextual keywords may still wish to avoid
+using those names unless there is a good reason to use such a name.
+****
+
+The restrictions on reserved keywords also apply for the
+primitive types, the boolean literals and the null literal (all of which are discussed later):
+
+[cols="1,1,1,1"]
+.Other reserved words
+|===
+include::../test/SyntaxTest.groovy[tags=reserved_words,indent=0]
+|===
+
+****
+While not recommended, the same trick as for reserved keywords can be used:
+[source,groovy]
+----
+include::../test/SyntaxTest.groovy[tags=reserved_words_example,indent=0]
+----
+Using such words as method names is potentially confusing and is often best to avoid, however,
+it might be useful for certain kinds of link:core-domain-specific-languages.html[DSLs].
+****
 
 == Identifiers
 
diff --git a/src/spec/test/SyntaxTest.groovy b/src/spec/test/SyntaxTest.groovy
index 7fbb437..9813893 100644
--- a/src/spec/test/SyntaxTest.groovy
+++ b/src/spec/test/SyntaxTest.groovy
@@ -17,6 +17,7 @@
  *  under the License.
  */
 import gls.CompilableTestSupport
+import org.codehaus.groovy.control.CompilationFailedException
 
 class SyntaxTest extends CompilableTestSupport {
 
@@ -793,7 +794,179 @@ class SyntaxTest extends CompilableTestSupport {
         assert person.containsKey('name')    // <2>
         assert !person.containsKey('key')    // <3>
         // end::variable_key_2[]
+    }
 
+    void testReservedKeywords() {
+        def rk = '''
+        // tag::reserved_keywords[]
+        |abstract
+        |assert
+        |break
+        |case
+
+        |catch
+        |class
+        |const
+        |continue
+
+        |def
+        |default
+        |do
+        |else
+
+        |enum
+        |extends
+        |final
+        |finally
+
+        |for
+        |goto
+        |if
+        |implements
+
+        |import
+        |instanceof
+        |interface
+        |native
+
+        |new
+        |null
+        |non-sealed
+        |package
+
+        |public
+        |protected
+        |private
+        |return
+
+        |static
+        |strictfp
+        |super
+        |switch
+
+        |synchronized
+        |this
+        |threadsafe
+        |throw
+
+        |throws
+        |transient
+        |try
+        |while
+        // end::reserved_keywords[]
+        '''.readLines()[2..-3].join()
+        def reservedKeywords = rk.split(/(?m)[|]/)*.trim().grep()
+        def shell = new GroovyShell()
+        reservedKeywords.each {
+            /*
+            // tag::reserved_keywords_example[]
+            // reserved keywords can be used for method names if quoted
+            def "abstract"() { true }
+            // when calling such methods, the name must be qualified using "this."
+            this.abstract()
+            // end::reserved_keywords_example[]
+            */
+            assertScript """
+            def "$it"() { true }
+            assert this.$it()
+            """
+            shouldFail(CompilationFailedException) {
+                shell.parse """
+                    def $it() { true }
+                """
+            }
+            shouldFail(CompilationFailedException) {
+                shell.parse """
+                    def $it = true
+                """
+            }
+        }
+    }
 
+    void testContextualKeywords() {
+        def ck = '''
+        // tag::contextual_keywords[]
+        | as
+        | in
+        | permits
+        | record
+        | sealed
+        | trait
+        | var
+        | yields
+        // end::contextual_keywords[]
+        '''.readLines()[2..-3].join()
+        def contextualKeywords = ck.split(/(?m)[|]/)*.trim().grep()
+        def shell = new GroovyShell()
+        /*
+        // tag::contextual_keywords_examples[]
+        // contextual keywords can be used for field and variable names
+        def as = true
+        assert as
+
+        // contextual keywords can be used for method names
+        def in() { true }
+        // when calling such methods, the name only needs to be qualified using "this." in scenarios which would be ambiguous
+        this.in()
+        // end::contextual_keywords_examples[]
+        */
+        contextualKeywords.each {
+            assertScript """
+            def $it = true
+            assert $it
+            def $it() { true }
+            this.$it()
+            """
+            shouldFail(CompilationFailedException) {
+                shell.parse """
+                    def $it() { true }
+                    $it()
+                """
+            }
+        }
+    }
+
+    void testOtherReservedWords() {
+        def rw = '''
+        // tag::reserved_words[]
+        | null
+        | true
+        | false
+        | boolean
+        | char
+        | byte
+        | short
+        | int
+        | long
+        | float
+        | double
+        |
+        // end::reserved_words[]
+        '''.readLines()[2..-3].join()
+        def reservedWords = rw.split(/(?m)[|]/)*.trim().grep()
+        def shell = new GroovyShell()
+        /*
+        // tag::reserved_words_example[]
+        def "null"() { true }  // not recommended; potentially confusing
+        assert this.null()     // must be qualified
+        // end::reserved_words_example[]
+        */
+        reservedWords.each {
+            assertScript """
+            def "$it"() { true }
+            assert this.$it()
+            """
+            shouldFail(CompilationFailedException) {
+                shell.parse """
+                    def $it() { true }
+                """
+            }
+            shouldFail(CompilationFailedException) {
+                shell.parse """
+                    def $it = true
+                """
+            }
+
+        }
     }
 }

[groovy] 04/05: documentation: replac TBD with initial version of info on expressions

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 675cb888ab15fc6d98a335b72254a825263253d7
Author: Paul King <pa...@asert.com.au>
AuthorDate: Wed Jan 5 22:46:21 2022 +1000

    documentation: replac TBD with initial version of info on expressions
---
 src/spec/doc/core-semantics.adoc | 53 ++++++++++++++++++++++++++++++++++------
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/src/spec/doc/core-semantics.adoc b/src/spec/doc/core-semantics.adoc
index 20a0d04..fdbdb5e 100644
--- a/src/spec/doc/core-semantics.adoc
+++ b/src/spec/doc/core-semantics.adoc
@@ -458,17 +458,53 @@ does to make testing easier.
 
 == Expressions
 
-(TBD)
+Expressions are the building blocks of Groovy programs that are used to reference
+existing values and execute code to create new ones.
 
+Groovy supports many of the same kinds of expressions as Java, including:
+
+[cols="a,a"]
+.Expressions like Java
+|===
+| Example expression(s) |Description
+| `foo` | the name of a variable, field, parameter, ...
+| `this`, `super`, `it` | special names
+| `true`, `10`, `"bar"` | literals
+| `String.class` | Class literal
+| `(` _expression_ `)`| parenthesised expressions
+| `foo++`, `~bar` | Unary link:core-operators.html[operator] expressions
+| `foo + bar`, `bar * baz` | Binary link:core-operators.html[operator] expressions
+| `foo ? bar : baz` | Ternary link:core-operators.html[operator] expressions
+| `(Integer x, Integer y) -> x + y` | Lambda expressions
+|
+[source,groovy]
+----
+assert 'bar' == switch('foo') {
+  case 'foo' -> 'bar'
+}
+----
+| switch expressions
+|===
+
+Groovy also has some of its own special expressions:
+
+[cols="a,a"]
+.Special expressions
+|===
+| Example expression(s) |Description
+| `String` | Abbreviated class literal (when not ambiguous)
+| `{ x, y -> x + y }` | Closure expressions
+| `[1, 3, 5]` | literal list expressions
+| `[a:2, b:4, c:6]` | literal map expressions
+|===
+
+Groovy also expands on the normal dot-notation used in Java for member access.
+Groovy provides special support for accessing hierarchical data structures by specifying the
+path in the hierarchy of some data of interest.
+These _Groovy path_ expressions are known as GPath expressions.
 
 [[gpath_expressions]]
 === GPath expressions
-////
-This is covered in ../../../subprojects/groovy-xml/src/spec/doc/xml-userguide.adoc, where the legacy codehaus GPath wiki page
-have been converted.
-Current section should explain what is an GPath expression (not just example, but more like a formal language specification, but kept simple).
-
-////
 
 `GPath` is a path expression language integrated into Groovy which allows parts of nested structured data to be identified. In this
 sense, it has similar aims and scope as XPath does for XML.  GPath is often used in the context of processing XML, but it really applies
@@ -572,6 +608,9 @@ include::../test/semantics/GPathTest.groovy[tags=gpath_on_xml_1,indent=0]
 <3> There is one element `sublevel` having an attribute `id` with value `1`
 <4> Text value of `key` element of first `keyVal` element of second `sublevel` element under `root/level` is 'anotherKey'
 
+Further details about GPath expressions for XML are in the
+link:../../../subprojects/groovy-xml/src/spec/doc/xml-userguide.adoc[XML User Guide].
+
 == Promotion and coercion
 
 === Number promotion

[groovy] 02/05: Merge branch 'GROOVY_4_0_X' of https://gitbox.apache.org/repos/asf/groovy into GROOVY_4_0_X

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit be0d0d8512b43cac03c40359dcd12efeb4eea1f5
Merge: 8f747af ede0116
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu Jan 6 21:29:19 2022 +1000

    Merge branch 'GROOVY_4_0_X' of https://gitbox.apache.org/repos/asf/groovy into GROOVY_4_0_X

 src/spec/test/groovy/lang/NamedValueTest.groovy                     | 6 ++++++
 .../apache/groovy/ginq/provider/collection/runtime/Partition.java   | 1 +
 .../apache/groovy/ginq/provider/collection/runtime/Queryable.java   | 1 +
 3 files changed, 8 insertions(+)