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

Incorrect type variable resolution for signatures #98

Closed
pbull-oracle opened this issue Dec 22, 2020 · 3 comments · Fixed by #202
Closed

Incorrect type variable resolution for signatures #98

pbull-oracle opened this issue Dec 22, 2020 · 3 comments · Fixed by #202
Assignees
Milestone

Comments

@pbull-oracle
Copy link

When indexing multiple classes, during class signature parsing/resolution, the wrong bounds can be resolved for a type variable, because the indexer reuses the signature parser and the signature parser reuses resolved type variables between consecutive calls to the index method.

Reproduce with:

package com.example;
public interface WithMethodSignature {
    public <E extends Runnable> E myMethod(E arg);
}
package com.example;
import java.util.Iterator;
public interface WithClassSignature<E extends Exception> extends Iterator<E /*what's the bound?*/ > {
}
package com.example;
import java.io.InputStream;
import org.assertj.core.api.Assertions;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
import org.junit.jupiter.api.Test;
public class JandexTest {
    @Test //passes
    public void classSignatureOnly()
            throws Exception {
        verifyIndex(createIndex(WithClassSignature.class), WithClassSignature.class);
    }
    @Test //passes
    public void classSignatureBeforeMethodSignature()
            throws Exception {
        verifyIndex(createIndex(WithClassSignature.class, WithMethodSignature.class), WithClassSignature.class);
    }
    @Test //fails
    public void classSignatureAfterMethodSignature()
            throws Exception {
        verifyIndex(createIndex(WithMethodSignature.class, WithClassSignature.class), WithClassSignature.class);
    }
    private Index createIndex(Class<?>... types)
            throws Exception {
        Indexer indexer = new Indexer();
        for (Class<?> type : types) { //order matters
            String classNameAsResource = type.getName().replace('.', '/') + ".class";
            try (InputStream fis = type.getClassLoader().getResourceAsStream(classNameAsResource);) {
                indexer.index(fis);
            }
        }
        Index index = indexer.complete();
        return index;
    }
    private void verifyIndex(Index index, Class<?> generic) {
        DotName bound = DotName.createSimple(((Class<?>) generic.getTypeParameters()[0].getBounds()[0]).getName());
        ClassInfo indexedGeneric = index.getClassByName(DotName.createSimple(generic.getName()));
        DotName indexedInterfaceBound = indexedGeneric.interfaceTypes().get(0).asParameterizedType().arguments().get(0).asTypeVariable()
                .bounds().get(0).asClassType().name();
        Assertions.assertThat(indexedInterfaceBound).isEqualTo(bound);
    }
}
@n1hility
Copy link
Contributor

Thanks for the report

@Ladicek
Copy link
Contributor

Ladicek commented May 16, 2022

Fix is a single line of code. The signature parser forgets previously encountered element-level type parameters when parsing a new element, and previously encountered class-level type parameters when parsing a new class. It doesn't forget previously encountered element-level type parameters when parsing a new class, which it should.

@Ladicek
Copy link
Contributor

Ladicek commented May 16, 2022

Done in #202.

@Ladicek Ladicek closed this as completed May 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants