X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fmodule%2Frepository%2FModuleRepository.java;h=0f0b8542049a53c7f8eea2667ba15c40789f0f7b;hp=b851810e375a3f306a6224f7c2d8aa2691780c5e;hb=7444d4b3a2f3c25fac462d8a168898656dafd52e;hpb=0ae2b770234dfc3cbb18bd38f324125cf0faca07 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java index b851810e3..0f0b85420 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java @@ -4,12 +4,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.environment.ConcreteEnvironment; +import org.simantics.scl.compiler.environment.EmptyEnvironment; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.environment.NamespaceImpl.ModuleImport; import org.simantics.scl.compiler.environment.NamespaceSpec; @@ -20,10 +21,12 @@ import org.simantics.scl.compiler.errors.CompilationError; import org.simantics.scl.compiler.errors.DoesNotExist; import org.simantics.scl.compiler.errors.Failable; import org.simantics.scl.compiler.errors.Failure; +import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.errors.Success; import org.simantics.scl.compiler.module.ImportDeclaration; import org.simantics.scl.compiler.module.Module; import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor; +import org.simantics.scl.compiler.module.repository.UpdateListener.Observable; import org.simantics.scl.compiler.runtime.RuntimeEnvironment; import org.simantics.scl.compiler.runtime.RuntimeEnvironmentImpl; import org.simantics.scl.compiler.runtime.RuntimeModule; @@ -36,6 +39,7 @@ import org.simantics.scl.compiler.top.ValueNotFound; import org.simantics.scl.compiler.types.Types; import gnu.trove.map.hash.THashMap; +import gnu.trove.map.hash.TObjectLongHashMap; import gnu.trove.procedure.TObjectObjectProcedure; import gnu.trove.set.hash.THashSet; @@ -67,9 +71,9 @@ public class ModuleRepository { PENDING_MODULES.get().remove(moduleName); } - private class ModuleEntry implements UpdateListener { + private class ModuleEntry extends UpdateListener implements Observable { final String moduleName; - WeakHashMap listeners = new WeakHashMap(); + THashSet listeners = new THashSet(); ModuleSource source; Failable compilationResult; @@ -80,14 +84,20 @@ public class ModuleRepository { } synchronized void addListener(UpdateListener listener) { - if(listener != null) - listeners.put(listener, null); + if(listener == null || listeners == null) + return; + listeners.add(listener); + listener.addObservable(this); + } + + public synchronized void removeListener(UpdateListener listener) { + if (listeners == null) + return; + listeners.remove(listener); } @Override public void notifyAboutUpdate() { - if (listeners == null) - return; ArrayList externalListeners = new ArrayList(); notifyAboutUpdate(externalListeners); for(UpdateListener listener : externalListeners) @@ -95,18 +105,26 @@ public class ModuleRepository { } synchronized void notifyAboutUpdate(ArrayList externalListeners) { + stopListening(); + if (listeners == null) + return; if(moduleCache.get(moduleName) == this) { moduleCache.remove(moduleName); if(SCLCompilerConfiguration.TRACE_MODULE_UPDATE) { System.out.println("Invalidate " + moduleName); - for(UpdateListener l : listeners.keySet()) + for(UpdateListener l : listeners) System.out.println(" " + l); } - for(UpdateListener l : listeners.keySet()) + THashSet listenersCopy = listeners; + listeners = null; + for(UpdateListener l : listenersCopy) + l.stopListening(); + for(UpdateListener l : listenersCopy) if(l instanceof ModuleEntry) ((ModuleEntry)l).notifyAboutUpdate(externalListeners); - else + else { externalListeners.add(l); + } } } @@ -145,7 +163,7 @@ public class ModuleRepository { Collection dependencies = module.getDependencies(); THashMap moduleEntries; try { - moduleEntries = getModuleEntries(dependencies.toArray(new ImportDeclaration[dependencies.size()]), null); + moduleEntries = getModuleEntries(null, dependencies.toArray(new ImportDeclaration[dependencies.size()]), null, false); } catch (ImportFailureException e) { throw new InternalCompilerError(e); } @@ -159,7 +177,7 @@ public class ModuleRepository { if(parentModule != null) parentModules.add(parentModule); }*/ - RuntimeModule rm = new RuntimeModule(module, parentModules, source.getClassLoader()); + RuntimeModule rm = new RuntimeModule(module, parentModules, module.getParentClassLoader()); ModuleInitializer initializer = module.getModuleInitializer(); if(initializer != null) try { @@ -176,10 +194,11 @@ public class ModuleRepository { return runtimeModule; } - public void dispose() { + public synchronized void dispose() { if (listeners != null) listeners.clear(); listeners = null; + stopListening(); source = null; compilationResult = null; if (runtimeModule != null) { @@ -219,7 +238,7 @@ public class ModuleRepository { public Failable getRuntimeModule(String moduleName) { return getRuntimeModule(moduleName, null); } - + private ModuleEntry getModuleEntry(String moduleName, UpdateListener listener) { /* It is deliberate that the following code does not try to prevent * simultaneous compilation of the same module. This is because in @@ -239,22 +258,35 @@ public class ModuleRepository { } private THashMap getModuleEntries( + CompilationContext compilationContext, ImportDeclaration[] imports, - UpdateListener listener) throws ImportFailureException { + UpdateListener listener, + boolean robustly) throws ImportFailureException { THashMap result = new THashMap(); Collection failures = null; + TObjectLongHashMap originalImports = new TObjectLongHashMap(); ArrayList stack = new ArrayList(imports.length); - for(ImportDeclaration import_ : imports) + for(ImportDeclaration import_ : imports) { stack.add(import_); + originalImports.put(import_.moduleName, import_.location); + } while(!stack.isEmpty()) { ImportDeclaration import_ = stack.remove(stack.size()-1); if(!result.containsKey(import_.moduleName)) { - ModuleEntry entry = getModuleEntry(import_.moduleName, listener); + boolean originalImport = originalImports.contains(import_.moduleName); + ModuleEntry entry = getModuleEntry(import_.moduleName, originalImport ? listener : null); Failable compilationResult = entry.compilationResult; if(compilationResult.didSucceed()) { result.put(import_.moduleName, entry); stack.addAll(compilationResult.getResult().getDependencies()); + if(originalImport) { + String deprecation = compilationResult.getResult().getDeprecation(); + if(deprecation != null && compilationContext != null) { + long location = originalImport ? originalImports.get(import_.moduleName) : Locations.NO_LOCATION; + compilationContext.errorLog.logWarning(location, "Deprecated module " + import_.moduleName + (deprecation.isEmpty() ? "." : ": " + deprecation)); + } + } } else { if(failures == null) @@ -267,7 +299,7 @@ public class ModuleRepository { } } - if(failures != null) + if(failures != null && !robustly) throw new ImportFailureException(failures); return result; @@ -300,11 +332,32 @@ public class ModuleRepository { public Environment createEnvironment( ImportDeclaration[] imports, UpdateListener listener) throws ImportFailureException { - THashMap entries = getModuleEntries(imports, listener); + return createEnvironment(null, imports, listener); + } + + public Environment createEnvironment( + CompilationContext compilationContext, + ImportDeclaration[] imports, + UpdateListener listener) throws ImportFailureException { + THashMap entries = getModuleEntries(compilationContext, imports, listener, false); THashMap moduleMap = mapEntriesToModules(entries); return createEnvironment(moduleMap, imports); } + public Environment createEnvironmentRobustly( + CompilationContext compilationContext, + ImportDeclaration[] imports, + UpdateListener listener) { + try { + THashMap entries = getModuleEntries(compilationContext, imports, listener, true); + THashMap moduleMap = mapEntriesToModules(entries); + return createEnvironment(moduleMap, imports); + } catch(ImportFailureException e) { + // Should not happen because of robust flag + return EmptyEnvironment.INSTANCE; + } + } + public Environment createEnvironment( EnvironmentSpecification specification, UpdateListener listener) throws ImportFailureException { @@ -316,6 +369,10 @@ public class ModuleRepository { return createRuntimeEnvironment(environmentSpecification, parentClassLoader, null); } + public RuntimeEnvironment createRuntimeEnvironment(EnvironmentSpecification environmentSpecification) throws ImportFailureException { + return createRuntimeEnvironment(environmentSpecification, getClass().getClassLoader()); + } + public RuntimeEnvironment createRuntimeEnvironment( EnvironmentSpecification environmentSpecification, ClassLoader parentClassLoader, @@ -330,14 +387,15 @@ public class ModuleRepository { ImportDeclaration[] imports, ClassLoader parentClassLoader, UpdateListener listener) throws ImportFailureException { - THashMap entries = getModuleEntries(imports, listener); + THashMap entries = getModuleEntries(null, imports, listener, false); THashMap moduleMap = mapEntriesToModules(entries); Environment environment = createEnvironment(moduleMap, imports); THashMap runtimeModuleMap = mapEntriesToRuntimeModules(entries); return new RuntimeEnvironmentImpl(environment, parentClassLoader, runtimeModuleMap); } - private static Environment createEnvironment(THashMap moduleMap, + private static Environment createEnvironment( + THashMap moduleMap, ImportDeclaration[] imports) { NamespaceSpec spec = new NamespaceSpec(); for(ImportDeclaration import_ : imports)