Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: just some spelling fixes
Excerpt
hiddentrue

Groovy Enhancement Proposal

Metadata

Number:

GEP-8

Title:

Static Type Checking

Version:

7

Type:

Feature

Status:

Draft

Leader:

Cédric Champeau

Created:

2011-10-08

Last modification:

2011-11-09

...

Feature

Example

Behaviour

Status

Method does not exist

Code Block
def method() {
...
}
methode() // typo

Complains about undefined method

Implemented

Property does not exist

Code Block
class A {
   int x
}
A obj = new A()
a.y = 2

Complains about undefined property "y"

Implemented

Assignment type checking

Code Block
int x=2
x = 'String'

Assigning a String to an int is forbidden

Implemented

Incompatible binary expressions

Code Block

'string'+1

Checks that arguments of a binary expression are compatible (here, no 'plus' method is available

Implemented

Possible loose loss of precision (1/2)

Code Block

long myLong = ...
int myInt = myLong

Complains about possible loose loss of precision

Implemented

Possible loose loss of precision (2/2)

Code Block

int myInt = 2L

Will not complain because '2' can be represented as an int

Implemented

Arrays components

Code Block
String[] arr = { '1','2','3' }
arr[2] = 200

Cannot assign an int value in an array of type String[]

Implemented

Method return type check

Code Block

String method() { 'Hello' }
int x = method() // return types don't match

Ensures that assignments are compatible with method return type

Implemented

Explicit return type checking

Code Block

int method() {
   return 'String' // return type is not compatible
}

Ensures that returned value is compatible with declared return type

Implemented

Implicit return type checking

Code Block

int method() {
   'String' // return type is not compatible
}

Ensures that returned value is compatible with declared return type

Implemented

Implicit toString()

Code Block

String method(String name) {
   StringBuilder sb = new StringBuilder()
   sb 'Hi ' << name << '!'
}

Implicit call to toString()

Implemented

Basic type inference

Code Block

def str = 'My string'
str.toUpperCase() // type of 'str' is inferred

Method calls as well as property access is are checked against inferred type

Implemented

Basic flow analysis

Code Block

def o = new Object()
o = 1
o = 'Hello'
o.toUpperCase()

Last method call will not complain because type of 'o' at this point can be inferred

Implemented

Instance of

Code Block

def o
...
if (o instanceof String) {
   o.toUpperCase() // no explicit cast required
}

Casts should not be necessary when type can be inferred from a previous instanceof check

Implemented

DefaultGroovyMethods support

Code Block

'123'.toInteger() // toInteger() is a Groovy extension method

Method calls can be resolved against Groovy extension methods

In progress (no type inference for closure arguments)

with

Code Block

class A {
   int x
}
def a = new A()
a.with {
   x = 1
}

Static type checking should be aware of the "with" structure

In progress

Categories

Code Block

use (MyStringCategory) {
   'string'.methodInStringCategory()
}

Compiler should be aware that extension method is found in a category

N/A (support will be limited as category support is inherently dynamic

Groovy list constructor

Code Block

Dimension d = [100,200]

Type checks the arguments and the number of arguments

Implemented

Groovy map constructor

Code Block

Bean myBean = [x:100,y:200]

Type checks the properties and checks for wrong property names

Implemented

Closure parameter types

Code Block

def closure = { int x, int y -> x+y }
closure(1,2)
closure('1','2') // complains

Type checking the arguments when calling a closure

Implemented

Closure return type inference

Code Block

def closure = { int x, int y -> x+y }
int sum = closure(1,2)

Closure return type can be infered inferred from block

Implemented

Method return type inference

Code Block

def method(int x, int y) { x+y }
int sum = method(1,2)

Return type can be infered inferred from a method if the method is itself annotated with @TypeChecked (or class is annotated with @TypeChecked)

Implemented

Multiple assignments

Code Block
def (x,y) = [1,2]

In case of inline declaration, type check arguments.

Implemented

Multiple assignments from a variable

Code Block
def (x,y) = list

In case of inline declaration, type check arguments.

Unsupported

Generics

Code Block

List<String> list = []
List<String> list = ['a','b','c']
List<String> list = [1,2,3] // should throw error

Type checking of generic parameters

Mostly implemented (some edge cases may fail)

Spread operator

Code Block

def list = ['a','b','c']
list*.toUpperCase()

Type checking against component type

Implemented

...