Skip to content
This repository has been archived by the owner on Apr 21, 2023. It is now read-only.

AbstractClassMirror.findMember(EObject, String) fails when inner class is used in signature of member before #704

Closed
cdietrich opened this issue Mar 18, 2021 · 6 comments · Fixed by #715
Assignees
Milestone

Comments

@cdietrich
Copy link
Member

cdietrich commented Mar 18, 2021

AbstractClassMirror.findMember(EObject, String) fails when inner class is used in signature of member before
e.g. native boolean closeScope0(Scope scope, Scope.ScopedAccessError exception);
in ScopedMemoryAccess in Java 16

(happens e.g when running org.eclipse.xtext.xbase.tests.serializer.SerializerTest with Java 16

@cdietrich
Copy link
Member Author

cdietrich commented Mar 18, 2021

possible solution

	protected EObject findMember(EObject container, String fragment) {
		if (container instanceof JvmDeclaredType) {
			EList<JvmMember> members = ((JvmDeclaredType) container).getMembers();
			boolean isOp = fragment.indexOf('(') >= 0; // maybe we also have to check the position of $ relative to ()
			for (JvmMember member : members) {
				if (!isOp) {
					if (member instanceof JvmOperation) {
						continue;
					}
				}
				String name = member.getIdentifier();
				if (equal(fragment, name)) {
					return member;
				}
			}
			for (JvmMember member : members) {
				if (!isOp) {
					if (member instanceof JvmOperation) {
						continue;
					}
				}
				String name = member.getIdentifier();
				if (fragment.startsWith(name)) {
					EObject match = findMember(member, fragment);
					if (match != null)
						return match;
				}
			}
		}
		return null;
	}

@cdietrich
Copy link
Member Author

can be reproduced with Java 8/11 and

public class CachingReflectionTypeProviderTest extends ReflectionTypeProviderTest {
	
	@Test
	public void testCreateMirror_01a() {
		URI uri = URI.createURI("java:/Objects/testdata.ClientFor");
		IMirror mirror = getTypeProvider().createMirror(uri);
		TypeResource resource = (TypeResource) resourceSet.getResource(uri, true);
		assertNotNull(resource);
		assertTrue(resource.isLoaded());
		assertEquals(1, resource.getContents().size());
		for (JvmMember m : ((JvmDeclaredType)resource.getContents().get(0)).getMembers()) {
			if (m instanceof JvmField) {
				((JvmField) m).getType().getSimpleName();
			}
		}
	}
package testdata;

/**
 * @author cdietrich - Initial contribution and API
 */
public class ClientFor {
	
	
	public testdata.ScopedMemoryAccess.Scope.ScopedAccessError e;

}

package testdata;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author cdietrich - Initial contribution and API
 */
public class ScopedMemoryAccess {
	
	 private static String UNSAFE = "";

	    private static native Scope registerNatives();
	
	private ScopedMemoryAccess() {}

    private static final ScopedMemoryAccess theScopedMemoryAccess = new ScopedMemoryAccess();

    public static ScopedMemoryAccess getScopedMemoryAccess() {
        return theScopedMemoryAccess;
    }

	public boolean closeScope(Scope scope) {
		return closeScope0(scope, Scope.ScopedAccessError.INSTANCE);
	}

	native boolean closeScope0(Scope scope, Scope.ScopedAccessError exception);

	public interface Scope {
		final class ScopedAccessError {
			public static ScopedAccessError INSTANCE = new ScopedAccessError();
		}
	}
	
	@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
    @Retention(RetentionPolicy.RUNTIME)
    @interface Scoped { }
	
}

@cdietrich
Copy link
Member Author

cdietrich commented Mar 18, 2021

org.eclipse.xtext.common.types.access.reflect.CachingReflectionTypeFactory.createType(Class<?>) org.eclipse.xtext.common.types.access.impl.CachingDeclaredTypeFactory and others call
EcoreUtil2.cloneWithProxies(cachedResult);

which wont copy identifier as it is derived.
maybe

EcoreUtil.Copier copier = new EcoreUtil.Copier(false) {
	 @Override
	public EObject copy(EObject eObject) {
		 EObject copy = super.copy(eObject);
		 if (copy instanceof JvmMember) {
			 copyAttribute(TypesPackage.Literals.JVM_MEMBER__IDENTIFIER, eObject, copy);
		 }
		 return copy;
	}
};
JvmDeclaredType copy = (JvmDeclaredType) copier.copy(cachedResult);
copier.copyReferences();
return copy;

@cdietrich
Copy link
Member Author

cdietrich commented May 17, 2021

alternative would be to change something in the metamodel.
(Make JvmMember.identifier non derived and changeable)
am not sure if this would have side effects
(first experiments with xtext-extras only look promising)

am not sure about serialization/transientvalueservice

cdietrich added a commit that referenced this issue Jul 19, 2021
cdietrich added a commit that referenced this issue Aug 9, 2021
@cdietrich
Copy link
Member Author

@cdietrich cdietrich self-assigned this Aug 9, 2021
@cdietrich cdietrich added this to the Release_2.26 milestone Aug 9, 2021
cdietrich added a commit that referenced this issue Aug 9, 2021
cdietrich added a commit that referenced this issue Aug 16, 2021
[#704] mark JvmMember.identifier non derived + settable
@cdietrich
Copy link
Member Author

Fixed in 2.26

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

Successfully merging a pull request may close this issue.

1 participant