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

[Bug]: Outer-most class of nested inner class not marked as implicit #5428

Closed
Luro02 opened this issue Sep 3, 2023 · 1 comment · Fixed by #5425
Closed

[Bug]: Outer-most class of nested inner class not marked as implicit #5428

Luro02 opened this issue Sep 3, 2023 · 1 comment · Fixed by #5425
Labels

Comments

@Luro02
Copy link
Contributor

Luro02 commented Sep 3, 2023

Describe the bug

Given

class Test {
  static class A { static class B {} }

  A.B myVariable;
}

For some reason spoon adds the Test. to the type and does not mark it implicit:

Test.A.B myVariable;
^^^^ this is not implicit

What is the use-case?

I want to check if types are (unnecessarily) qualified in the source code. If someone writes Test.A.B, then I want to suggest replacing it with A.B, because the Test. is redundant.

Workaround?

If you do not care about arrays, then you can simply check if !type.getPosition().isValid().

I care about arrays, because I do want to detect Test.A.B[] as well, which makes this a bit more complicated.

My solution is to check if type.getPosition().isValid() || type.getParent(CtArrayTypeReference.class) != null. This seems to work mostly, but I think it will result in problems in the future...


@I-Al-Istannen has spent some time looking into this issue, but it seems like something difficult to fix.

Source code you are trying to analyze/transform

class Test {
    static class A { static class B {} }

    A.B variable = new A.B();
}

Source code for your Spoon processing

import org.junit.jupiter.api.Test;
import spoon.Launcher;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtField;
import spoon.reflect.reference.CtTypeReference;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class TestSpoon {
    @Test
    void testImplicitOuterClass() {
        CtClass<?> ctClass = Launcher.parseClass(
            "class Test {\n" +
            "    static class A { static class B {} }\n" +
            "\n" +
            "    A.B variable = new A.B();\n" +
            "}\n"
        );

        CtField<?> ctField = ctClass.getField("variable");
        CtTypeReference<?> fieldType = ctField.getType();

        assertEquals("B", fieldType.getSimpleName());

        CtTypeReference<?> a = fieldType.getDeclaringType();
        assertEquals("A", a.getSimpleName());

        CtTypeReference<?> test = a.getDeclaringType();
        assertEquals("Test", test.getSimpleName());
        assertTrue(test.isImplicit(), "`Test` class access should be implicit, because it is not in the source code");
    }
}

Actual output

org.opentest4j.AssertionFailedError: `Test` class access should be implicit, because it is not in the source code ==> 
Expected :true
Actual   :false
<Click to see difference>


	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
	at org.junit.jupiter.api.Assertions.assertTrue(Assertions.java:211)
	at org.example.playground.TestSpoon.testImplicitOuterClass(TestSpoon.java:34)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)

Expected output

No response

Spoon Version

10.4.0

JVM Version

openjdk version "17.0.1" 2021-10-19 OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12) OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing)

What operating system are you using?

Windows 10

@Luro02 Luro02 added the bug label Sep 3, 2023
@Luro02
Copy link
Contributor Author

Luro02 commented Sep 3, 2023

See #5425

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

Successfully merging a pull request may close this issue.

1 participant