Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STC: NullPointerException for raw type guard followed by parameterized method call #1349

Closed
mauromol opened this issue Mar 7, 2022 · 11 comments
Assignees
Labels
Milestone

Comments

@mauromol
Copy link

mauromol commented Mar 7, 2022

Using Greclipse 4.5.0.v202203070924-e2112.
Using Groovy 2.5.16 in my project build path.

One of my projects has started to fail Groovy compilation within Eclipse with this error:

Groovy: compiler error: exception in phase 'instruction selection' in source unit 
 '/home/mauro/svn/myproject/mysubproject/src/main/groovy/it/dcssrl/fatturapa/web/invio/ui/common/validation/UiValidationUtils.
 groovy' unexpected NullPointerException

On the groovy console I find this:

   Code select : 18:02:52 Code select on UiValidationUtils.groovy at [ 502,0 ]
   Code select : 18:02:52 Event complete: 1ms: Code select: UiValidationUtils.groovy
AST Transforms : 18:02:52 Global transform org.codehaus.groovy.ast.builder.AstBuilderTransformation applied to UiValidationUtils.groovy in 0ms
      Compiler : 18:02:52 exception in phase 'instruction selection' in source unit '/home/mauro/svn/myproject/mysubproject/src/main/groovy/it/dcssrl/fatturapa/web/invio/ui/common/validation/UiValidationUtils.groovy' unexpected NullPointerException
      Compiler : 18:02:52 /home/mauro/svn/myproject/mysubproject/src/main/groovy/it/dcssrl/fatturapa/web/invio/ui/common/validation/UiValidationUtils.groovy: 1:  compiler error: exception in phase 'instruction selection' in source unit '/home/mauro/svn/myproject/mysubproject/src/main/groovy/it/dcssrl/fatturapa/web/invio/ui/common/validation/UiValidationUtils.groovy' unexpected NullPointerException @ line 1, column 1.
   package it.dcssrl.fatturapa.web.invio.ui.common.validation
   ^
AST Transforms : 18:02:54 Global transform groovy.grape.GrabAnnotationTransformation applied to UiValidationUtils.groovy in 0ms
AST Transforms : 18:02:54 Global transform org.codehaus.groovy.ast.builder.AstBuilderTransformation applied to UiValidationUtils.groovy in 0ms
      Compiler : 18:02:54 exception in phase 'instruction selection' in source unit '/home/mauro/svn/myproject/mysubproject/src/main/groovy/it/dcssrl/fatturapa/web/invio/ui/common/validation/UiValidationUtils.groovy' unexpected NullPointerException
      Compiler : 18:02:54 /home/mauro/svn/myproject/mysubproject/src/main/groovy/it/dcssrl/fatturapa/web/invio/ui/common/validation/UiValidationUtils.groovy: 1:  compiler error: exception in phase 'instruction selection' in source unit '/home/mauro/svn/myproject/mysubproject/src/main/groovy/it/dcssrl/fatturapa/web/invio/ui/common/validation/UiValidationUtils.groovy' unexpected NullPointerException @ line 1, column 1.
   package it.dcssrl.fatturapa.web.invio.ui.common.validation
   ^

This is a huge proprietary project, so I have no idea on how to cut it down. Is there something I can share with you to understand what's wrong? Maybe the contents of the affected class?

It seems like removing @CompileStatic from this class and issue a full project rebuild fixes the error.

This same project compiles fine with Gradle.

@eric-milles
Copy link
Member

You can debug your eclipse process by adding this to eclipse.ini:

-Xdebug
-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y

Then you can connect from any new java workspace using a Remote Java Application launch config set to port 5005. From there just add exception breakpoint for NullPointerException to get a stack in the Debug perspective.

@mauromol
Copy link
Author

mauromol commented Mar 7, 2022

Here it is:

