use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol in project ceylon by eclipse.
the class JavacClass method getEnclosingMethod.
@Override
public MethodMirror getEnclosingMethod() {
if (!enclosingMethodSet) {
Symbol encl = classSymbol.getEnclosingElement();
if (encl != null && encl instanceof MethodSymbol) {
// it's a method, it must be in a Class
ClassSymbol enclosingClass = (ClassSymbol) encl.getEnclosingElement();
JavacClass enclosingClassMirror = new JavacClass(enclosingClass);
enclosingMethod = new JavacMethod(enclosingClassMirror, (MethodSymbol) encl);
}
enclosingMethodSet = true;
}
return enclosingMethod;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol in project ceylon by eclipse.
the class LambdaToMethod method makeIndyCall.
/**
* Generate an indy method call with given name, type and static bootstrap
* arguments types
*/
private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName, List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs, Name methName) {
int prevPos = make.pos;
try {
make.at(pos);
List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType, syms.stringType, syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site, bsmName, bsm_staticArgs, List.<Type>nil());
DynamicMethodSymbol dynSym = new DynamicMethodSymbol(methName, syms.noSymbol, bsm.isStatic() ? ClassFile.REF_invokeStatic : ClassFile.REF_invokeVirtual, (MethodSymbol) bsm, indyType, staticArgs.toArray());
JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
qualifier.sym = dynSym;
qualifier.type = indyType.getReturnType();
JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs);
proxyCall.type = indyType.getReturnType();
return proxyCall;
} finally {
make.at(prevPos);
}
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol in project ceylon by eclipse.
the class LambdaToMethod method visitLambda.
/**
* Translate a lambda into a method to be inserted into the class.
* Then replace the lambda site with an invokedynamic call of to lambda
* meta-factory, which will use the lambda method.
* @param tree
*/
@Override
public void visitLambda(JCLambda tree) {
LambdaAnalyzerPreprocessor.LambdaTranslationContext localContext = (LambdaAnalyzerPreprocessor.LambdaTranslationContext) context;
MethodSymbol sym = localContext.translatedSym;
MethodType lambdaType = (MethodType) sym.type;
{
Symbol owner = localContext.owner;
ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) {
if (tc.position.onLambda == tree) {
lambdaTypeAnnos.append(tc);
} else {
ownerTypeAnnos.append(tc);
}
}
if (lambdaTypeAnnos.nonEmpty()) {
owner.setTypeAttributes(ownerTypeAnnos.toList());
sym.setTypeAttributes(lambdaTypeAnnos.toList());
}
}
// create the method declaration hoisting the lambda body
JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field), sym.name, make.QualIdent(lambdaType.getReturnType().tsym), List.<JCTypeParameter>nil(), localContext.syntheticParams, lambdaType.getThrownTypes() == null ? List.<JCExpression>nil() : make.Types(lambdaType.getThrownTypes()), null, null);
lambdaDecl.sym = sym;
lambdaDecl.type = lambdaType;
// translate lambda body
// As the lambda body is translated, all references to lambda locals,
// captured variables, enclosing members are adjusted accordingly
// to refer to the static method parameters (rather than i.e. acessing to
// captured members directly).
lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
// Add the method to the list of methods to be added to this class.
kInfo.addMethod(lambdaDecl);
// now that we have generated a method for the lambda expression,
// we can translate the lambda into a method reference pointing to the newly
// created method.
//
// Note that we need to adjust the method handle so that it will match the
// signature of the SAM descriptor - this means that the method reference
// should be added the following synthetic arguments:
//
// * the "this" argument if it is an instance method
// * enclosing locals captured by the lambda expression
ListBuffer<JCExpression> syntheticInits = new ListBuffer<>();
if (localContext.methodReferenceReceiver != null) {
syntheticInits.append(localContext.methodReferenceReceiver);
} else if (!sym.isStatic()) {
syntheticInits.append(makeThis(sym.owner.enclClass().asType(), localContext.owner.enclClass()));
}
// add captured locals
for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
if (fv != localContext.self) {
JCTree captured_local = make.Ident(fv).setType(fv.type);
syntheticInits.append((JCExpression) captured_local);
}
}
// then, determine the arguments to the indy call
List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
// build a sam instance using an indy call to the meta-factory
int refKind = referenceKind(sym);
// convert to an invokedynamic call
result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol in project ceylon by eclipse.
the class CeylonModelLoader method isFunctionalInterface.
@Override
protected String isFunctionalInterface(ClassMirror klass) {
Type type = ((JavacClass) klass).classSymbol.type;
try {
Type descriptorType = types.findDescriptorType(type);
if (descriptorType == null)
return null;
// Let's be honest I've no idea what this means, but it happens and Javac seems to refuse it too
if (descriptorType.hasTag(TypeTag.FORALL))
return null;
MethodSymbol descriptorSymbol = (MethodSymbol) types.findDescriptorSymbol(type.tsym);
if (descriptorSymbol != null) {
// make sure we don't treat ignored shit like impl accessors as SAM
if (isIgnored(descriptorSymbol))
return null;
String name = descriptorSymbol.getSimpleName().toString();
if (isGetter(descriptorSymbol)) {
name = NamingBase.getJavaAttributeName(name);
}
return name;
}
return null;
} catch (Symbol.CompletionFailure err) {
// bad luck
return null;
} catch (FunctionDescriptorLookupError err) {
return null;
}
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol in project ceylon by eclipse.
the class CeylonModelLoader method isFunctionalInterfaceType.
@Override
protected boolean isFunctionalInterfaceType(TypeMirror typeMirror) {
if (typeMirror.getKind() != TypeKind.DECLARED)
return false;
// FIXME: possibly apply other optimisations to lighten the lookup cost? see what javac does
Type type = ((JavacType) typeMirror).type;
try {
Type descriptorType = types.findDescriptorType(type);
// Let's be honest I've no idea what this means, but it happens and Javac seems to refuse it too
if (descriptorType.hasTag(TypeTag.FORALL))
return false;
MethodType methodDescriptorType = (MethodType) descriptorType;
MethodSymbol methodSymbol = (MethodSymbol) types.findDescriptorSymbol(type.tsym);
// make sure we can load them
methodDescriptorType.complete();
methodSymbol.complete();
return true;
} catch (Symbol.CompletionFailure err) {
// bad luck
return false;
} catch (FunctionDescriptorLookupError err) {
return false;
}
}
Aggregations