use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class MethodOrValueReferenceVisitor method isCapturableMplParameter.
/**
* Because methods with MPL use nested anonymous AbstractCallables
* if the declaration is a parameter in all but the last parameter list
* it should be captured.
*/
private boolean isCapturableMplParameter(Declaration d) {
if (!(d instanceof FunctionOrValue)) {
return false;
}
org.eclipse.ceylon.model.typechecker.model.Parameter param = ((FunctionOrValue) d).getInitializerParameter();
if (param == null) {
return false;
}
Declaration paramDecl = param.getDeclaration();
if (paramDecl instanceof Functional) {
List<org.eclipse.ceylon.model.typechecker.model.ParameterList> parameterLists = ((Functional) paramDecl).getParameterLists();
for (int i = 0; i < parameterLists.size() - 1; i++) {
if (parameterLists.get(i).getParameters().contains(param)) {
return true;
}
}
}
return false;
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class AbstractModelLoader method addConstructorMethorOrValue.
protected FunctionOrValue addConstructorMethorOrValue(Class klass, ClassMirror classMirror, MethodMirror ctor, Constructor constructor, boolean isNativeHeader) {
boolean isCeylon = classMirror.getAnnotation(CEYLON_CEYLON_ANNOTATION) != null;
if (ctor.getAnnotation(CEYLON_ENUMERATED_ANNOTATION) != null) {
klass.setEnumerated(true);
Value v = new Value();
v.setName(constructor.getName());
v.setType(constructor.getType());
v.setContainer(klass);
v.setScope(klass);
v.setUnit(klass.getUnit());
v.setVisibleScope(constructor.getVisibleScope());
// read annotations from the getter method
setNonLazyDeclarationProperties(v, ctor, ctor, classMirror, isCeylon);
setAnnotations(v, ctor, isNativeHeader);
klass.addMember(v);
return v;
} else {
setParameters(constructor, classMirror, ctor, true, klass, false);
klass.setConstructors(true);
Function f = new Function();
f.setName(constructor.getName());
f.setType(constructor.getType());
f.addParameterList(constructor.getParameterList());
f.setContainer(klass);
f.setScope(klass);
f.setUnit(klass.getUnit());
f.setVisibleScope(constructor.getVisibleScope());
// read annotations from the constructor
setNonLazyDeclarationProperties(f, ctor, ctor, classMirror, isCeylon);
setAnnotations(f, ctor, isNativeHeader);
klass.addMember(f);
return f;
}
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class AbstractModelLoader method setParameters.
private void setParameters(Functional decl, ClassMirror classMirror, MethodMirror methodMirror, boolean isCeylon, Scope container, boolean isCoercedMethod) {
ParameterList parameters = new ParameterList();
parameters.setNamedParametersSupported(isCeylon);
decl.addParameterList(parameters);
int parameterCount = methodMirror.getParameters().size();
int parameterIndex = 0;
for (VariableMirror paramMirror : methodMirror.getParameters()) {
// ignore some parameters
if (paramMirror.getAnnotation(CEYLON_IGNORE_ANNOTATION) != null)
continue;
boolean isLastParameter = parameterIndex == parameterCount - 1;
boolean isVariadic = isLastParameter && methodMirror.isVariadic();
String paramName = getAnnotationStringValue(paramMirror, CEYLON_NAME_ANNOTATION);
// use whatever param name we find as default
if (paramName == null)
paramName = paramMirror.getName();
Parameter parameter = new Parameter();
parameter.setName(paramName);
TypeMirror typeMirror = paramMirror.getType();
Scope scope = (Scope) decl;
Module module = ModelUtil.getModuleContainer(scope);
Type type;
boolean coercedParameter = false;
if (isVariadic) {
// possibly make it optional
TypeMirror variadicType = typeMirror.getComponentType();
// we pretend it's toplevel because we want to get magic string conversion for variadic methods
if (isCoercedMethod && isCoercedType(variadicType)) {
type = applyTypeCoercion(variadicType, paramMirror, methodMirror, paramName, (Declaration) decl, module, scope);
coercedParameter = true;
} else {
type = obtainType(module, variadicType, scope, TypeLocation.TOPLEVEL);
}
if (!isCeylon) {
// Java parameters are all optional unless primitives or annotated as such
if (getUncheckedNullPolicy(isCeylon, variadicType, paramMirror) != NullStatus.NonOptional) {
type = makeOptionalTypePreserveUnderlyingType(type, module);
}
}
// turn it into a Sequential<T>
type = typeFactory.getSequentialType(type);
} else {
if (isCoercedMethod && isCoercedType(typeMirror)) {
type = applyTypeCoercion(typeMirror, paramMirror, methodMirror, paramName, (Declaration) decl, module, scope);
coercedParameter = true;
} else {
type = obtainType(typeMirror, paramMirror, scope, module, "parameter '" + paramName + "' of method '" + methodMirror.getName() + "'", (Declaration) decl);
}
if (!isCeylon) {
// Java parameters are all optional unless primitives or annotated as such
if (getUncheckedNullPolicy(isCeylon, typeMirror, paramMirror) != NullStatus.NonOptional) {
type = makeOptionalTypePreserveUnderlyingType(type, module);
}
}
}
if (type.isCached()) {
type = type.clone();
}
if (!type.isRaw())
type.setRaw(isRaw(ModelUtil.getModuleContainer(container), typeMirror));
FunctionOrValue value = null;
boolean lookedup = false;
if (isCeylon && decl instanceof Class) {
// For a functional parameter to a class, we can just lookup the member
value = (FunctionOrValue) ((Class) decl).getDirectMember(paramName, null, false);
lookedup = value != null;
}
if (value == null) {
// So either decl is not a Class,
// or the method or value member of decl is not shared
AnnotationMirror functionalParameterAnnotation = paramMirror.getAnnotation(CEYLON_FUNCTIONAL_PARAMETER_ANNOTATION);
if (functionalParameterAnnotation != null) {
// A functional parameter to a method
Function method = loadFunctionalParameter((Declaration) decl, paramName, type, (String) functionalParameterAnnotation.getValue());
value = method;
parameter.setDeclaredAnything(method.isDeclaredVoid());
} else if (coercedParameter && isFunctionCercion(typeMirror)) {
Function method = loadFunctionCoercionParameter((Declaration) decl, paramName, typeMirror, module, scope);
value = method;
parameter.setDeclaredAnything(method.isDeclaredVoid());
} else {
// A value parameter to a method
value = isCeylon ? new Value() : new JavaParameterValue();
value.setType(type);
}
value.setContainer(scope);
value.setScope(scope);
ModelUtil.setVisibleScope(value);
value.setUnit(scope.getUnit());
value.setName(paramName);
} else {
// the method return type, so we try to detect this and fix it
if (value instanceof Function && isCeylon1Dot1(classMirror)) {
Type newType = getSimpleCallableReturnType(value.getType());
if (!newType.isUnknown())
value.setType(newType);
}
}
value.setInitializerParameter(parameter);
value.setCoercionPoint(coercedParameter);
parameter.setModel(value);
if (paramMirror.getAnnotation(CEYLON_SEQUENCED_ANNOTATION) != null || isVariadic)
parameter.setSequenced(true);
if (paramMirror.getAnnotation(CEYLON_DEFAULTED_ANNOTATION) != null)
parameter.setDefaulted(true);
if (parameter.isSequenced() && // FIXME: store info in Sequenced
"ceylon.language.Sequence".equals(paramMirror.getType().getQualifiedName())) {
parameter.setAtLeastOne(true);
}
// unboxed is already set if it's a real method
if (!lookedup) {
// if it's variadic, consider the array element type (T[] == T...) for boxing rules
markUnboxed(value, null, isVariadic ? paramMirror.getType().getComponentType() : paramMirror.getType());
markSmall(value, paramMirror.getType());
}
parameter.setDeclaration((Declaration) decl);
value.setDeprecated(value.isDeprecated() || isDeprecated(paramMirror));
setAnnotations(value, paramMirror, false);
parameters.getParameters().add(parameter);
if (!lookedup) {
parameter.getDeclaration().getMembers().add(parameter.getModel());
}
parameterIndex++;
}
if (decl instanceof Function) {
// Multiple parameter lists
AnnotationMirror functionalParameterAnnotation = methodMirror.getAnnotation(CEYLON_FUNCTIONAL_PARAMETER_ANNOTATION);
if (functionalParameterAnnotation != null) {
parameterNameParser.parseMpl((String) functionalParameterAnnotation.getValue(), ((Function) decl).getType().getFullType(), (Function) decl);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class JvmBackendUtil method getTopmostRefinedDeclaration.
public static Declaration getTopmostRefinedDeclaration(Declaration decl, Map<Function, Function> methodOverrides) {
if (decl instanceof FunctionOrValue && ((FunctionOrValue) decl).isParameter() && decl.getContainer() instanceof Class) {
// Parameters in a refined class are not considered refinements themselves
// We have in find the refined attribute
Class c = (Class) decl.getContainer();
boolean isAlias = c.isAlias();
boolean isActual = c.isActual();
// boxing and stuff
if (isAlias || isActual) {
Functional ctor = null;
int index = c.getParameterList().getParameters().indexOf(findParamForDecl(((TypedDeclaration) decl)));
// Note(Stef): not entirely sure about that one, what about aliases of actual classes?
while ((isAlias && c.isAlias()) || (isActual && c.isActual())) {
ctor = (isAlias && c.isAlias()) ? (Functional) ((ClassAlias) c).getConstructor() : c;
Type et = c.getExtendedType();
c = et != null && et.isClass() ? (Class) et.getDeclaration() : null;
// handle compile errors
if (c == null)
return null;
}
if (isActual) {
ctor = c;
}
// be safe
if (ctor == null || ctor.getParameterLists() == null || ctor.getParameterLists().isEmpty() || ctor.getFirstParameterList() == null || ctor.getFirstParameterList().getParameters() == null || ctor.getFirstParameterList().getParameters().size() <= index)
return null;
decl = ctor.getFirstParameterList().getParameters().get(index).getModel();
}
if (decl.isShared()) {
Declaration refinedDecl = c.getRefinedMember(decl.getName(), getSignature(decl), isVariadic(decl));
if (refinedDecl != null && !ModelUtil.equal(refinedDecl, decl)) {
return getTopmostRefinedDeclaration(refinedDecl, methodOverrides);
}
}
return decl;
} else if (decl instanceof FunctionOrValue && // a parameter
((FunctionOrValue) decl).isParameter() && (// that's not parameter of a functional parameter
(decl.getContainer() instanceof Function && !(((Function) decl.getContainer()).isParameter())) || // or is a parameter in a specification
decl.getContainer() instanceof Specification || (decl.getContainer() instanceof Function && ((Function) decl.getContainer()).isParameter() && createMethod((Function) decl.getContainer())))) {
// or is a class functional parameter
// Parameters in a refined method are not considered refinements themselves
// so we have to look up the corresponding parameter in the container's refined declaration
Functional func = (Functional) getParameterized((FunctionOrValue) decl);
if (func == null)
return decl;
Declaration kk = getTopmostRefinedDeclaration((Declaration) func, methodOverrides);
// error recovery
if (kk instanceof Functional == false)
return decl;
Functional refinedFunc = (Functional) kk;
// shortcut if the functional doesn't override anything
if (ModelUtil.equal((Declaration) refinedFunc, (Declaration) func)) {
return decl;
}
if (func.getParameterLists().size() != refinedFunc.getParameterLists().size()) {
// invalid input
return decl;
}
for (int ii = 0; ii < func.getParameterLists().size(); ii++) {
if (func.getParameterLists().get(ii).getParameters().size() != refinedFunc.getParameterLists().get(ii).getParameters().size()) {
// invalid input
return decl;
}
// find the index of the parameter in the declaration
int index = 0;
for (Parameter px : func.getParameterLists().get(ii).getParameters()) {
if (px.getModel() == null || px.getModel().equals(decl)) {
// And return the corresponding parameter from the refined declaration
return refinedFunc.getParameterLists().get(ii).getParameters().get(index).getModel();
}
index++;
}
continue;
}
} else if (methodOverrides != null && decl instanceof Function && ModelUtil.equal(decl.getRefinedDeclaration(), decl) && decl.getContainer() instanceof Specification && ((Specification) decl.getContainer()).getDeclaration() instanceof Function && ((Function) ((Specification) decl.getContainer()).getDeclaration()).isShortcutRefinement() && // hash lookup we do next to make sure it is really one of those cases
methodOverrides.containsKey(decl)) {
// special case for class X() extends T(){ m = function() => e; } which we inline
decl = methodOverrides.get(decl);
}
Declaration refinedDecl = decl.getRefinedDeclaration();
if (refinedDecl != null && !ModelUtil.equal(refinedDecl, decl))
return getTopmostRefinedDeclaration(refinedDecl);
return decl;
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class ParameterNameParser method parseName.
private Parameter parseName(Type type, Function container) {
String identifier = lexer.eatIdentifier();
boolean declaredVoid = false;
boolean sequenced = false;
boolean atLeastOne = false;
if (lexer.lookingAt(STAR)) {
lexer.eat();
sequenced = true;
} else if (lexer.lookingAt(PLUS)) {
lexer.eat();
sequenced = true;
atLeastOne = true;
}
if (lexer.lookingAt(BANG)) {
lexer.eat();
declaredVoid = true;
}
final FunctionOrValue result;
if (lexer.lookingAt(LEFT_PAREN)) {
// functionParameter()
result = parseMethod(type, declaredVoid);
} else {
if (declaredVoid) {
throw new ParameterNameParserException("void Value");
}
// valueParameter();
result = parseValue(type);
}
result.setName(identifier);
result.setUnit(unit);
result.setContainer(container);
result.setScope(container);
Parameter p = new Parameter();
p.setName(identifier);
p.setSequenced(sequenced);
p.setAtLeastOne(atLeastOne);
p.setDeclaredAnything(declaredVoid);
p.setModel(result);
result.setInitializerParameter(p);
container.addMember(result);
return p;
}
Aggregations