private void loadModuleFromSource(
      Package pkg, Modules modules, LinkedList<JCCompilationUnit> moduleTrees) {
    // skip it if we already resolved the package
    if (pkg.getModule() != null) return;
    String pkgName = pkg.getQualifiedNameString();
    Module module = null;
    // do we have a module for this package?
    // FIXME: is this true? what if we have a module.ceylon at toplevel?
    if (pkgName.isEmpty()) module = modules.getDefaultModule();
    else {
      for (Module m : modules.getListOfModules()) {
        if (pkgName.startsWith(m.getNameAsString())) {
          module = m;
          break;
        }
      }
      if (module == null) {
        module = loadModuleFromSource(pkgName, moduleTrees);
      } else if (!module.isAvailable()) {
        loadModuleFromSource(pkgName, moduleTrees);
      }

      if (module == null) {
        // no declaration for it, must be the default module
        module = modules.getDefaultModule();
      }
    }
    // bind module and package together
    pkg.setModule(module);
    module.getPackages().add(pkg);
    // automatically add this module's jar to the classpath if it exists
    ceylonEnter.addModuleToClassPath(module, false);
  }
  @Override
  protected void setPhasedUnitIfNecessary() {
    if (phasedUnitRef == null) {
      // Look into the mapping.txt of the module archive, and get the name of the source unit
      // Then get the PhasedUnits related to this module, and search for the relative path in it.
      // Then set it into the WeakRef with createPhasedUnit

      String[] splittedPath = getFullPath().split("!");
      if (splittedPath.length == 2) {
        String carPath = splittedPath[0];
        try {
          Properties mapping = CarUtils.retrieveMappingFile(new File(carPath));
          String sourceFileRelativePath = mapping.getProperty(splittedPath[1]);
          Package pkg = getPackage();
          if (pkg != null) {
            Module module = pkg.getModule();
            // TODO : retrieve the PhasedUnits object related to this module
            // get the PhasedUnit object through its src-relative path
            IdePhasedUnit pu = null; // replace by the right value
            createPhasedUnitRef(pu);
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }
  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) {
      // 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?
    // FIXME: is this true? what if we have a module.ceylon at toplevel?
    if (pkgName.isEmpty()) module = modules.getDefaultModule();
    else {
      for (Module m : modulesLoadedFromSource) {
        if (Util.isSubPackage(m.getNameAsString(), pkgName)) {
          module = m;
          break;
        }
      }
      if (module == null) {
        module = loadModuleFromSource(pkgName, moduleTrees, parsedTrees);
      } else if (!module.isAvailable()) {
        loadModuleFromSource(pkgName, moduleTrees, parsedTrees);
      }

      if (module == null) {
        // no declaration for it, must be the default module, unless we're bootstrapping the
        // language module,
        // because we have some com.redhat.ceylon packages that must go in the language module
        if (isBootstrap) module = modules.getLanguageModule();
        else module = modules.getDefaultModule();
      }
    }
    // bind module and package together
    pkg.setModule(module);
    module.getPackages().add(pkg);
    // automatically add this module's jar to the classpath if it exists
    ceylonEnter.addOutputModuleToClassPath(module);
  }
 private JavaFileObject genCodeUnlessError(Env<AttrContext> env, JCClassDecl cdef)
     throws IOException {
   CeylonFileObject sourcefile = (CeylonFileObject) env.toplevel.sourcefile;
   try {
     // do not look at the global number of errors but only those for this file
     if (super.gen.genClass(env, cdef) && !sourcefile.hasError(cdef.pos)) {
       String packageName = cdef.sym.packge().getQualifiedName().toString();
       Package pkg = modelLoader.findPackage(packageName);
       if (pkg == null) throw new RuntimeException("Failed to find package: " + packageName);
       Module module = pkg.getModule();
       if (!module.isDefault()) {
         String moduleName = module.getNameAsString();
         CeylonFileObject moduleFileObject = moduleNamesToFileObjects.get(moduleName);
         // if there's no module source file object it means the module descriptor had parse errors
         if (moduleFileObject == null || moduleFileObject.hasError()) {
           // we do not produce any class files for modules with errors
           if (options.get(OptionName.VERBOSE) != null) {
             Log.printLines(
                 log.noticeWriter,
                 "[Not writing class "
                     + cdef.sym.className()
                     + " because its module has errors: "
                     + moduleName
                     + "]");
           }
           return null;
         }
       }
       return writer.writeClass(cdef.sym);
     }
   } catch (ClassWriter.PoolOverflow ex) {
     log.error(cdef.pos(), "limit.pool");
   } catch (ClassWriter.StringOverflow ex) {
     log.error(cdef.pos(), "limit.string.overflow", ex.value.substring(0, 20));
   } catch (CompletionFailure ex) {
     chk.completionError(cdef.pos(), ex);
   } catch (AssertionError e) {
     throw new RuntimeException("Error generating bytecode for " + sourcefile.getName(), e);
   }
   return null;
 }
 @Override
 public void removeUnit(Unit unit) {
   synchronized (modelLoader) {
     if (lazyUnits.remove(unit)) {
       for (Declaration d : unit.getDeclarations()) {
         compiledDeclarations.remove(d);
         // TODO : remove the declaration from the declaration map in AbstractModelLoader
       }
       modelLoader.removeDeclarations(unit.getDeclarations());
     } else {
       super.removeUnit(unit);
     }
   }
 }
 @Override
 protected IStatus run(IProgressMonitor monitor) {
   monitor.beginTask("Warming up completion processor", 100000);
   Set<Module> modules =
       typeChecker
           .getPhasedUnits()
           .getModuleManager()
           .getContext()
           .getModules()
           .getListOfModules();
   monitor.worked(10000);
   for (Module m : modules) {
     List<Package> packages = m.getAllPackages();
     for (Package p : packages) {
       p.getMembers();
     }
     monitor.worked(90000 / max(modules.size(), 1));
     if (monitor.isCanceled()) {
       return Status.CANCEL_STATUS;
     }
   }
   monitor.done();
   return Status.OK_STATUS;
 }
 public static String getLabel(Package packageModel) {
   String name = packageModel.getQualifiedNameString();
   if (name.isEmpty()) name = "default package";
   return name;
 }
 private Module loadModuleFromSource(
     String pkgName,
     LinkedList<JCCompilationUnit> moduleTrees,
     List<JCCompilationUnit> parsedTrees) {
   if (pkgName.isEmpty()) return null;
   String moduleClassName = pkgName + ".module";
   JavaFileObject fileObject;
   try {
     if (options.get(OptionName.VERBOSE) != null) {
       Log.printLines(log.noticeWriter, "[Trying to load module " + moduleClassName + "]");
     }
     fileObject =
         fileManager.getJavaFileForInput(
             StandardLocation.SOURCE_PATH, moduleClassName, Kind.SOURCE);
     if (options.get(OptionName.VERBOSE) != null) {
       Log.printLines(log.noticeWriter, "[Got file object: " + fileObject + "]");
     }
   } catch (IOException e) {
     e.printStackTrace();
     return loadModuleFromSource(getParentPackage(pkgName), moduleTrees, parsedTrees);
   }
   if (fileObject != null) {
     // first make sure we're not already compiling it: this can happen if we have several versions
     // of the
     // same module already loaded: we will get one which isn't the one we compile, but that's not
     // the one
     // we really want to compile.
     for (JCCompilationUnit parsedTree : parsedTrees) {
       if (parsedTree.sourcefile.equals(fileObject)
           && parsedTree instanceof CeylonCompilationUnit) {
         // same file! we already parsed it, let's return this one's module
         PhasedUnit phasedUnit = ((CeylonCompilationUnit) parsedTree).phasedUnit;
         // the module visitor does load the module but does not set the unit's package module
         if (phasedUnit.getPackage().getModule() == null) {
           // so find the module it created
           for (Module mod : ceylonContext.getModules().getListOfModules()) {
             // we recognise it with the unit
             if (mod.getUnit() == phasedUnit.getUnit()) {
               // set the package's module
               Package pkg = phasedUnit.getPackage();
               pkg.setModule(mod);
               mod.getPackages().add(pkg);
               modulesLoadedFromSource.add(mod);
               break;
             }
           }
         }
         // now return it
         return phasedUnit.getPackage().getModule();
       }
     }
     JCCompilationUnit javaCompilationUnit = parse(fileObject);
     Module module;
     if (javaCompilationUnit instanceof CeylonCompilationUnit) {
       CeylonCompilationUnit ceylonCompilationUnit = (CeylonCompilationUnit) javaCompilationUnit;
       moduleTrees.add(ceylonCompilationUnit);
       // parse the module info from there
       module = ceylonCompilationUnit.phasedUnit.visitSrcModulePhase();
       ceylonCompilationUnit.phasedUnit.visitRemainingModulePhase();
       // now set the module
       if (module != null) {
         ceylonCompilationUnit.phasedUnit.getPackage().setModule(module);
       }
     } else {
       // there was a syntax error in the module descriptor, make a pretend module so that we can
       // correctly mark all declarations as part of that module, but we won't generate any code
       // for it
       ModuleManager moduleManager = phasedUnits.getModuleManager();
       module = moduleManager.getOrCreateModule(Arrays.asList(pkgName.split("\\.")), "bogus");
     }
     // now remember it
     if (module != null) {
       modulesLoadedFromSource.add(module);
       return module;
     }
   }
   return loadModuleFromSource(getParentPackage(pkgName), moduleTrees, parsedTrees);
 }
    @Override
    public void apply(IDocument document) {
      super.apply(document);
      if (withBody && EditorsUI.getPreferenceStore().getBoolean(LINKED_MODE)) {
        final LinkedModeModel linkedModeModel = new LinkedModeModel();
        final Point selection = getSelection(document);
        List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
        for (final Declaration d : p.getMembers()) {
          if (Util.isResolvable(d) && d.isShared()) {
            proposals.add(
                new ICompletionProposal() {
                  @Override
                  public Point getSelection(IDocument document) {
                    return null;
                  }

                  @Override
                  public Image getImage() {
                    return getImageForDeclaration(d);
                  }

                  @Override
                  public String getDisplayString() {
                    return d.getName();
                  }

                  @Override
                  public IContextInformation getContextInformation() {
                    return null;
                  }

                  @Override
                  public String getAdditionalProposalInfo() {
                    return null;
                  }

                  @Override
                  public void apply(IDocument document) {
                    try {
                      document.replace(selection.x, selection.y, d.getName());
                    } catch (BadLocationException e) {
                      e.printStackTrace();
                    }
                    linkedModeModel.exit(ILinkedModeListener.UPDATE_CARET);
                  }
                });
          }
        }
        ProposalPosition linkedPosition =
            new ProposalPosition(
                document, selection.x, selection.y, 0, proposals.toArray(NO_COMPLETIONS));
        try {
          LinkedMode.addLinkedPosition(linkedModeModel, linkedPosition);
          LinkedMode.installLinkedMode(
              (CeylonEditor) EditorUtil.getCurrentEditor(),
              document,
              linkedModeModel,
              this,
              new LinkedMode.NullExitPolicy(),
              -1,
              0);
        } catch (BadLocationException ble) {
          ble.printStackTrace();
        }
      }
    }