Daemon Thread [org.eclipse.jdt.internal.ui.text.JavaReconciler] (Suspended (exception NullPointerException))	
	StaticTypeCheckingSupport.isAssignableTo(ClassNode, ClassNode) line: 506	
	StaticTypeCheckingSupport.allParametersAndArgumentsMatch(Parameter[], ClassNode[]) line: 372	
	StaticTypeCheckingSupport.measureParametersAndArgumentsDistance(Parameter[], ClassNode[]) line: 1205	
	StaticTypeCheckingSupport.chooseBestMethod(ClassNode, Collection<MethodNode>, ClassNode...) line: 1174	
	StaticTypeCheckingSupport.findDGMMethodsByNameAndArguments(ClassLoader, ClassNode, String, ClassNode[], List<MethodNode>) line: 1097	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).findMethod(ClassNode, String, ClassNode...) line: 5714	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitMethodCallExpression(MethodCallExpression) line: 4159	
	StaticCompilationVisitor.visitMethodCallExpression(MethodCallExpression) line: 423	
	MethodCallExpression.visit(GroovyCodeVisitor) line: 69	
	StaticCompilationVisitor(CodeVisitorSupport).visitExpressionStatement(ExpressionStatement) line: 120	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitExpressionStatement(ExpressionStatement) line: 289	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitExpressionStatement(ExpressionStatement) line: 2658	
	ExpressionStatement.visit(GroovyCodeVisitor) line: 40	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitIfElse(IfStatement) line: 4616	
	IfStatement.visit(GroovyCodeVisitor) line: 41	
	StaticCompilationVisitor(CodeVisitorSupport).visitBlockStatement(BlockStatement) line: 86	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitBlockStatement(BlockStatement) line: 253	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitBlockStatement(BlockStatement) line: 4672	
	BlockStatement.visit(GroovyCodeVisitor) line: 69	
	StaticCompilationVisitor(CodeVisitorSupport).visitClosureExpression(ClosureExpression) line: 225	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitClosureExpression(ClosureExpression) line: 2952	
	ClosureExpression.visit(GroovyCodeVisitor) line: 46	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitMethodCallArguments(ClassNode, ArgumentListExpression, boolean, MethodNode) line: 3346	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitMethodCallExpression(MethodCallExpression) line: 4248	
	StaticCompilationVisitor.visitMethodCallExpression(MethodCallExpression) line: 423	
	MethodCallExpression.visit(GroovyCodeVisitor) line: 69	
	StaticCompilationVisitor(CodeVisitorSupport).visitExpressionStatement(ExpressionStatement) line: 120	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitExpressionStatement(ExpressionStatement) line: 289	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitExpressionStatement(ExpressionStatement) line: 2658	
	ExpressionStatement.visit(GroovyCodeVisitor) line: 40	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitIfElse(IfStatement) line: 4616	
	IfStatement.visit(GroovyCodeVisitor) line: 41	
	StaticCompilationVisitor(CodeVisitorSupport).visitBlockStatement(BlockStatement) line: 86	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitBlockStatement(BlockStatement) line: 253	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitBlockStatement(BlockStatement) line: 4672	
	BlockStatement.visit(GroovyCodeVisitor) line: 69	
	StaticCompilationVisitor(CodeVisitorSupport).visitClosureExpression(ClosureExpression) line: 225	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitClosureExpression(ClosureExpression) line: 2952	
	ClosureExpression.visit(GroovyCodeVisitor) line: 46	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitMethodCallArguments(ClassNode, ArgumentListExpression, boolean, MethodNode) line: 3346	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitMethodCallExpression(MethodCallExpression) line: 4248	
	StaticCompilationVisitor.visitMethodCallExpression(MethodCallExpression) line: 423	
	MethodCallExpression.visit(GroovyCodeVisitor) line: 69	
	StaticCompilationVisitor(CodeVisitorSupport).visitExpressionStatement(ExpressionStatement) line: 120	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitExpressionStatement(ExpressionStatement) line: 289	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitExpressionStatement(ExpressionStatement) line: 2658	
	ExpressionStatement.visit(GroovyCodeVisitor) line: 40	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitIfElse(IfStatement) line: 4616	
	IfStatement.visit(GroovyCodeVisitor) line: 41	
	StaticCompilationVisitor(CodeVisitorSupport).visitBlockStatement(BlockStatement) line: 86	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitBlockStatement(BlockStatement) line: 253	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitBlockStatement(BlockStatement) line: 4672	
	BlockStatement.visit(GroovyCodeVisitor) line: 69	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitClassCodeContainer(Statement) line: 160	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitConstructorOrMethod(MethodNode, boolean) line: 171	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitConstructorOrMethod(MethodNode, boolean) line: 2622	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitMethod(MethodNode) line: 184	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).startMethodInference(MethodNode, ErrorCollector) line: 3158	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitMethod(MethodNode) line: 3121	
	StaticCompilationVisitor.visitConstructorOrMethod(MethodNode) line: 235	
	StaticCompilationVisitor.visitMethod(MethodNode) line: 250	
	ClassNode.visitContents(GroovyClassVisitor) line: 1167	
	StaticCompilationVisitor(ClassCodeVisitorSupport).visitClass(ClassNode) line: 56	
	StaticCompilationVisitor(StaticTypeCheckingVisitor).visitClass(ClassNode) line: 415	
	StaticCompilationVisitor.visitClass(ClassNode) line: 200	
	StaticCompileTransformation.visit(ASTNode[], SourceUnit) line: 65	
	ASTTransformationVisitor.visitClass(ClassNode) line: 191	
	ASTTransformationVisitor$2.call(SourceUnit, GeneratorContext, ClassNode) line: 290	
	CompilationUnit.applyToPrimaryClassNodes(CompilationUnit$PrimaryClassNodeOperation) line: 1150	
	CompilationUnit.doPhaseOperation(Object) line: 659	
	CompilationUnit.processPhaseOperations(int) line: 638	
	CompilationUnit.compile(int) line: 615	
	GroovyCompilationUnitDeclaration.processToPhase(int) line: 228	
	GroovyCompilationUnitDeclaration.generateCode() line: 315	
	CompilationUnitProblemFinder(Compiler).resolve(CompilationUnitDeclaration, ICompilationUnit, boolean, boolean, boolean) line: 1087	
	CompilationUnitProblemFinder.process(CompilationUnit, SourceElementParser, WorkingCopyOwner, HashMap, boolean, int, IProgressMonitor) line: 282	
	GroovyCompilationUnit.buildStructure(OpenableElementInfo, IProgressMonitor, Map, IResource) line: 296	
	GroovyCompilationUnit(Openable).generateInfos(Object, HashMap, IProgressMonitor) line: 266	
	GroovyCompilationUnit(JavaElement).openWhenClosed(Object, boolean, IProgressMonitor) line: 599	
	GroovyCompilationUnit(CompilationUnit).makeConsistent(int, boolean, int, HashMap, IProgressMonitor) line: 1154	
	GroovyReconcileWorkingCopyOperation.makeConsistent(CompilationUnit) line: 60	
	GroovyReconcileWorkingCopyOperation(ReconcileWorkingCopyOperation).executeOperation() line: 94	
	GroovyReconcileWorkingCopyOperation(JavaModelOperation).run(IProgressMonitor) line: 740	
	GroovyReconcileWorkingCopyOperation(JavaModelOperation).runOperation(IProgressMonitor) line: 806	
	GroovyCompilationUnit.reconcile(int, int, WorkingCopyOwner, IProgressMonitor) line: 384	
	JavaReconcilingStrategy.reconcile(ICompilationUnit, boolean) line: 131	
	JavaReconcilingStrategy$1.run() line: 93	
	SafeRunner.run(ISafeRunnable) line: 45	
	JavaReconcilingStrategy.reconcile(boolean) line: 90	
	JavaReconcilingStrategy.reconcile(IRegion) line: 157	
	JavaCompositeReconcilingStrategy(CompositeReconcilingStrategy).reconcile(IRegion) line: 94	
	JavaCompositeReconcilingStrategy.reconcile(IRegion) line: 107	
	JavaReconciler(MonoReconciler).process(DirtyRegion) line: 76	
	AbstractReconciler$BackgroundThread.run() line: 210	

