use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class TypeUtils method mapTypeArgument.
/**
* Generates the right type arguments for operators that are sugar for method calls.
* @param methodName The name of the method that is to be invoked
* @param rightTpName The name of the type argument on the right term
* @param leftTpName The name of the type parameter on the method
* @return A map with the type parameter of the method as key
* and the produced type belonging to the type argument of the term on the right.
*/
public static Map<TypeParameter, Type> mapTypeArgument(final Tree.BinaryOperatorExpression expr, final String methodName, final String rightTpName, final String leftTpName) {
Function md = (Function) expr.getLeftTerm().getTypeModel().getDeclaration().getMember(methodName, null, false);
if (md == null) {
expr.addUnexpectedError("Left term of intersection operator should have method named " + methodName, Backend.JavaScript);
return null;
}
Map<TypeParameter, Type> targs = expr.getRightTerm().getTypeModel().getTypeArguments();
Type otherType = null;
for (TypeParameter tp : targs.keySet()) {
if (tp.getName().equals(rightTpName)) {
otherType = targs.get(tp);
break;
}
}
if (otherType == null) {
expr.addUnexpectedError("Right term of intersection operator should have type parameter named " + rightTpName, Backend.JavaScript);
return null;
}
targs = new HashMap<>();
TypeParameter mtp = null;
for (TypeParameter tp : md.getTypeParameters()) {
if (tp.getName().equals(leftTpName)) {
mtp = tp;
break;
}
}
if (mtp == null) {
expr.addUnexpectedError("Left term of intersection should have type parameter named " + leftTpName, Backend.JavaScript);
}
targs.put(mtp, otherType);
return targs;
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class TypeUtils method generateModelPath.
/**
* Returns the list of keys to get from the package to the declaration, in the model.
*/
public static List<String> generateModelPath(final Declaration d) {
final ArrayList<String> sb = new ArrayList<>();
final Package pkg = d.getUnit().getPackage();
sb.add(pkg.isLanguagePackage() ? "$" : pkg.getNameAsString());
if (d.isToplevel()) {
sb.add(d.getName());
if (d instanceof Setter) {
sb.add("$set");
}
} else {
Declaration p = d;
final int i = sb.size();
while (p instanceof Declaration) {
if (p instanceof Setter) {
sb.add(i, "$set");
}
final String mname = TypeUtils.modelName(p);
if (!(mname.startsWith("anon$") || mname.startsWith("anonymous#"))) {
sb.add(i, mname);
// Build the path in reverse
if (!p.isToplevel()) {
if (p instanceof Class) {
sb.add(i, p.isAnonymous() ? MetamodelGenerator.KEY_OBJECTS : MetamodelGenerator.KEY_CLASSES);
} else if (p instanceof org.eclipse.ceylon.model.typechecker.model.Interface) {
sb.add(i, MetamodelGenerator.KEY_INTERFACES);
} else if (p instanceof Function) {
if (!p.isAnonymous()) {
sb.add(i, MetamodelGenerator.KEY_METHODS);
}
} else if (p instanceof TypeAlias || p instanceof Setter) {
sb.add(i, MetamodelGenerator.KEY_ATTRIBUTES);
} else if (p instanceof Constructor || ModelUtil.isConstructor(p)) {
sb.add(i, MetamodelGenerator.KEY_CONSTRUCTORS);
} else {
// It's a value
TypeDeclaration td = ((TypedDeclaration) p).getTypeDeclaration();
sb.add(i, (td != null && td.isAnonymous()) ? MetamodelGenerator.KEY_OBJECTS : MetamodelGenerator.KEY_ATTRIBUTES);
}
}
}
p = ModelUtil.getContainingDeclaration(p);
while (p != null && p instanceof ClassOrInterface == false && !(p.isToplevel() || p.isAnonymous() || p.isClassOrInterfaceMember() || p.isJsCaptured())) {
p = ModelUtil.getContainingDeclaration(p);
}
}
}
return sb;
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class JsIdentifierNames method name.
public String name(Parameter param) {
if (param == null) {
return null;
}
String name = param.getName();
FunctionOrValue decl = param.getModel();
final boolean nonLocal = decl.isShared() && decl.isMember() || decl.isToplevel() && decl instanceof Function;
if (nonLocal) {
// The identifier might be accessed from other .js files, so it must
// be reliably reproducible. In most cases simply using the original
// name is ok because otherwise it would result in a name collision in
// Ceylon too. We just have to take care of a few exceptions:
String suffix = nestingSuffix(decl, false);
if (suffix.length() > 0) {
// nested type
name += suffix;
} else if (reservedWords.contains(name)) {
// JavaScript keyword
name = "$_" + name;
}
} else {
// The identifier will not be used outside the generated .js file,
// so we can simply disambiguate it with a numeric ID.
name = uniquePrivateName(decl, false);
}
return JsUtils.escapeStringLiteral(name);
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class JsIdentifierNames method getName.
private String getName(Declaration decl, boolean forGetterSetter, boolean priv) {
if (decl == null) {
return null;
}
String name = decl.getName();
if (name == null && ModelUtil.isConstructor(decl)) {
return "$c$";
}
if (name.startsWith("anonymous#")) {
name = "anon$" + name.substring(10);
}
if (decl.isDynamic()) {
return JsUtils.escapeStringLiteral(decl.getName());
}
boolean nonLocal = !priv;
if (nonLocal) {
// check if it's a shared member or a toplevel function
nonLocal = decl.isMember() ? decl.isShared() || decl instanceof TypeDeclaration : decl.isToplevel() && (forGetterSetter || decl instanceof Function || decl instanceof ClassOrInterface || decl instanceof TypeAlias);
}
if (nonLocal && decl instanceof Class && ((Class) decl).isAnonymous() && !forGetterSetter) {
// A lower-case class name belongs to an object and is not public.
nonLocal = false;
}
if (nonLocal) {
// The identifier might be accessed from other .js files, so it must
// be reliably reproducible. In most cases simply using the original
// name is ok because otherwise it would result in a name collision in
// Ceylon too. We just have to take care of a few exceptions:
String suffix = nestingSuffix(decl, false);
if (suffix.length() > 0) {
// nested type
name += suffix;
} else if ((!forGetterSetter && !ModelUtil.isConstructor(decl) && reservedWords.contains(name)) || isJsGlobal(decl)) {
// JavaScript keyword or global declaration
name = "$_" + name;
}
} else {
// The identifier will not be used outside the generated .js file,
// so we can simply disambiguate it with a numeric ID.
name = uniquePrivateName(decl, priv);
}
// Fix #204 - same top-level declarations in different packages
final Package declPkg = decl.getUnit().getPackage();
if (decl.isToplevel() && !declPkg.equals(declPkg.getModule().getRootPackage())) {
final Package raiz = declPkg.getModule().getRootPackage();
// rootPackage can be null when compiling from IDE
String rootName = raiz == null ? (declPkg.getModule().isDefaultModule() ? "" : declPkg.getModule().getNameAsString()) : raiz.getNameAsString();
String pkgName = declPkg.getNameAsString();
rootName = pkgName.substring(rootName.length()).replaceAll("\\.", "\\$");
if (rootName.length() > 0 && rootName.charAt(0) != '$') {
rootName = '$' + rootName;
}
name += rootName;
}
if (decl instanceof TypeAlias) {
name += "()";
}
return JsUtils.escapeStringLiteral(name);
}
use of org.eclipse.ceylon.model.typechecker.model.Function in project ceylon by eclipse.
the class RefinementVisitor method checkOverloadedAnnotation.
private void checkOverloadedAnnotation(Tree.Declaration that, Declaration member) {
// non-actual overloaded methods
// must be annotated 'overloaded'
boolean marked = false;
Unit unit = that.getUnit();
for (Tree.Annotation a : that.getAnnotationList().getAnnotations()) {
Tree.Primary p = a.getPrimary();
if (p instanceof Tree.BaseMemberExpression) {
Tree.BaseMemberExpression bme = (Tree.BaseMemberExpression) p;
String aname = bme.getIdentifier().getText();
Declaration ad = p.getScope().getMemberOrParameter(unit, aname, null, false);
if (ad != null && isOverloadedAnnotation(ad)) {
marked = true;
}
}
}
if (!marked) {
if (member.isActual()) {
that.addUsageWarning(Warning.unknownWarning, "overloaded function should be declared with the 'overloaded' annotation in 'java.lang'");
} else {
if (member instanceof Constructor) {
// default constructors are the only
// thing that can legally have no name
that.addError("duplicate default constructor (overloaded default constructor must be declared with the 'overloaded' annotation in 'java.lang')");
} else if (member instanceof Function) {
// functions are the only thing
// that can legally have a name
// and be overloaded
that.addError("duplicate declaration: the name '" + member.getName() + "' is not unique in this scope " + "(overloaded function must be declared with the 'overloaded' annotation in 'java.lang')");
}
}
}
}
Aggregations