use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class TreeUtil method hasUncheckedNulls.
private static boolean hasUncheckedNulls(Tree.Term term, boolean invoking) {
if (term instanceof Tree.MemberOrTypeExpression) {
Tree.MemberOrTypeExpression mte = (Tree.MemberOrTypeExpression) term;
Declaration d = mte.getDeclaration();
if (d instanceof TypedDeclaration) {
TypedDeclaration td = (TypedDeclaration) d;
return td.hasUncheckedNullType() && // because java method references can't be null
(!(d instanceof Function) || invoking);
} else {
return false;
}
} else if (term instanceof Tree.QualifiedMemberOrTypeExpression) {
Tree.QualifiedMemberOrTypeExpression qmte = (Tree.QualifiedMemberOrTypeExpression) term;
return hasUncheckedNulls(qmte.getPrimary(), invoking);
} else if (term instanceof Tree.InvocationExpression) {
Tree.InvocationExpression ite = (Tree.InvocationExpression) term;
return hasUncheckedNulls(ite.getPrimary(), true);
} else if (term instanceof Tree.DefaultOp) {
Tree.DefaultOp op = (Tree.DefaultOp) term;
return hasUncheckedNulls(op.getRightTerm(), invoking);
} else if (term instanceof Tree.Expression) {
Tree.Expression e = (Tree.Expression) term;
return hasUncheckedNulls(e.getTerm(), invoking);
} else if (term instanceof Tree.LetExpression) {
Tree.LetExpression e = (Tree.LetExpression) term;
return hasUncheckedNulls(e.getLetClause().getExpression(), invoking);
} else if (term instanceof Tree.IfExpression) {
Tree.IfExpression e = (Tree.IfExpression) term;
return hasUncheckedNulls(e.getIfClause().getExpression(), invoking) || hasUncheckedNulls(e.getElseClause().getExpression(), invoking);
} else if (term instanceof Tree.SwitchExpression) {
Tree.SwitchExpression e = (Tree.SwitchExpression) term;
for (CaseClause clause : e.getSwitchCaseList().getCaseClauses()) {
if (hasUncheckedNulls(clause.getExpression(), invoking)) {
return true;
}
}
if (e.getSwitchCaseList().getElseClause() != null) {
return hasUncheckedNulls(e.getSwitchCaseList().getElseClause().getExpression(), invoking);
}
return false;
} else {
return false;
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class Metamodel method getTypeDescriptorForProducedType.
public static TypeDescriptor getTypeDescriptorForProducedType(org.eclipse.ceylon.model.typechecker.model.Type type) {
TypeDeclaration declaration = type.getDeclaration();
if (type.isNothing()) {
return TypeDescriptor.NothingType;
}
if (type.isUnion()) {
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getCaseTypes());
return TypeDescriptor.union(tdArgs);
}
if (type.isIntersection()) {
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getSatisfiedTypes());
return TypeDescriptor.intersection(tdArgs);
}
if (declaration instanceof LazyClass) {
ReflectionClass classMirror = (ReflectionClass) ((LazyClass) declaration).classMirror;
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getTypeArgumentList());
TypeDescriptor ret = TypeDescriptor.klass(classMirror.klass, tdArgs);
if (type.getQualifyingType() != null)
return TypeDescriptor.member(getTypeDescriptorForProducedType(type.getQualifyingType()), ret);
return ret;
}
if (declaration instanceof LazyInterface) {
ReflectionClass classMirror = (ReflectionClass) ((LazyInterface) declaration).classMirror;
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getTypeArgumentList());
TypeDescriptor ret = TypeDescriptor.klass(classMirror.klass, tdArgs);
if (type.getQualifyingType() != null)
return TypeDescriptor.member(getTypeDescriptorForProducedType(type.getQualifyingType()), ret);
return ret;
}
if (declaration instanceof FunctionOrValueInterface) {
TypedDeclaration underlyingDeclaration = ((FunctionOrValueInterface) declaration).getUnderlyingDeclaration();
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getTypeArgumentList());
TypeDescriptor ret;
if (underlyingDeclaration.isToplevel()) {
ReflectionClass classMirror;
// type arguments
if (underlyingDeclaration instanceof Setter)
underlyingDeclaration = ((Setter) underlyingDeclaration).getGetter();
if (underlyingDeclaration instanceof LazyValue)
classMirror = (ReflectionClass) ((LazyValue) underlyingDeclaration).classMirror;
else if (underlyingDeclaration instanceof LazyFunction)
classMirror = (ReflectionClass) ((LazyFunction) underlyingDeclaration).classMirror;
else
throw Metamodel.newModelError("Unsupported underlying declaration type: " + underlyingDeclaration);
ret = TypeDescriptor.functionOrValue(classMirror.klass, tdArgs);
} else
ret = TypeDescriptor.functionOrValue(underlyingDeclaration.getPrefixedName(), tdArgs);
if (type.getQualifyingType() != null)
return TypeDescriptor.member(getTypeDescriptorForProducedType(type.getQualifyingType()), ret);
return ret;
}
if (declaration instanceof UnknownType) {
((UnknownType) declaration).reportErrors();
}
throw Metamodel.newModelError("Unsupported declaration type: " + (declaration == null ? "null" : declaration.getClass()));
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class InvocationGenerator method generateSpreadArgument.
private void generateSpreadArgument(final Tree.Primary primary, final Tree.SpreadArgument arg, Tree.Expression expr, final Parameter pd) {
TypedDeclaration td = pd == null ? null : pd.getModel();
int boxType = gen.boxUnboxStart(expr.getTerm(), td);
if (boxType == 4) {
arg.visit(gen);
gen.out(",");
describeMethodParameters(expr.getTerm());
gen.out(",");
TypeUtils.printTypeArguments(arg, arg.getTypeModel().getTypeArguments(), gen, false, arg.getTypeModel().getVarianceOverrides());
} else if (pd == null) {
final Declaration primDec = primary instanceof Tree.MemberOrTypeExpression ? ((Tree.MemberOrTypeExpression) primary).getDeclaration() : null;
if (gen.isInDynamicBlock() && primary instanceof Tree.MemberOrTypeExpression && (primDec == null || primDec.isDynamic() || (primDec instanceof TypedDeclaration && ((TypedDeclaration) primDec).isDynamicallyTyped())) && arg.getTypeModel() != null && arg.getTypeModel().getDeclaration().inherits((arg.getUnit().getTupleDeclaration()))) {
// Spread dynamic parameter
Type tupleType = arg.getTypeModel();
Type targ = tupleType.getTypeArgumentList().get(2);
arg.visit(gen);
gen.out(".$_get(0)");
int i = 1;
while (!targ.isSubtypeOf(arg.getUnit().getEmptyType())) {
gen.out(",");
arg.visit(gen);
gen.out(".$_get(" + (i++) + ")");
targ = targ.getTypeArgumentList().get(2);
}
} else {
arg.visit(gen);
}
} else if (pd.isSequenced()) {
arg.visit(gen);
if (!arg.getUnit().isSequentialType(arg.getTypeModel())) {
gen.out(".sequence()");
}
} else if (!arg.getTypeModel().isEmpty()) {
final String specialSpreadVar = gen.getNames().createTempVariable();
gen.out("(", specialSpreadVar, "=");
arg.visit(gen);
final boolean unknownSpread = arg.getTypeModel().isUnknown();
final String get0 = unknownSpread ? "[" : ".$_get(";
final String get1 = unknownSpread ? "]" : ")";
if (!unknownSpread && !arg.getUnit().isSequentialType(arg.getTypeModel())) {
gen.out(".sequence()");
}
gen.out(",");
if (pd.isDefaulted()) {
gen.out(gen.getClAlias(), "nn$(", specialSpreadVar, get0, "0", get1, ")?", specialSpreadVar, get0, "0", get1, ":undefined)");
} else {
gen.out(specialSpreadVar, get0, "0", get1, ")");
}
// Find out if there are more params
final List<Parameter> moreParams;
final Declaration pdd = pd.getDeclaration();
boolean found = false;
if (pdd instanceof Function) {
moreParams = ((Function) pdd).getFirstParameterList().getParameters();
} else if (pdd instanceof Class) {
moreParams = ((Class) pdd).getParameterList().getParameters();
} else {
// Check the parameters of the primary (obviously a callable, so this is a Tuple)
List<Parameter> cparms = TypeUtils.convertTupleToParameters(primary.getTypeModel().getTypeArgumentList().get(1));
cparms.remove(0);
moreParams = cparms;
found = true;
}
if (moreParams != null) {
int c = 1;
for (Parameter restp : moreParams) {
if (found) {
final String cs = Integer.toString(c++);
if (restp.isDefaulted()) {
gen.out(",", gen.getClAlias(), "nn$(", specialSpreadVar, get0, cs, get1, ")?", specialSpreadVar, get0, cs, get1, ":undefined");
} else if (restp.isSequenced()) {
if (c == 2) {
gen.out(",", specialSpreadVar, ".rest");
} else {
gen.out(",", specialSpreadVar, ".sublistFrom(", cs, ")");
}
} else {
gen.out(",", specialSpreadVar, get0, cs, get1);
}
} else {
found = restp.equals(pd);
}
}
}
}
gen.boxUnboxEnd(boxType);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class JsCompiler method generate.
/**
* Compile all the phased units in the typechecker.
* @return true is compilation was successful (0 errors/warnings), false otherwise.
*/
public boolean generate() throws IOException {
errorVisitor.clear();
errCount = 0;
output.clear();
try {
if (opts.isVerbose()) {
logger.debug("Generating metamodel...");
}
List<PhasedUnit> typecheckerPhasedUnits = tc.getPhasedUnits().getPhasedUnits();
List<PhasedUnit> phasedUnits = new ArrayList<>(typecheckerPhasedUnits.size());
for (PhasedUnit pu : typecheckerPhasedUnits) {
if (srcFiles == null) {
phasedUnits.add(pu);
} else {
File path = getFullPath(pu);
if (srcFiles.contains(path)) {
phasedUnits.add(pu);
}
}
}
boolean generatedCode = false;
// First generate the metamodel
final Module defmod = tc.getContext().getModules().getDefaultModule();
for (PhasedUnit pu : phasedUnits) {
// #416 default module with packages
Module mod = pu.getPackage().getModule();
if (mod.getVersion() == null && !mod.isDefaultModule()) {
// Switch with the default module
for (org.eclipse.ceylon.model.typechecker.model.Package pkg : mod.getPackages()) {
defmod.getPackages().add(pkg);
pkg.setModule(defmod);
}
}
EnumSet<Warning> suppressedWarnings = opts.getSuppressWarnings();
if (suppressedWarnings == null)
suppressedWarnings = EnumSet.noneOf(Warning.class);
pu.getCompilationUnit().visit(new WarningSuppressionVisitor<>(Warning.class, suppressedWarnings));
// Perform capture analysis
for (org.eclipse.ceylon.model.typechecker.model.Declaration d : pu.getDeclarations()) {
if (d instanceof TypedDeclaration && d instanceof org.eclipse.ceylon.model.typechecker.model.Setter == false) {
pu.getCompilationUnit().visit(new ValueVisitor((TypedDeclaration) d));
}
}
pu.getCompilationUnit().visit(getOutput(pu).mmg);
if (opts.hasVerboseFlag("ast")) {
if (opts.getOutWriter() == null) {
logger.debug(pu.getCompilationUnit().toString());
} else {
opts.getOutWriter().write(pu.getCompilationUnit().toString());
opts.getOutWriter().write('\n');
}
}
}
// Then write it out and output the reference in the module file
names = new JsIdentifierNames(this);
if (!compilingLanguageModule) {
for (Map.Entry<Module, JsOutput> e : output.entrySet()) {
e.getValue().encodeModel(names);
}
}
// Output all the require calls for any imports
final Visitor importVisitor = new Visitor() {
public void visit(Tree.Import that) {
ImportableScope scope = that.getImportMemberOrTypeList().getImportList().getImportedScope();
Module _m = that.getUnit().getPackage().getModule();
if (scope instanceof Package) {
Package pkg = (Package) scope;
Module om = pkg.getModule();
if (!om.equals(_m) && (!om.isNative() || om.getNativeBackends().supports(Backend.JavaScript))) {
Module impmod = ((Package) scope).getModule();
if (impmod instanceof NpmAware && ((NpmAware) impmod).getNpmPath() != null) {
output.get(_m).requireFromNpm(impmod, names);
} else {
output.get(_m).require(impmod, names);
}
}
}
}
public void visit(Tree.ImportModule that) {
if (that.getImportPath() != null && that.getImportPath().getModel() instanceof Module) {
Module m = (Module) that.getImportPath().getModel();
// Binary version check goes here now
int binMajorVersion = m.getJsMajor();
int binMinorVersion = m.getJsMinor();
if (m.getJsMajor() == 0) {
// Check if it's something we're compiling
for (PhasedUnit pu : tc.getPhasedUnits().getPhasedUnits()) {
if (pu.getPackage() != null && pu.getPackage().getModule() == m) {
m.setJsMajor(Versions.JS_BINARY_MAJOR_VERSION);
m.setJsMinor(Versions.JS_BINARY_MINOR_VERSION);
binMajorVersion = Versions.JS_BINARY_MAJOR_VERSION;
binMinorVersion = Versions.JS_BINARY_MINOR_VERSION;
break;
}
}
if (m.getJsMajor() == 0) {
// Load the module (most likely we're in the IDE if we need to do this)
ArtifactContext ac = new ArtifactContext(null, m.getNameAsString(), m.getVersion(), ArtifactContext.JS_MODEL);
ac.setIgnoreDependencies(true);
ac.setThrowErrorIfMissing(false);
ArtifactResult ar = tc.getContext().getRepositoryManager().getArtifactResult(ac);
if (ar == null) {
return;
}
File js = ar.artifact();
if (js != null) {
Map<String, Object> json = JsModuleSourceMapper.loadJsonModel(js);
String binVersion = json.get("$mod-bin").toString();
int p = binVersion.indexOf('.');
binMajorVersion = Integer.valueOf(binVersion.substring(0, p));
binMinorVersion = Integer.valueOf(binVersion.substring(p + 1));
}
}
}
if (!Versions.isJsBinaryVersionSupported(binMajorVersion, binMinorVersion)) {
that.addError("version '" + m.getVersion() + "' of module '" + m.getNameAsString() + "' was compiled by an incompatible version of the compiler (binary version " + binMajorVersion + "." + binMinorVersion + " of module is not compatible with binary version " + Versions.JS_BINARY_MAJOR_VERSION + "." + Versions.JS_BINARY_MINOR_VERSION + " of this compiler)");
}
}
}
};
for (PhasedUnit pu : phasedUnits) {
pu.getCompilationUnit().visit(importVisitor);
}
// Then generate the JS code
List<PhasedUnit> pkgs = new ArrayList<>(4);
if (srcFiles == null && !phasedUnits.isEmpty()) {
for (PhasedUnit pu : phasedUnits) {
if ("module.ceylon".equals(pu.getUnitFile().getName())) {
final int t = compileUnit(pu);
generatedCode = true;
if (t != 0) {
return false;
}
}
}
for (PhasedUnit pu : phasedUnits) {
if ("package.ceylon".equals(pu.getUnitFile().getName())) {
pkgs.add(pu);
continue;
} else if ("module.ceylon".equals(pu.getUnitFile().getName())) {
continue;
}
final int t = compileUnit(pu);
generatedCode = true;
if (t == 1) {
return false;
} else if (t == 2) {
break;
}
}
} else if (srcFiles != null && !srcFiles.isEmpty() && // For the specific case of the Stitcher
!typecheckerPhasedUnits.isEmpty()) {
for (PhasedUnit pu : phasedUnits) {
if ("module.ceylon".equals(pu.getUnitFile().getName())) {
final int t = compileUnit(pu);
generatedCode = true;
if (t != 0) {
return false;
}
}
}
for (File path : srcFiles) {
if (path.getPath().endsWith(ArtifactContext.JS)) {
// Just output the file
File dir = path.getParentFile();
PhasedUnit lastUnit = phasedUnits.isEmpty() ? typecheckerPhasedUnits.get(0) : phasedUnits.get(0);
for (PhasedUnit pu : phasedUnits) {
if (pu.getUnitFile().getPath().startsWith(dir.getPath())) {
lastUnit = pu;
break;
}
}
final JsOutput lastOut = getOutput(lastUnit);
VirtualFile vpath = findFile(path);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(vpath.getInputStream(), opts.getEncoding()))) {
String line = null;
while ((line = reader.readLine()) != null) {
if (opts.isMinify()) {
line = line.trim();
if (!opts.isComment() && line.startsWith("//") && !line.contains("*/")) {
continue;
}
}
if (line.length() == 0) {
continue;
}
lastOut.getWriter().write(line);
lastOut.getWriter().write('\n');
}
} finally {
lastOut.addSource(path);
}
generatedCode = true;
} else {
// Find the corresponding compilation unit
for (PhasedUnit pu : phasedUnits) {
File unitFile = getFullPath(pu);
if (path.equals(unitFile)) {
if (path.getName().equals("package.ceylon")) {
pkgs.add(pu);
continue;
} else if (path.getName().equals("module.ceylon")) {
continue;
}
final int t = compileUnit(pu);
generatedCode = true;
if (t == 1) {
return false;
} else if (t == 2) {
break;
}
}
}
}
}
if (resFiles != null) {
for (Map.Entry<Module, JsOutput> entry : output.entrySet()) {
Module module = entry.getKey();
final JsOutput lastOut = getOutput(module);
for (File file : filterForModule(resFiles, opts.getResourceDirs(), module.getNameAsString())) {
String type = Files.probeContentType(file.toPath());
String fileName = file.getName();
boolean isResourceFile = fileName.endsWith(".properties") || fileName.endsWith(".txt");
if (isResourceFile || type != null && type.startsWith("text")) {
Writer writer = lastOut.getWriter();
writer.write("ex$.");
writer.write(resourceKey(module, file));
writer.write("=\"");
Pattern pattern = Pattern.compile("\\\\|\\t|\\r|\\f|\\n");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), opts.getEncoding()))) {
String line = null;
while ((line = reader.readLine()) != null) {
if (isResourceFile && opts.isMinify()) {
line = line.trim();
if (line.length() == 0) {
continue;
}
if (!opts.isComment() && line.startsWith("#")) {
continue;
}
}
StringBuffer result = new StringBuffer();
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
String escaped;
switch(matcher.group(0)) {
case "\\":
escaped = "\\\\\\\\";
break;
case "\t":
escaped = "\\\\t";
break;
case "\r":
escaped = "\\\\r";
break;
case "\f":
escaped = "\\\\f";
break;
case "\n":
escaped = "\\\\n";
break;
default:
throw new IllegalStateException();
}
matcher.appendReplacement(result, escaped);
}
matcher.appendTail(result);
writer.write(result.toString());
if (reader.ready()) {
writer.write("\\n");
}
}
}
writer.write("\";\n");
generatedCode = true;
}
}
}
}
}
for (PhasedUnit pu : pkgs) {
final int t = compileUnit(pu);
generatedCode = true;
if (t == 1) {
return false;
} else if (t == 2) {
break;
}
}
if (!generatedCode) {
logger.error("No source units found to compile");
exitCode = 2;
}
} finally {
if (exitCode == 0) {
exitCode = finish();
}
}
return errCount == 0 && exitCode == 0;
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class BmeGenerator method createTypeArguments.
/**
* Create a map with type arguments from the type parameter list in the expression's declaration and the
* type argument list in the expression itself.
*/
static Map<TypeParameter, Type> createTypeArguments(final Tree.StaticMemberOrTypeExpression expr) {
List<TypeParameter> tparams = null;
Declaration declaration = expr.getDeclaration();
if (declaration instanceof Generic) {
tparams = declaration.getTypeParameters();
} else if (declaration instanceof TypedDeclaration && ((TypedDeclaration) declaration).getType() != null && ((TypedDeclaration) declaration).getType().isTypeConstructor()) {
tparams = ((TypedDeclaration) declaration).getType().getDeclaration().getTypeParameters();
} else {
expr.addUnexpectedError("Getting type parameters from unidentified declaration type " + declaration, Backend.JavaScript);
return null;
}
final HashMap<TypeParameter, Type> targs = new HashMap<>();
TypeArguments typeArguments = expr.getTypeArguments();
if (typeArguments != null) {
List<Type> typeModels = typeArguments.getTypeModels();
if (typeModels != null) {
final Iterator<Type> iter = typeModels.iterator();
for (TypeParameter tp : tparams) {
Type pt = iter.hasNext() ? iter.next() : tp.getDefaultTypeArgument();
targs.put(tp, pt);
}
}
}
return targs;
}
Aggregations