Permalink
Browse files

LanguageCompiler #1052: Adapt the typechecker hacks with moduleless p…

…ackages to the new model loader
  • Loading branch information...
1 parent 595fe1a commit 6cc79272c00424442baf2cb15a418f28000accbd @FroMage FroMage committed May 28, 2013
@@ -394,6 +394,9 @@ protected Module findModuleForClassMirror(ClassMirror classMirror) {
return lookupModuleInternal(pkgName);
}
+ /**
+ * See explanation in cacheModulelessPackages() below. This is called by LanguageCompiler during loadCompiledModules().
+ */
public synchronized LazyPackage findOrCreateModulelessPackage(String pkgName) {
LazyPackage pkg = modulelessPackages.get(pkgName);
if(pkg != null)
@@ -405,6 +408,13 @@ public synchronized LazyPackage findOrCreateModulelessPackage(String pkgName) {
return pkg;
}
+ /**
+ * Stef: this sucks balls, but the typechecker wants Packages created before we have any Module set up, including for parsing a module
+ * file, and because the model loader looks up packages and caches them using their modules, we can't really have packages before we
+ * have modules. Rather than rewrite the typechecker, we create moduleless packages during parsing, which means they are not cached with
+ * their modules, and after the loadCompiledModules step above, we fix the package modules. Remains to be done is to move the packages
+ * created from their cache to the right per-module cache.
+ */
public synchronized void cacheModulelessPackages(){
for(LazyPackage pkg : modulelessPackages.values()){
String quotedPkgName = Util.quoteJavaKeywords(pkg.getQualifiedNameString());
@@ -413,6 +423,13 @@ public synchronized void cacheModulelessPackages(){
modulelessPackages.clear();
}
+ /**
+ * Stef: after a lot of attempting, I failed to make the CompilerModuleManager produce a LazyPackage when the ModuleManager.initCoreModules
+ * is called for the default package. Because it is called by the PhasedUnits constructor, which is called by the ModelLoader constructor,
+ * which means the model loader is not yet in the context, so the CompilerModuleManager can't obtain it to pass it to the LazyPackage
+ * constructor. A rewrite of the logic of the typechecker scanning would fix this, but at this point it's just faster to let it create
+ * the wrong default package and fix it before we start parsing anything.
+ */
public synchronized void fixDefaultPackage() {
Module defaultModule = modules.getDefaultModule();
Package defaultPackage = defaultModule.getDirectPackage("");
@@ -53,7 +53,6 @@
import com.redhat.ceylon.compiler.java.loader.model.CompilerModuleManager;
import com.redhat.ceylon.compiler.java.util.Timer;
import com.redhat.ceylon.compiler.java.util.Util;
-import com.redhat.ceylon.compiler.loader.AbstractModelLoader;
import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleManager;
import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleValidator;
import com.redhat.ceylon.compiler.typechecker.context.PhasedUnit;
@@ -108,14 +107,15 @@
private final com.redhat.ceylon.compiler.typechecker.context.Context ceylonContext;
private final VFS vfs;
- private AbstractModelLoader modelLoader;
+ private CeylonModelLoader modelLoader;
private CeylonEnter ceylonEnter;
private Options options;
private Timer timer;
private boolean isBootstrap;
+ private boolean addedDefaultModuleToClassPath;
/** Get the PhasedUnits instance for this context. */
public static PhasedUnits getPhasedUnitsInstance(final Context context) {
@@ -210,7 +210,7 @@ public LanguageCompiler(Context context) {
} catch (Exception e) {
throw new RuntimeException(e);
}
- modelLoader = CeylonModelLoader.instance(context);
+ modelLoader = (CeylonModelLoader) CeylonModelLoader.instance(context);
ceylonEnter = CeylonEnter.instance(context);
options = Options.instance(context);
isBootstrap = options.get(OptionName.BOOTSTRAPCEYLON) != null;
@@ -313,7 +313,10 @@ private JCCompilationUnit ceylonParse(JavaFileObject filename, CharSequence read
// FIXME: this is bad in many ways
String pkgName = getPackage(filename);
// make a Package with no module yet, we will resolve them later
- com.redhat.ceylon.compiler.typechecker.model.Package p = modelLoader.findOrCreatePackage(null, pkgName == null ? "" : pkgName);
+ /*
+ * Stef: see javadoc for findOrCreateModulelessPackage() for why this is here.
+ */
+ com.redhat.ceylon.compiler.typechecker.model.Package p = modelLoader.findOrCreateModulelessPackage(pkgName == null ? "" : pkgName);
phasedUnit = new CeylonPhasedUnit(file, srcDir, cu, p, moduleManager, ceylonContext, filename, map);
phasedUnits.addPhasedUnit(file, phasedUnit);
gen.setMap(map);
@@ -335,13 +338,22 @@ private JCCompilationUnit ceylonParse(JavaFileObject filename, CharSequence read
@Override
public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) {
timer.startTask("parse");
+ /*
+ * Stef: see javadoc for fixDefaultPackage() for why this is here.
+ */
+ modelLoader.fixDefaultPackage();
List<JCCompilationUnit> trees = super.parseFiles(fileObjects);
timer.startTask("loadCompiledModules");
LinkedList<JCCompilationUnit> moduleTrees = new LinkedList<JCCompilationUnit>();
+ // now load modules and associate their moduleless packages with the corresponding modules
loadCompiledModules(trees, moduleTrees);
for (JCCompilationUnit moduleTree : moduleTrees) {
trees = trees.append(moduleTree);
}
+ /*
+ * Stef: see javadoc for cacheModulelessPackages() for why this is here.
+ */
+ modelLoader.cacheModulelessPackages();
timer.endTask();
return trees;
}
@@ -362,15 +374,24 @@ private void loadCompiledModules(List<JCCompilationUnit> trees, LinkedList<JCCom
String packageName = "";
if(cu.pid != null)
packageName = TreeInfo.fullName(cu.pid).toString();
- Package pkg = modelLoader.findOrCreatePackage(null, packageName);
+ /*
+ * Stef: see javadoc for findOrCreateModulelessPackage() for why this is here.
+ */
+ Package pkg = modelLoader.findOrCreateModulelessPackage(packageName);
loadModuleFromSource(pkg, modules, moduleTrees, trees);
}
}
private void loadModuleFromSource(Package pkg, Modules modules, LinkedList<JCCompilationUnit> moduleTrees, List<JCCompilationUnit> parsedTrees) {
// skip it if we already resolved the package
- if(pkg.getModule() != null)
+ if(pkg.getModule() != null){
+ // make sure the default module is always added to the classpath, it will be the only one to have a module
+ if(!addedDefaultModuleToClassPath && pkg.getModule().isDefault()){
+ addedDefaultModuleToClassPath = true;
+ ceylonEnter.addOutputModuleToClassPath(pkg.getModule());
+ }
return;
+ }
String pkgName = pkg.getQualifiedNameString();
Module module = null;
// do we have a module for this package?

0 comments on commit 6cc7927

Please sign in to comment.