Skip to content

Commit

Permalink
always set mapped type as anonymous for anonymous Xtend classes
Browse files Browse the repository at this point in the history
And customize code generation
  • Loading branch information
LorenzoBettini committed Dec 30, 2023
1 parent 944efb0 commit 055d211
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class JvmModelTests extends AbstractXtendTestCase {
assertTrue(anonymous.final)
assertFalse(anonymous.static)
assertTrue(anonymous.local)
assertFalse(anonymous.anonymous) // additional member -> named local class
assertTrue(anonymous.anonymous)
assertEquals(JvmVisibility.DEFAULT, anonymous.visibility)
assertEquals(2, anonymous.superTypes.size)
assertEquals('java.lang.Runnable', anonymous.superTypes.last.qualifiedName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ public void testAnonymousClass_01() {
Assert.assertTrue(anonymous.isFinal());
Assert.assertFalse(anonymous.isStatic());
Assert.assertTrue(anonymous.isLocal());
Assert.assertFalse(anonymous.isAnonymous());
Assert.assertTrue(anonymous.isAnonymous());
Assert.assertEquals(JvmVisibility.DEFAULT, anonymous.getVisibility());
Assert.assertEquals(2, anonymous.getSuperTypes().size());
Assert.assertEquals("java.lang.Runnable", IterableExtensions.<JvmTypeReference>last(anonymous.getSuperTypes()).getQualifiedName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
import org.eclipse.xtend.core.xtend.RichStringForLoop;
import org.eclipse.xtend.core.xtend.RichStringIf;
import org.eclipse.xtend.core.xtend.RichStringLiteral;
import org.eclipse.xtend.core.xtend.XtendField;
import org.eclipse.xtend.core.xtend.XtendFormalParameter;
import org.eclipse.xtend.core.xtend.XtendFunction;
import org.eclipse.xtend.core.xtend.XtendMember;
import org.eclipse.xtend.core.xtend.XtendPackage;
import org.eclipse.xtend.core.xtend.XtendTypeDeclaration;
import org.eclipse.xtend.core.xtend.XtendVariableDeclaration;
Expand Down Expand Up @@ -571,6 +574,8 @@ public void exec(ITreeAppendable appendable) {
protected boolean internalCanCompileToJavaExpression(XExpression expression, ITreeAppendable appendable) {
if(expression instanceof AnonymousClass) {
AnonymousClass anonymousClass = (AnonymousClass) expression;
if (!canBeCompiledAsJavaAnonymousClass(anonymousClass))
return false;
JvmGenericType inferredLocalClass = associations.getInferredType(anonymousClass);
return inferredLocalClass.isAnonymous();
} else
Expand Down Expand Up @@ -655,5 +660,13 @@ protected boolean needSyntheticSelfVariable(XClosure closure, LightweightTypeRef
}
return false;
}


protected boolean canBeCompiledAsJavaAnonymousClass(AnonymousClass anonymousClass) {
for(XtendMember member: anonymousClass.getMembers()) {
if(member instanceof XtendField ||
(member instanceof XtendFunction && !((XtendFunction) member).isOverride()))
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ import org.eclipse.xtext.xbase.compiler.output.ITreeAppendable
import org.eclipse.xtext.xbase.compiler.output.SharedAppendableState
import org.eclipse.xtext.xbase.typesystem.IBatchTypeResolver
import org.eclipse.xtext.xbase.typesystem.references.ITypeReferenceOwner
import org.eclipse.xtend.core.xtend.XtendField
import org.eclipse.xtext.common.types.impl.JvmGenericTypeImplCustom

/**
* @author Sven Efftinge - Initial contribution and API
Expand Down Expand Up @@ -164,9 +166,13 @@ class XtendGenerator extends JvmModelGenerator implements IGenerator2 {
}

def compileLocalTypeStubs(JvmFeature feature, ITreeAppendable appendable, GeneratorConfig config) {
feature.localClasses.filter[ !anonymous ].forEach[
appendable.newLine
feature.localClasses.forEach[
val anonymousClass = sourceElements.head as AnonymousClass
if (anonymousClass.canBeCompiledAsJavaAnonymousClass) {
return
}
(it as JvmGenericTypeImplCustom).basicSetAnonymous(false)

This comment has been minimized.

Copy link
@szarnekow

szarnekow Dec 30, 2023

This is not an option. The model is not supposed to be modified by the compiler. Otherwise validation results are no longer trustworthy since introduces a semantic dependency back from the code generator into the model.

This comment has been minimized.

Copy link
@LorenzoBettini

LorenzoBettini Dec 31, 2023

Author Owner

@szarnekow I thought this could be acceptable since it's an "innocent" change without triggering notifications, but of course, I see your point :)

If you don't mind, I'd like to have another try without changing the model. While working on this I had the "pleasure" to debug the compilation process and maybe I know where to hook ;)

Another reason I think moving the decision to the compilation process makes sense is that it is indeed a compilation strategy, which also depends on the target Java version.

For example, in Java 10, this

def m() {
  val e = new Exception("") {
	int i = 0;
  }
  e.i = 3
}

could be compiled into the valid Java code relying on Java 10 local variable inference:

public void m() {
	final var e = new Exception("") {
		int i = 0;
	};
	e.i = 3;
}

Of course, this holds only for local variables: not for fields and in other cases where the Xtend anonymous class uses this. I'm not saying to switch to this compilation strategy. At least, not now. But just in case :)

appendable.newLine
val childAppendable = appendable.trace(anonymousClass)
childAppendable.append('abstract class ')
childAppendable.traceSignificant(anonymousClass).append(simpleName)
Expand Down Expand Up @@ -386,5 +392,13 @@ class XtendGenerator extends JvmModelGenerator implements IGenerator2 {
}

}


def private boolean canBeCompiledAsJavaAnonymousClass(AnonymousClass anonymousClass) {
for(XtendMember member: anonymousClass.getMembers()) {
if(member instanceof XtendField ||
(member instanceof XtendFunction && !(member as XtendFunction).isOverride()))
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ public void inferLocalClass(
JvmFeature container) {
final JvmGenericType inferredType = typesFactory.createJvmGenericType();
inferredType.setSimpleName(localClassName);
inferredType.setAnonymous(!hasAdditionalMembers(anonymousClass));
inferredType.setAnonymous(true);
inferredType.setFinal(true);
inferredType.setVisibility(JvmVisibility.DEFAULT);
inferredType.getSuperTypes().add(jvmTypesBuilder.inferredType(anonymousClass));
Expand All @@ -873,14 +873,14 @@ public void inferLocalClass(
associator.associateLogicalContainer(actualParameter, container);
}
}

protected boolean hasAdditionalMembers(AnonymousClass anonymousClass) {
for(XtendMember member: anonymousClass.getMembers()) {
if(member instanceof XtendField ||
(member instanceof XtendFunction && !((XtendFunction) member).isOverride()))
return true;
}
return false;
}
//
// protected boolean hasAdditionalMembers(AnonymousClass anonymousClass) {
// for(XtendMember member: anonymousClass.getMembers()) {
// if(member instanceof XtendField ||
// (member instanceof XtendFunction && !((XtendFunction) member).isOverride()))
// return true;
// }
// return false;
// }

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
Expand All @@ -25,6 +26,7 @@
import org.eclipse.xtend.core.macro.CodeGenerationContextImpl;
import org.eclipse.xtend.core.xtend.AnonymousClass;
import org.eclipse.xtend.core.xtend.XtendAnnotationTarget;
import org.eclipse.xtend.core.xtend.XtendField;
import org.eclipse.xtend.core.xtend.XtendFunction;
import org.eclipse.xtend.core.xtend.XtendMember;
import org.eclipse.xtend.core.xtend.XtendTypeDeclaration;
Expand All @@ -44,6 +46,7 @@
import org.eclipse.xtext.common.types.JvmTypeParameterDeclarator;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.JvmVisibility;
import org.eclipse.xtext.common.types.impl.JvmGenericTypeImplCustom;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.generator.IFileSystemAccess2;
import org.eclipse.xtext.generator.IGenerator2;
Expand Down Expand Up @@ -251,14 +254,15 @@ public String reassignThisType(final ITreeAppendable b, final JvmDeclaredType de
}

public void compileLocalTypeStubs(final JvmFeature feature, final ITreeAppendable appendable, final GeneratorConfig config) {
final Function1<JvmGenericType, Boolean> _function = (JvmGenericType it) -> {
boolean _isAnonymous = it.isAnonymous();
return Boolean.valueOf((!_isAnonymous));
};
final Consumer<JvmGenericType> _function_1 = (JvmGenericType it) -> {
appendable.newLine();
final Consumer<JvmGenericType> _function = (JvmGenericType it) -> {
EObject _head = IterableExtensions.<EObject>head(this.getSourceElements(it));
final AnonymousClass anonymousClass = ((AnonymousClass) _head);
boolean _canBeCompiledAsJavaAnonymousClass = this.canBeCompiledAsJavaAnonymousClass(anonymousClass);
if (_canBeCompiledAsJavaAnonymousClass) {
return;
}
((JvmGenericTypeImplCustom) it).basicSetAnonymous(false);
appendable.newLine();
final ITreeAppendable childAppendable = appendable.trace(anonymousClass);
childAppendable.append("abstract class ");
this._treeAppendableUtil.traceSignificant(childAppendable, anonymousClass).append(it.getSimpleName());
Expand All @@ -277,10 +281,10 @@ public void compileLocalTypeStubs(final JvmFeature feature, final ITreeAppendabl
childAppendable.newLine().append("final ").append(it.getSimpleName()).append(" ").append(thisName).append(" = this;");
childAppendable.blankLine();
}
final Procedure1<LoopParams> _function_2 = (LoopParams it_1) -> {
final Procedure1<LoopParams> _function_1 = (LoopParams it_1) -> {
it_1.setSeparator(this.memberSeparator());
};
final Procedure1<JvmMember> _function_3 = (JvmMember it_1) -> {
final Procedure1<JvmMember> _function_2 = (JvmMember it_1) -> {
final ITreeAppendable memberAppendable = this._treeAppendableUtil.traceWithComments(childAppendable, it_1);
memberAppendable.openScope();
if ((it_1 instanceof JvmOperation)) {
Expand Down Expand Up @@ -345,11 +349,11 @@ public void compileLocalTypeStubs(final JvmFeature feature, final ITreeAppendabl
}
memberAppendable.closeScope();
};
this._loopExtensions.<JvmMember>forEach(childAppendable, this.getAddedDeclarations(it, anonymousClass), _function_2, _function_3);
this._loopExtensions.<JvmMember>forEach(childAppendable, this.getAddedDeclarations(it, anonymousClass), _function_1, _function_2);
childAppendable.decreaseIndentation().newLine().append("}");
appendable.blankLine();
};
IterableExtensions.<JvmGenericType>filter(feature.getLocalClasses(), _function).forEach(_function_1);
feature.getLocalClasses().forEach(_function);
}

private ITreeAppendable generateJavaConstant(final Object value, final ITreeAppendable appendable) {
Expand Down Expand Up @@ -574,4 +578,14 @@ public ITreeAppendable generateMembersInBody(final JvmDeclaredType it, final ITr
}
return _xifexpression;
}

private boolean canBeCompiledAsJavaAnonymousClass(final AnonymousClass anonymousClass) {
EList<XtendMember> _members = anonymousClass.getMembers();
for (final XtendMember member : _members) {
if (((member instanceof XtendField) || ((member instanceof XtendFunction) && (!((XtendFunction) member).isOverride())))) {
return false;
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,11 @@ public boolean isAnonymous() {
checkPendingInitialization();
return super.isAnonymous();
}

/**
* Without triggering notifications
*/
public void basicSetAnonymous(boolean anonymous) {
this.anonymous = anonymous;
}
}

0 comments on commit 055d211

Please sign in to comment.