@eric-milles
Copy link
Member

Thanks. You can also back up the stack and see what file and what part of this file has the issue. The visitMethodCallExpression is the last AST reference.

@mauromol
Copy link
Author

mauromol commented Mar 7, 2022

The call parameter is a MethodCallExpression whose toString is:

org.codehaus.groovy.ast.expr.MethodCallExpression@7cf7ba8b[object: org.codehaus.groovy.ast.expr.VariableExpression@43fae7fd[variable: this] method: org.codehaus.groovy.ast.expr.ConstantExpression@4ab647ed[cleanEmptyValues] arguments: org.codehaus.groovy.ast.expr.ArgumentListExpression@764980c7[org.codehaus.groovy.ast.expr.VariableExpression@629844fc[variable: value]]]

That method source is:

        void cleanEmptyValues(Object... beans) {
		if(beans)
			beans.each { bean ->
				if(bean)
					bean.properties.each { key, value ->
						if(value instanceof IdentifiableDto || value instanceof ModelObject)
							cleanEmptyValues(value)
						else if(value instanceof Iterable)
							value.each { cleanEmptyValues(it) }
						else if(value instanceof String && value.toString().trim() == '')
							bean[(String) key] = null
					}
			}
	}

@eric-milles
Copy link
Member

Can you try casting "it" to Iterable<?> or Iterable<Object> just to see if the NPE subsides?

