Does groovy @CompileStatic imply @TypeChecked?

人盡茶涼 提交于 2020-01-17 01:37:18

问题


I have been adding both @TypeChecked and @CompileStatic to groovy code.

The compiler accepts this, but is it redundant? Does TypeChecked add anything that CompileStatic does not? The docs seems to imply that CompileStatic is a superset, but stop short of saying so outright. I would like to compile statically while occasionally disabling strict type checking, to let groovy auto-typecast while still catching misspelled references or missing methods.

An example:

@TypeChecked
@CompileStatic
class MyClass {
    void simple() {
        // compiles fine statically
    }

    @TypeChecked(SKIP)
    void complicated() {
        // would require too many ugly typecasts
    }

    @CompileDynamic
    void evenworse() {
        // need time to untangle this
    }
}

I read Difference between @TypeChecked and @CompileStatic and it did not answer this specific question. It suggested that TypeCast allows some additional checks, but I don't know if it does additional checks by default.


回答1:


I would say yes, CompileStatic implies TypeChecked. Looking into the groovy source for the annotation interfaces TypeChecked and CompileStatic, we see:

// TypeChecked.java
@GroovyASTTransformationClass("org.codehaus.groovy.transform.StaticTypesTransformation")
public @interface TypeChecked {

and

// CompileStatic.java
@GroovyASTTransformationClass("org.codehaus.groovy.transform.sc.StaticCompileTransformation")
public @interface CompileStatic {
...

which tells us that the classes doing the actual AST transformations (the work of the annotations) are StaticCompileTransformation and StaticTypesTransformation.

Looking at the code for those we get:

// Transformation for TypeChecked
public class StaticTypesTransformation implements ASTTransformation, CompilationUnitAware {

and

// Transformation for CompileStatic
public class StaticCompileTransformation extends StaticTypesTransformation {

i.e. the transformation for CompileStatic extends the transformation for TypeChecked, thus it would seem that the behavior of CompileStatic is indeed a superset of the behavior of TypeChecked.

<< edit >>

Digging even deeper, we see that the transformation classes use a visitor pattern and that they have respectively the following methods:

    // StaticTypesTransformation, transformation for TypeChecked
    protected StaticTypeCheckingVisitor newVisitor(SourceUnit unit, ClassNode node) {
        return new StaticTypeCheckingVisitor(unit, node);
    }

and

    // StaticCompileTransformation, transformation for CompileStatic 
    protected StaticTypeCheckingVisitor newVisitor(final SourceUnit unit, final ClassNode node) {
        return new StaticCompilationVisitor(unit, node);
    }

which return a custom visitor class for each of the cases.

Looking at the StaticCompilationVisitor we see:

public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
    ...
    public void visitClass(final ClassNode node) {
        ...
        super.visitClass(node);
        ...
    }
    ...
}

in other words, the visitor class for CompileStatic extends the visitor class for TypeChecked and in addition, the visitClass method (which does the actual work) in the CompileStatic visitor calls super.visitClass(node) where super is the visitor class for TypeChecked.

I think this more or less proves it. The behavior of CompileStatic is in fact a superset of the behavior of TypeChecked.



来源:https://stackoverflow.com/questions/55717879/does-groovy-compilestatic-imply-typechecked

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!