@mauromol
Copy link
Author

mauromol commented Mar 7, 2022

Unfortunately, adding that cast doesn't make any difference. The exception is the same, as well as the involved MethodCallExpression.

@mauromol
Copy link
Author

mauromol commented Mar 7, 2022

I can make the problem go away if I change both recursive cleanEmptyValues calls so that an array/a collection is passed (please see [value] and [it] below):

	void cleanEmptyValues(Object... beans) {
		if(beans)
			beans.each { bean ->
				if(bean)
					bean.properties.each { key, value ->
						if(value instanceof IdentifiableDto || value instanceof ModelObject)
							cleanEmptyValues([value])
						else if(value instanceof Iterable)
							value.each { cleanEmptyValues([it]) }
						else if(value instanceof String && value.toString().trim() == '')
							bean[(String) key] = null
					}
			}
	}

@eric-milles
Copy link
Member

Sorry, I meant to say cast "value" since that is what was tested against Iterable: ((Iterable<Object>)value).each { ... }

@eric-milles eric-milles self-assigned this Mar 7, 2022
@eric-milles eric-milles added the bug label Mar 7, 2022
@eric-milles eric-milles added this to the v4.5.0 milestone Mar 7, 2022
@mauromol
Copy link
Author

mauromol commented Mar 7, 2022

I have to cast both value and it to Iterable<?> in order to make the problem go away. Casting just one or the other is not enough. Or, as I said, I can pass value and it within [...].

@eric-milles
Copy link
Member

eric-milles commented Mar 8, 2022

The issue starts because the extension method getProperties() returns the raw type Map. It shows itself a second time because Iterable is also a raw type in the instanceof expression. The NPE comes from the GROOVY-10067 backport code.

Two typecasts have been inserted below that should get rid of the raw-type funging:

void cleanEmptyValues(Object... beans) {
  beans?.each { bean ->
    if (bean) ((Map<String,Object>)bean.properties).each { key, value ->
      if (value instanceof IdentifiableDto || value instanceof ModelObject)
        cleanEmptyValues(value)
      else if (value instanceof Iterable)
        ((Iterable<Object>)value).each { cleanEmptyValues(it) }
      else if (value instanceof String && value.trim().isEmpty())
        bean[key] = null
    }
  }
}

https://issues.apache.org/jira/browse/GROOVY-10527
https://issues.apache.org/jira/browse/GROOVY-10528

@eric-milles eric-milles changed the title Compiler bug STC: NullPointerException for raw type guard followed by parameterized method call Mar 8, 2022
eric-milles added a commit that referenced this issue Mar 29, 2022
GROOVY-9968, GROOVY-10327, GROOVY-10528
@mauromol
Copy link
Author

mauromol commented Apr 5, 2022

I confirm this does not happen any more with 4.6.0.v202204021925-e2112.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants