package jetbrains.mps.ide.java.newparser; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.module.SRepository; import org.jetbrains.mps.openapi.module.ModelAccess; import java.util.Map; import java.util.Set; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import java.util.List; import jetbrains.mps.vfs.IFile; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.messages.IMessageHandler; import java.util.Collections; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.HashSet; import jetbrains.mps.internal.collections.runtime.IVisitor; import org.jetbrains.mps.openapi.model.EditableSModel; import org.jetbrains.mps.openapi.util.ProgressMonitor; import java.io.IOException; import jetbrains.mps.messages.Message; import jetbrains.mps.messages.MessageKind; import jetbrains.mps.project.AbstractModule; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.extapi.model.SModelBase; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.internal.collections.runtime.IMapping; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import org.jetbrains.mps.openapi.model.SReference; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.internal.collections.runtime.ISequence; import org.jetbrains.mps.openapi.language.SAbstractConcept; import jetbrains.mps.internal.collections.runtime.ITranslator2; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.smodel.DynamicReference; import jetbrains.mps.internal.collections.runtime.ISelector; import jetbrains.mps.vfs.IFileUtils; import org.jetbrains.mps.openapi.model.SNodeReference; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; import jetbrains.mps.typesystem.inference.TypeChecker; import jetbrains.mps.lang.smodel.generator.smodelAdapter.AttributeOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.IAttributeDescriptor; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations; import jetbrains.mps.smodel.behaviour.BHReflection; import jetbrains.mps.core.aspects.behaviour.SMethodTrimmedId; import jetbrains.mps.smodel.StaticReference; import jetbrains.mps.scope.Scope; import java.util.Deque; import jetbrains.mps.internal.collections.runtime.DequeSequence; import java.util.LinkedList; import org.jetbrains.mps.openapi.model.SModelReference; import jetbrains.mps.smodel.SModelInternal; import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; import jetbrains.mps.persistence.DefaultModelRoot; import jetbrains.mps.extapi.persistence.SourceRoot; import jetbrains.mps.extapi.persistence.datasource.DataSourceFactoryFromName; import org.jetbrains.mps.openapi.persistence.ModelFactory; import jetbrains.mps.extapi.persistence.ModelFactoryService; import org.jetbrains.mps.openapi.model.SModelName; import jetbrains.mps.persistence.ModelCannotBeCreatedException; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.persistence.DataSource; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.persistence.ModelRoot; import jetbrains.mps.persistence.FilePerRootDataSource; import org.jetbrains.mps.openapi.persistence.datasource.DataSourceType; import jetbrains.mps.extapi.persistence.datasource.PreinstalledDataSourceTypes; import jetbrains.mps.extapi.persistence.SourceRootKinds; import jetbrains.mps.util.FileUtil; import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; public class JavaToMpsConverter { private static final Logger LOG = LogManager.getLogger(JavaToMpsConverter.class); private SModule myModule; private SModel myModel; private boolean myCreatePerRoot; private boolean myCreateInplace; private SRepository myRepository; private ModelAccess myModelAccess; private JavaParser myJavaParser = new JavaParser(); private Map<String, Set<SNode>> classesPerPackage = MapSequence.fromMap(new HashMap<String, Set<SNode>>()); private Map<String, List<IFile>> filesPerPackage = MapSequence.fromMap(new HashMap<String, List<IFile>>()); private Map<String, IFile> packageDirs = MapSequence.fromMap(new HashMap<String, IFile>()); private List<SModel> myModels; private List<SNode> myRoots = ListSequence.fromList(new ArrayList<SNode>()); private List<SNode> myAttachedRoots = ListSequence.fromList(new ArrayList<SNode>()); private Map<SNode, SModel> myRootsToModels = MapSequence.fromMap(new HashMap<SNode, SModel>()); private List<IFile> mySuccessfulFiles = ListSequence.fromList(new ArrayList<IFile>()); private boolean wasDefaultPkg = false; private int myRootCount = 0; private IMessageHandler myMessageHandler; public JavaToMpsConverter(SModule module, SRepository repository, IMessageHandler messageHandler) { this(module, repository, false, false, messageHandler); } public Set<SNode> getRootsBuilt() { return Collections.<SNode>unmodifiableSet(SetSequence.fromSetWithValues(new HashSet<SNode>(), myAttachedRoots)); } public JavaToMpsConverter(SModule module, SRepository repository, boolean perRoot, boolean inPlace, IMessageHandler messageHandler) { // currently perRoot==false and inPlace==true doesn't make it in-place // because of how DefaultModelRoot is implemented myModule = module; myCreatePerRoot = perRoot; myCreateInplace = inPlace; myRepository = repository; myModelAccess = repository.getModelAccess(); myMessageHandler = messageHandler; } public JavaToMpsConverter(SModel model, SRepository repository, IMessageHandler messageHandler) { myModel = model; myModule = model.getModule(); myRepository = repository; myModelAccess = repository.getModelAccess(); myMessageHandler = messageHandler; } public void saveAll() { ListSequence.fromList(myModels).visitAll(new IVisitor<SModel>() { public void visit(SModel it) { ((EditableSModel) it).setChanged(true); ((EditableSModel) it).save(); } }); } public void convertToMps(List<IFile> files, ProgressMonitor progress) throws JavaParseException, IOException { progress.start("Converting...", 31); // first we build AST ProgressMonitor parseProgress = progress.subTask(1); parseProgress.start("Parsing...", ListSequence.fromList(files).count()); for (IFile file : ListSequence.fromList(files)) { try { parseFile(file); parseProgress.advance(1); } catch (JavaParseException e) { Message msg = new Message(MessageKind.ERROR, String.format("Parse error: %s", e.getMessage())); if (e.getCause() != null) { msg.setException(e.getCause()); } myMessageHandler.handle(msg); } catch (IOException e) { myMessageHandler.handle(new Message(MessageKind.ERROR, String.format("IO error when converting (java->mps) file %s", file.getName())).setException(e)); } } parseProgress.done(); int rootCount = 0; // now we attach the models and try to resolve myModelAccess.runWriteAction(new Runnable() { public void run() { ((AbstractModule) myModule).addDependency(PersistenceFacade.getInstance().createModuleReference("6354ebe7-c22a-4a0f-ac54-50b52ab9b065(JDK)"), false); if (myModel == null) { myModels = ListSequence.fromList(new ArrayList<SModel>()); for (String pakage : MapSequence.fromMap(classesPerPackage).keySet()) { final SModel model = getModel(pakage, MapSequence.fromMap(packageDirs).get(pakage)); if (model == null) { continue; } Set<SNode> roots = MapSequence.fromMap(classesPerPackage).get(pakage); SetSequence.fromSet(roots).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { MapSequence.fromMap(myRootsToModels).put(it, model); } }); ListSequence.fromList(mySuccessfulFiles).addSequence(ListSequence.fromList(MapSequence.fromMap(filesPerPackage).get(pakage))); ListSequence.fromList(myAttachedRoots).addSequence(SetSequence.fromSet(roots)); ListSequence.fromList(myModels).addElement(model); } } else { // todo maybe do something clever with packages <-> java imports // with regard to model where we put it all for (SNode root : ListSequence.fromList(myRoots)) { // todo be more accurate with duplicates MapSequence.fromMap(myRootsToModels).put(root, myModel); } myModels = Sequence.fromIterable(Sequence.<SModel>singleton(myModel)).toListSequence(); myAttachedRoots = myRoots; } } }); IncrementalModelAccess modelAccess; if (myModelAccess.isCommandAction()) { modelAccess = IncrementalModelAccess.INSIDE_COMMAND_OR_UPDATE_MODE; } else if (myModel != null) { // import into single already existing model; use proper command for replacing nodes modelAccess = new IncrementalModelAccessWithCommand(myModelAccess, myModels, myMessageHandler); } else { modelAccess = new IncrementalModelAccessWithoutCommand(myModelAccess, myModels, myMessageHandler); } // actually attach roots modelAccess.replaceNodes(new Runnable() { public void run() { ListSequence.fromList(myModels).visitAll(new IVisitor<SModel>() { public void visit(SModel it) { ((SModelBase) it).addLanguage(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage")); ((SModelBase) it).addLanguage(MetaAdapterFactory.getLanguage(0xf280165065d5424eL, 0xbb1b463a8781b786L, "jetbrains.mps.baseLanguage.javadoc")); } }); MapSequence.fromMap(myRootsToModels).visitAll(new IVisitor<IMapping<SNode, SModel>>() { public void visit(IMapping<SNode, SModel> it) { SModel m = it.value(); SNode root = it.key(); SModelOperations.addRootNode(m, root); } }); } }); myRootCount = myAttachedRoots.size(); ProgressMonitor resolveProgress = progress.subTask(30); tryResolveRefs(myAttachedRoots, FeatureKind.CLASS, resolveProgress, modelAccess); progress.done(); } public void tryResolveRefs(Iterable<SNode> nodes, FeatureKind level, ProgressMonitor progress) { tryResolveRefs(nodes, level, progress, IncrementalModelAccess.INSIDE_COMMAND_OR_UPDATE_MODE); } private void tryResolveRefs(Iterable<SNode> nodes, FeatureKind level, ProgressMonitor progress, IncrementalModelAccess modelAccess) { // 11 - number of progress.subTask() below progress.start("Resolving...", 11); if (FeatureKind.CLASS.equals(level)) { resolveUpdatePass("top level references", nodes, new _FunctionTypes._return_P1_E0<Iterable<SReference>, SNode>() { public Iterable<SReference> invoke(SNode node) { return getTopLevelRefs(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))); } }, progress.subTask(1), modelAccess); } if (FeatureKind.CLASS.equals(level) || FeatureKind.CLASS_CONTENT.equals(level)) { resolveUpdatePass("field/method type references", nodes, new _FunctionTypes._return_P1_E0<Iterable<SReference>, SNode>() { public Iterable<SReference> invoke(SNode node) { return getFieldAndMethodTypeRefs(SNodeOperations.cast(node, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x112574373bdL, "jetbrains.mps.baseLanguage.structure.ClassifierMember"))); } }, progress.subTask(1), modelAccess); } // this happens on the level of expressions, but relies on top-level references (from class and method // declarations) having been resolved JavaParser.tryResolveUnknowns(myAttachedRoots, progress.subTask(1), modelAccess); resolveUpdatePass("type references", nodes, new _FunctionTypes._return_P1_E0<Iterable<SReference>, SNode>() { public Iterable<SReference> invoke(SNode node) { return getVarTypeRefs(node); } }, progress.subTask(1), modelAccess); resolveUpdatePass("variable references", nodes, new _FunctionTypes._return_P1_E0<Iterable<SReference>, SNode>() { public Iterable<SReference> invoke(SNode node) { return getVariableRefs(node); } }, progress.subTask(1), modelAccess); resolveUpdatePass("dot operands", nodes, new _FunctionTypes._return_P1_E0<ISequence<SReference>, SNode>() { public ISequence<SReference> invoke(SNode node) { return ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, "jetbrains.mps.baseLanguage.structure.DotExpression"), false, new SAbstractConcept[]{})).translate(new ITranslator2<SNode, SReference>() { public Iterable<SReference> translate(SNode it) { return deepReferences(SLinkOperations.getTarget(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46a4416L, "operand"))); } }); } }, progress.subTask(1), modelAccess); resolveUpdatePass("dot operations", nodes, new _FunctionTypes._return_P1_E0<ISequence<SReference>, SNode>() { public ISequence<SReference> invoke(SNode node) { return ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, "jetbrains.mps.baseLanguage.structure.DotExpression"), false, new SAbstractConcept[]{})).translate(new ITranslator2<SNode, SReference>() { public Iterable<SReference> translate(SNode it) { if (Sequence.fromIterable(deepReferences(SLinkOperations.getTarget(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46a4416L, "operand")))).any(new IWhereFilter<SReference>() { public boolean accept(SReference it) { return (SReference) it instanceof DynamicReference; } })) { return ListSequence.fromList(new ArrayList<SReference>()); } else { if (SNodeOperations.isInstanceOf(SLinkOperations.getTarget(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46b36c4L, "operation")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b483d77aL, "jetbrains.mps.baseLanguage.structure.FieldReferenceOperation"))) { return Sequence.<SReference>singleton(SNodeOperations.getReference(SNodeOperations.cast(SLinkOperations.getTarget(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46b36c4L, "operation")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b483d77aL, "jetbrains.mps.baseLanguage.structure.FieldReferenceOperation")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b483d77aL, 0x116b484a653L, "fieldDeclaration"))); } else if (SNodeOperations.isInstanceOf(SLinkOperations.getTarget(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46b36c4L, "operation")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x118154a6332L, "jetbrains.mps.baseLanguage.structure.InstanceMethodCallOperation"))) { return Sequence.<SReference>singleton(SNodeOperations.getReference(SNodeOperations.cast(SLinkOperations.getTarget(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46b36c4L, "operation")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x118154a6332L, "jetbrains.mps.baseLanguage.structure.InstanceMethodCallOperation")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301adL, "baseMethodDeclaration"))); } else { return ListSequence.fromList(new ArrayList<SReference>()); } } } }); } }, progress.subTask(1), modelAccess); resolveUpdatePass("classifiers in static access", nodes, new _FunctionTypes._return_P1_E0<List<SReference>, SNode>() { public List<SReference> invoke(SNode node) { List<SReference> result = ListSequence.fromList(new ArrayList<SReference>()); ListSequence.fromList(result).addSequence(ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf09L, "jetbrains.mps.baseLanguage.structure.StaticMethodCall"), false, new SAbstractConcept[]{})).select(new ISelector<SNode, SReference>() { public SReference select(SNode it) { return SNodeOperations.getReference(it, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf09L, 0x10a7588b546L, "classConcept")); } })); ListSequence.fromList(result).addSequence(ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940c80846L, "jetbrains.mps.baseLanguage.structure.StaticFieldReference"), false, new SAbstractConcept[]{})).select(new ISelector<SNode, SReference>() { public SReference select(SNode it) { return SNodeOperations.getReference(it, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940c80846L, 0x10a75869f9bL, "classifier")); } })); return result; } }, progress.subTask(1), modelAccess); resolveUpdatePass("static member references", nodes, new _FunctionTypes._return_P1_E0<List<SReference>, SNode>() { public List<SReference> invoke(SNode node) { List<SReference> result = ListSequence.fromList(new ArrayList<SReference>()); ListSequence.fromList(result).addSequence(ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf09L, "jetbrains.mps.baseLanguage.structure.StaticMethodCall"), false, new SAbstractConcept[]{})).select(new ISelector<SNode, SReference>() { public SReference select(SNode it) { return SNodeOperations.getReference(it, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301adL, "baseMethodDeclaration")); } })); ListSequence.fromList(result).addSequence(ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940c80846L, "jetbrains.mps.baseLanguage.structure.StaticFieldReference"), false, new SAbstractConcept[]{})).select(new ISelector<SNode, SReference>() { public SReference select(SNode it) { return SNodeOperations.getReference(it, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); } })); return result; } }, progress.subTask(1), modelAccess); resolveUpdatePass("remaining references", nodes, new _FunctionTypes._return_P1_E0<Iterable<SReference>, SNode>() { public Iterable<SReference> invoke(SNode node) { return deepReferences(node); } }, progress.subTask(1), modelAccess); codeTransformPass(nodes, progress.subTask(1), modelAccess); removeJavaImportsPass(nodes, progress.subTask(1), modelAccess); progress.done(); } public List<IFile> getSuccessfulFiles() { return mySuccessfulFiles; } public List<SModel> getModels() { return myModels; } private void parseFile(IFile file) throws JavaParseException, IOException { String contents = IFileUtils.getTextContents(file); JavaParser.JavaParseResult parseResult = myJavaParser.parseCompilationUnit(contents); String pkg = parseResult.getPackage(); if (pkg == null) { // default package (i.e. none), bad if (!(wasDefaultPkg)) { myMessageHandler.handle(new Message(MessageKind.ERROR, String.format("default package is not supported in java source directory input (first such file in dir: %s)", file.getName()))); wasDefaultPkg = true; } return; } IFile dir = file.getParent(); if (!(DirParser.checkPackageMatchesSourceDirectory(pkg, dir))) { myMessageHandler.handle(new Message(MessageKind.ERROR, String.format("package %s doesn't match directory %s (in file %s)", pkg, dir.getPath(), file.getName()))); return; } IFile currentDir = MapSequence.fromMap(packageDirs).get(pkg); // if it's already set, leave it as is // it means one package is present in more than one dir, but we will have only one model // and it has to be somewhere if (currentDir == null) { MapSequence.fromMap(packageDirs).put(pkg, dir); } Iterable<SNode> roots = parseResult.getNodes(); Set<SNode> classesInPackage = MapSequence.fromMap(classesPerPackage).get(pkg); if (classesInPackage == null) { classesInPackage = SetSequence.fromSet(new HashSet<SNode>(Sequence.fromIterable(roots).count())); MapSequence.fromMap(classesPerPackage).put(pkg, classesInPackage); } SetSequence.fromSet(classesInPackage).addSequence(Sequence.fromIterable(roots)); List<IFile> files = MapSequence.fromMap(filesPerPackage).get(pkg); if (files == null) { files = ListSequence.fromList(new ArrayList<IFile>()); MapSequence.fromMap(filesPerPackage).put(pkg, files); } ListSequence.fromList(files).addElement(file); ListSequence.fromList(myRoots).addSequence(Sequence.fromIterable(roots)); myRootCount += Sequence.fromIterable(roots).count(); } private Set<SReference> myVisitedRefs = SetSequence.fromSet(new HashSet<SReference>()); private void resolveUpdatePass(String name, final Iterable<SNode> nodes, final _FunctionTypes._return_P1_E0<? extends Iterable<SReference>, ? super SNode> extractor, final ProgressMonitor progress, IncrementalModelAccess modelAccess) { final Map<SNodeReference, List<SReference>> resolveMap = MapSequence.fromMap(new HashMap<SNodeReference, List<SReference>>()); progress.start(name, Sequence.fromIterable(nodes).count() + 1); modelAccess.accessModel(new Runnable() { public void run() { for (SNode node : Sequence.fromIterable(nodes)) { if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, "jetbrains.mps.lang.core.structure.INamedConcept"))) { progress.step("class: " + SPropertyOperations.getString(SNodeOperations.cast(node, MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, "jetbrains.mps.lang.core.structure.INamedConcept")), MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"))); } Iterable<SReference> refs = extractor.invoke(node); resolveRefs(refs, resolveMap); SetSequence.fromSet(myVisitedRefs).addSequence(Sequence.fromIterable(refs)); progress.advance(1); } } }); progress.step("updating references..."); modelAccess.replaceReferences(new Runnable() { public void run() { updateReference(resolveMap); } }); progress.advance(1); progress.done(); } private void codeTransformPass(final Iterable<SNode> nodes, final ProgressMonitor progress, IncrementalModelAccess modelAccess) { progress.start("Code transforms", Sequence.fromIterable(nodes).count() * 5 + 1); final Wrappers._T<TypeChecker> typeChecker = new Wrappers._T<TypeChecker>(TypeChecker.getInstance()); // all this can be replaced by one map old -> new final List<SNode> toReplaceWithArrayLength = ListSequence.fromList(new ArrayList<SNode>()); final List<SNode> toReplaceWithArrayClone = ListSequence.fromList(new ArrayList<SNode>()); final Map<SNode, SNode> enumConstRefs = MapSequence.fromMap(new HashMap<SNode, SNode>()); final Map<SNode, SNode> staticMethodQualifiers = MapSequence.fromMap(new HashMap<SNode, SNode>()); final Map<SNode, SNode> staticFieldQualifiers = MapSequence.fromMap(new HashMap<SNode, SNode>()); modelAccess.accessModel(new Runnable() { public void run() { for (SNode node : Sequence.fromIterable(nodes)) { for (SNode fieldRefOp : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b483d77aL, "jetbrains.mps.baseLanguage.structure.FieldReferenceOperation"), false, new SAbstractConcept[]{}))) { SReference fieldRef = SNodeOperations.getReference(fieldRefOp, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b483d77aL, 0x116b484a653L, "fieldDeclaration")); if (!((fieldRef instanceof DynamicReference && "length".equals((((DynamicReference) fieldRef).getResolveInfo()))))) { continue; } SNode operand = SLinkOperations.getTarget(SNodeOperations.cast(SNodeOperations.getParent(fieldRefOp), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, "jetbrains.mps.baseLanguage.structure.DotExpression")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46a4416L, "operand")); Iterable<SReference> operandRefs = SNodeOperations.getReferences(operand); if (Sequence.fromIterable(operandRefs).any(new IWhereFilter<SReference>() { public boolean accept(SReference it) { return it instanceof DynamicReference; } })) { continue; } SNode operandType = typeChecker.value.getTypeOf(operand); if (SNodeOperations.isInstanceOf(operandType, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940d819f7L, "jetbrains.mps.baseLanguage.structure.ArrayType"))) { ListSequence.fromList(toReplaceWithArrayLength).addElement(fieldRefOp); } } progress.advance(1); for (SNode imco : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x118154a6332L, "jetbrains.mps.baseLanguage.structure.InstanceMethodCallOperation"), false, new SAbstractConcept[]{}))) { SReference fieldRef = SNodeOperations.getReference(imco, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301adL, "baseMethodDeclaration")); if (!((fieldRef instanceof DynamicReference && "clone".equals((((DynamicReference) fieldRef).getResolveInfo()))))) { continue; } SNode operand = SLinkOperations.getTarget(SNodeOperations.cast(SNodeOperations.getParent(imco), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, "jetbrains.mps.baseLanguage.structure.DotExpression")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46a4416L, "operand")); Iterable<SReference> operandRefs = SNodeOperations.getReferences(operand); if (Sequence.fromIterable(operandRefs).any(new IWhereFilter<SReference>() { public boolean accept(SReference it) { return it instanceof DynamicReference; } })) { continue; } SNode operandType = typeChecker.value.getTypeOf(operand); if (SNodeOperations.isInstanceOf(operandType, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940d819f7L, "jetbrains.mps.baseLanguage.structure.ArrayType"))) { ListSequence.fromList(toReplaceWithArrayClone).addElement(imco); } } progress.advance(1); for (SNode localCall : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x6c6b6a1e379f9404L, "jetbrains.mps.baseLanguage.structure.LocalMethodCall"), false, new SAbstractConcept[]{}))) { SNode smc = transformLocalCall(localCall); if ((smc == null)) { continue; } MapSequence.fromMap(staticMethodQualifiers).put(localCall, smc); } progress.advance(1); typeChecker.value = TypeChecker.getInstance(); for (SNode swicthCase : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10ef02cdd1bL, "jetbrains.mps.baseLanguage.structure.SwitchCase"), false, new SAbstractConcept[]{}))) { SNode subst = transformUnqualifedEnumUnderSwitch(swicthCase, typeChecker.value); if ((subst == null)) { continue; } MapSequence.fromMap(enumConstRefs).put(SNodeOperations.cast(SLinkOperations.getTarget(swicthCase, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10ef02cdd1bL, 0x10ef02d67cfL, "expression")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")), subst); } progress.advance(1); for (SNode varRef : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference"), false, new SAbstractConcept[]{}))) { SNode exp = transformLocalNameRef(varRef); if ((exp != null)) { MapSequence.fromMap(staticFieldQualifiers).put(varRef, exp); continue; } SNode subst = transformUnqualifedEnum(varRef); if ((subst == null)) { continue; } MapSequence.fromMap(enumConstRefs).put(varRef, subst); } progress.advance(1); } } }); progress.step("updating models..."); modelAccess.replaceNodes(new Runnable() { public void run() { for (SNode fieldRefOp : ListSequence.fromList(toReplaceWithArrayLength)) { SNodeOperations.replaceWithNewChild(fieldRefOp, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x1197781411dL, "jetbrains.mps.baseLanguage.structure.ArrayLengthOperation")); } for (SNode imco : ListSequence.fromList(toReplaceWithArrayClone)) { SNodeOperations.replaceWithNewChild(imco, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x483ee9d7f09580d6L, "jetbrains.mps.baseLanguage.structure.ArrayCloneOperation")); } for (IMapping<SNode, SNode> pair : MapSequence.fromMap(enumConstRefs)) { SNodeOperations.replaceWithAnother(pair.key(), pair.value()); } for (IMapping<SNode, SNode> pair : MapSequence.fromMap(staticMethodQualifiers)) { SNodeOperations.replaceWithAnother(pair.key(), pair.value()); } for (IMapping<SNode, SNode> pair : MapSequence.fromMap(staticFieldQualifiers)) { SNodeOperations.replaceWithAnother(pair.key(), pair.value()); } } }); progress.advance(1); progress.done(); } private void removeJavaImportsPass(final Iterable<SNode> nodes, final ProgressMonitor progress, IncrementalModelAccess modelAccess) { progress.start("Removing java imports", Sequence.fromIterable(nodes).count() + 1); final Map<SNode, Iterable<SNode>> toRemove = MapSequence.fromMap(new HashMap<SNode, Iterable<SNode>>()); modelAccess.accessModel(new Runnable() { public void run() { for (SNode node : Sequence.fromIterable(nodes)) { progress.advance(1); if (!(SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))) { continue; } if ((AttributeOperations.getAttribute(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, "jetbrains.mps.baseLanguage.structure.JavaImports"))) == null)) { continue; } MapSequence.fromMap(toRemove).put(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), getImportsToRemove(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))); } } }); modelAccess.replaceNodes(new Runnable() { public void run() { for (SNode node : SetSequence.fromSet(MapSequence.fromMap(toRemove).keySet())) { Iterable<SNode> imps = MapSequence.fromMap(toRemove).get(node); Sequence.fromIterable(imps).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { SNodeOperations.deleteNode(it); } }); SNode importAnnotation = AttributeOperations.getAttribute(node, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, "jetbrains.mps.baseLanguage.structure.JavaImports"))); if (ListSequence.fromList(SLinkOperations.getChildren(importAnnotation, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, 0x64c0181e6020a7L, "entries"))).isEmpty()) { SNodeOperations.deleteNode(importAnnotation); } } } }); progress.advance(1); progress.done(); } private SNode transformUnqualifedEnum(SNode varRef) { // FIXME share or re-use code with the corresponding NonTypesystemRule if (!(SConceptOperations.isExactly(SNodeOperations.asSConcept(SNodeOperations.getConcept(varRef)), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")))) { return null; } SReference ref = SNodeOperations.getReference(varRef, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); if (!(ref instanceof DynamicReference)) { return null; } if (ref.getTargetNode() != null) { return null; } // now we can try to search SNode gateway = SConceptOperations.createNewNode(SNodeOperations.asInstanceConcept(MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x70ea1dc4c5721865L, "jetbrains.mps.baseLanguage.structure.IYetUnresolved"))); String enumConstName = ((DynamicReference) ref).getResolveInfo(); for (SNode enclosingEnum : ListSequence.fromList(SNodeOperations.getNodeAncestors(varRef, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass"), false))) { SNode enumConstRef = makeEnumConstRef(enclosingEnum, enumConstName); if (enumConstRef != null) { return enumConstRef; } } SNode root = SNodeOperations.getContainingRoot(varRef); if (!(SNodeOperations.isInstanceOf(root, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))) { return null; } SNode javaImports = AttributeOperations.getAttribute(SNodeOperations.cast(root, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, "jetbrains.mps.baseLanguage.structure.JavaImports"))); if ((javaImports == null)) { return null; } for (SNode singleNameImport : Sequence.fromIterable(((Iterable<SNode>) BHReflection.invoke(javaImports, SMethodTrimmedId.create("staticSingleName", MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, "jetbrains.mps.baseLanguage.structure.JavaImports"), "4ykJ8Y6iJRa"))))) { if (!(enumConstName.equals(((String) BHReflection.invoke(singleNameImport, SMethodTrimmedId.create("lastToken", MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x5a98df4004080866L, "jetbrains.mps.baseLanguage.structure.Tokens"), "17WpDCYLyrY")))))) { continue; } String enumClassCandidateName = ((String) BHReflection.invoke(singleNameImport, SMethodTrimmedId.create("withoutLastToken", MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x5a98df4004080866L, "jetbrains.mps.baseLanguage.structure.Tokens"), "5ll4uk6512$"))); SNode enumClassCandidate = ((SNode) BHReflection.invoke(gateway, SMethodTrimmedId.create("findClass", MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x70ea1dc4c5721865L, "jetbrains.mps.baseLanguage.structure.IYetUnresolved"), "4ykJ8Y83bdr"), varRef, enumClassCandidateName)); if ((enumClassCandidate == null)) { // seems like there is no need to continue // we had import of the form: import static <class>.<ourName> // if we meet <ourName> in java code then it must strictly reference this import, not any other return null; } if (!(SNodeOperations.isInstanceOf(enumClassCandidate, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass")))) { return null; } SNode result = makeEnumConstRef(SNodeOperations.cast(enumClassCandidate, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass")), enumConstName); if (result != null) { return null; } } for (SNode onDemandImport : Sequence.fromIterable(((Iterable<SNode>) BHReflection.invoke(javaImports, SMethodTrimmedId.create("staticOnDemand", MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, "jetbrains.mps.baseLanguage.structure.JavaImports"), "4ykJ8Y6iCVz"))))) { SNode claz = ((SNode) BHReflection.invoke(gateway, SMethodTrimmedId.create("findClass", MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x70ea1dc4c5721865L, "jetbrains.mps.baseLanguage.structure.IYetUnresolved"), "4ykJ8Y83bdr"), varRef, SPropertyOperations.getString(onDemandImport, MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x5a98df4004080866L, 0x1996ec29712bdd92L, "tokens")))); if ((claz == null)) { continue; } if (!(SNodeOperations.isInstanceOf(claz, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass")))) { continue; } SNode result = makeEnumConstRef(SNodeOperations.cast(claz, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass")), enumConstName); if (result != null) { return null; } } return null; } private SNode makeEnumConstRef(SNode enumClass, final String constName) { // Q: maybe not findFirst, but rather fail if there are more than one... SNode enumConst = ListSequence.fromList(SLinkOperations.getChildren(SNodeOperations.cast(enumClass, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, 0xfc367503acL, "enumConstant"))).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return constName.equals(SPropertyOperations.getString(it, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"))); } }); if ((enumConst == null)) { return null; } SNode result = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc37588bc8L, "jetbrains.mps.baseLanguage.structure.EnumConstantReference")); SLinkOperations.setTarget(result, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc37588bc8L, 0x10a758428feL, "enumClass"), SNodeOperations.cast(enumClass, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass"))); SLinkOperations.setTarget(result, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc37588bc8L, 0xfc37588bcaL, "enumConstantDeclaration"), enumConst); return result; } private SNode transformUnqualifedEnumUnderSwitch(SNode switchCase, TypeChecker typeChecker) { // FIXME share or re-use code with the corresponding NonTypesystemRule SNode caseExp = SLinkOperations.getTarget(switchCase, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10ef02cdd1bL, 0x10ef02d67cfL, "expression")); if (!(SNodeOperations.isInstanceOf(caseExp, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")))) { return null; } SReference ref = SNodeOperations.getReference(SNodeOperations.cast(caseExp, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); if (!(ref instanceof DynamicReference)) { return null; } final String enumConstName = ((DynamicReference) ref).getResolveInfo(); SNode scrutenee = SLinkOperations.getTarget(SNodeOperations.getNodeAncestor(caseExp, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10ef02a8c6aL, "jetbrains.mps.baseLanguage.structure.SwitchStatement"), false, false), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10ef02a8c6aL, 0x10ef02ec241L, "expression")); if ((scrutenee == null)) { return null; } SNode scruteneeType = typeChecker.getTypeOf(scrutenee); if (!(SNodeOperations.isInstanceOf(scruteneeType, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, "jetbrains.mps.baseLanguage.structure.ClassifierType")))) { return null; } SNode claz = SLinkOperations.getTarget(SNodeOperations.cast(scruteneeType, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, "jetbrains.mps.baseLanguage.structure.ClassifierType")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, 0x101de490babL, "classifier")); if (!(SNodeOperations.isInstanceOf(claz, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass")))) { return null; } SNode enumConst = ListSequence.fromList(SLinkOperations.getChildren(SNodeOperations.cast(claz, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, 0xfc367503acL, "enumConstant"))).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return SPropertyOperations.getString(it, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")).equals(enumConstName); } }); SNode enumConstRef = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc37588bc8L, "jetbrains.mps.baseLanguage.structure.EnumConstantReference")); SLinkOperations.setTarget(enumConstRef, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc37588bc8L, 0x10a758428feL, "enumClass"), SNodeOperations.cast(claz, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass"))); SLinkOperations.setTarget(enumConstRef, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc37588bc8L, 0xfc37588bcaL, "enumConstantDeclaration"), enumConst); return enumConstRef; } private SNode transformLocalCall(SNode localCall) { // FIXME share or re-use code with the corresponding NonTypesystemRule SReference ref = SNodeOperations.getReference(localCall, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301adL, "baseMethodDeclaration")); if (!(ref instanceof StaticReference)) { return null; } SNode target = ref.getTargetNode(); if (!(SNodeOperations.isInstanceOf(target, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf0aL, "jetbrains.mps.baseLanguage.structure.StaticMethodDeclaration")))) { return null; } Scope staticMethodScope = Scope.getScope(SNodeOperations.getParent(localCall), localCall, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf0aL, "jetbrains.mps.baseLanguage.structure.StaticMethodDeclaration")); if (staticMethodScope.contains(target)) { return null; } // it's out of scope, let's make it StaticMethodCall SNode smc = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf09L, "jetbrains.mps.baseLanguage.structure.StaticMethodCall")); SLinkOperations.setTarget(smc, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf09L, 0x10a7588b546L, "classConcept"), SNodeOperations.getNodeAncestor(target, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept"), false, false)); SLinkOperations.setTarget(smc, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301adL, "baseMethodDeclaration"), SNodeOperations.cast(target, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbebabf0aL, "jetbrains.mps.baseLanguage.structure.StaticMethodDeclaration"))); for (SNode arg : ListSequence.fromList(SLinkOperations.getChildren(localCall, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301aeL, "actualArgument")))) { ListSequence.fromList(SLinkOperations.getChildren(smc, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0xf8c78301aeL, "actualArgument"))).addElement(SNodeOperations.copyNode(arg)); } for (SNode arg : ListSequence.fromList(SLinkOperations.getChildren(localCall, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0x4500f31eb02a7788L, "typeArgument")))) { ListSequence.fromList(SLinkOperations.getChildren(smc, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11857355952L, 0x4500f31eb02a7788L, "typeArgument"))).addElement(SNodeOperations.copyNode(arg)); } return smc; } private SNode transformLocalNameRef(SNode varRef) { // it's either EnumConstReference or StaticFieldReference // FIXME share or re-use code with the corresponding NonTypesystemRule SReference ref = SNodeOperations.getReference(varRef, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); if (!(ref instanceof StaticReference)) { return null; } SNode target = ref.getTargetNode(); if (!(SNodeOperations.isInstanceOf(target, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf93c84351fL, "jetbrains.mps.baseLanguage.structure.StaticFieldDeclaration")))) { return null; } // now check whether it's in another class SNode thisClass = SNodeOperations.getNodeAncestor(varRef, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"), false, false); SNode thatClass = SNodeOperations.getNodeAncestor(target, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"), false, false); // it should be ok to use ==, I think if (thisClass == thatClass) { // same class, such local method call is ok in baseLanguage return null; } // different class, let's make this reference non-local, but qualified SNode sfr = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940c80846L, "jetbrains.mps.baseLanguage.structure.StaticFieldReference")); SLinkOperations.setTarget(sfr, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940c80846L, 0x10a75869f9bL, "classifier"), thatClass); SLinkOperations.setTarget(sfr, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration"), SNodeOperations.cast(target, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf93c84351fL, "jetbrains.mps.baseLanguage.structure.StaticFieldDeclaration"))); return sfr; } private Iterable<SNode> getImportsToRemove(SNode root) { // FIXME share or re-use code with the corresponding NonTypesystemRule final Map<String, SNode> importsByName = MapSequence.fromMap(new HashMap<String, SNode>()); ListSequence.fromList(SLinkOperations.getChildren(AttributeOperations.getAttribute(root, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, "jetbrains.mps.baseLanguage.structure.JavaImports"))), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, 0x64c0181e6020a7L, "entries"))).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return !(SPropertyOperations.getBoolean(it, MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x64c0181e603bcfL, 0x64c0181e603bd0L, "onDemand"))); } }).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { MapSequence.fromMap(importsByName).put(((String) BHReflection.invoke(it, SMethodTrimmedId.create("lastToken", MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x5a98df4004080866L, "jetbrains.mps.baseLanguage.structure.Tokens"), "17WpDCYLyrY"))), it); } }); boolean unknownPresent = false; boolean dynRefsPresent = false; Set<SNode> retain = SetSequence.fromSet(new HashSet<SNode>()); Deque<SNode> stack = DequeSequence.fromDequeNew(new LinkedList<SNode>()); DequeSequence.fromDequeNew(stack).pushElement(root); while (DequeSequence.fromDequeNew(stack).isNotEmpty()) { SNode node = DequeSequence.fromDequeNew(stack).popElement(); DequeSequence.fromDequeNew(stack).addSequence(ListSequence.fromList(SNodeOperations.getChildren(node))); if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x70ea1dc4c5721865L, "jetbrains.mps.baseLanguage.structure.IYetUnresolved"))) { unknownPresent = true; break; } Iterable<? extends SReference> refs = node.getReferences(); for (SReference ref : Sequence.fromIterable(refs)) { if (!(ref instanceof DynamicReference)) { continue; } dynRefsPresent = true; String resolveInfo = ((DynamicReference) ref).getResolveInfo(); SetSequence.fromSet(retain).addElement(MapSequence.fromMap(importsByName).get(resolveInfo)); } } // retain all imports if 'unknown' concepts still present if (unknownPresent) { return null; } // on the other hand, if everything is resolved, remove all imports altogether if (dynRefsPresent == false) { // quick-fix return SLinkOperations.getChildren(AttributeOperations.getAttribute(root, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, "jetbrains.mps.baseLanguage.structure.JavaImports"))), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x53f7c33f069862f2L, 0x64c0181e6020a7L, "entries")); } // removing only those single-type imports that didn't get into retain set // quick fix Iterable<SNode> unneeded = Sequence.fromIterable(MapSequence.fromMap(importsByName).values()).subtract(SetSequence.fromSet(retain)); return unneeded; } private Iterable<SReference> getTopLevelRefs(SNode node) { final List<SReference> refs = ListSequence.fromList(new ArrayList<SReference>()); if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept"))) { ListSequence.fromList(refs).addSequence(ListSequence.fromList(SNodeOperations.getReferences(SLinkOperations.getTarget(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0x10f6353296dL, "superclass"))))); ListSequence.fromList(SLinkOperations.getChildren(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0xff2ac0b419L, "implementedInterface"))).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(it))); } }); } else if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface"))) { ListSequence.fromList(SLinkOperations.getChildren(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, 0x101eddadad7L, "extendedInterface"))).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(it))); } }); } for (SNode inner : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"), false, new SAbstractConcept[]{}))) { if (SNodeOperations.isInstanceOf(inner, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x1107e0cb103L, "jetbrains.mps.baseLanguage.structure.AnonymousClass"))) { continue; } ListSequence.fromList(refs).addSequence(Sequence.fromIterable(getTopLevelRefs(inner))); } return refs; } private Iterable<SReference> getFieldAndMethodTypeRefs(SNode node) { List<SReference> refs = ListSequence.fromList(new ArrayList<SReference>()); Iterable<SNode> members = (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")) ? SLinkOperations.getChildren(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, 0x4a9a46de59132803L, "member")) : Sequence.<SNode>singleton(SNodeOperations.cast(node, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x112574373bdL, "jetbrains.mps.baseLanguage.structure.ClassifierMember")))); for (SNode member : Sequence.fromIterable(members)) { if (SNodeOperations.isInstanceOf(member, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, "jetbrains.mps.baseLanguage.structure.VariableDeclaration"))) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(SLinkOperations.getTarget(SNodeOperations.cast(member, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, "jetbrains.mps.baseLanguage.structure.VariableDeclaration")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"))))); } else if (SNodeOperations.isInstanceOf(member, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x6c6b6a1e379f9408L, "jetbrains.mps.baseLanguage.structure.MethodDeclaration"))) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(SLinkOperations.getTarget(SNodeOperations.cast(member, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, "jetbrains.mps.baseLanguage.structure.BaseMethodDeclaration")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1fdL, "returnType"))))); for (SNode param : ListSequence.fromList(SLinkOperations.getChildren(SNodeOperations.cast(member, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, "jetbrains.mps.baseLanguage.structure.BaseMethodDeclaration")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter")))) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(SLinkOperations.getTarget(param, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"))))); } for (SNode thrws : ListSequence.fromList(SLinkOperations.getChildren(SNodeOperations.cast(member, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, "jetbrains.mps.baseLanguage.structure.BaseMethodDeclaration")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0x10f383d6949L, "throwsItem")))) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(thrws))); } } else if (SNodeOperations.isInstanceOf(member, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(getFieldAndMethodTypeRefs(member))); } } return refs; } private Iterable<SReference> getVarTypeRefs(SNode node) { List<SReference> refs = ListSequence.fromList(new ArrayList<SReference>()); for (SNode block : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b200L, "jetbrains.mps.baseLanguage.structure.StatementList"), false, new SAbstractConcept[]{}))) { for (SNode varDecl : ListSequence.fromList(SNodeOperations.getNodeDescendants(block, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, "jetbrains.mps.baseLanguage.structure.VariableDeclaration"), false, new SAbstractConcept[]{}))) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(SLinkOperations.getTarget(varDecl, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"))))); } } return refs; } private Iterable<SReference> getVariableRefs(SNode node) { return ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference"), false, new SAbstractConcept[]{})).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return !(SNodeOperations.isInstanceOf(it, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940c80846L, "jetbrains.mps.baseLanguage.structure.StaticFieldReference"))); } }).select(new ISelector<SNode, SReference>() { public SReference select(SNode it) { return SNodeOperations.getReference(SNodeOperations.cast(it, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); } }); } private Iterable<SReference> getDotExpLeftParts(SNode node) { return ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, "jetbrains.mps.baseLanguage.structure.DotExpression"), false, new SAbstractConcept[]{})).translate(new ITranslator2<SNode, SReference>() { public Iterable<SReference> translate(SNode it) { return deepReferences(SLinkOperations.getTarget(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x116b46a08c4L, 0x116b46a4416L, "operand"))); } }); } private void resolveRefs(Iterable<SReference> refs, Map<SNodeReference, List<SReference>> result) { for (SReference ref : refs) { if (!(ref instanceof DynamicReference)) { continue; } if (SetSequence.fromSet(myVisitedRefs).contains((SReference) ref)) { continue; } SNode target = ref.getTargetNode(); if (target == null) { continue; } SNode source = ref.getSourceNode(); SModelReference targetModel = target.getModel().getReference(); SReference staticRef = StaticReference.create(ref.getRole(), source, targetModel, target.getNodeId(), ((DynamicReference) ref).getResolveInfo()); List<SReference> nodeRefs = MapSequence.fromMap(result).get(source.getReference()); if (nodeRefs == null) { nodeRefs = ListSequence.fromList(new ArrayList<SReference>()); MapSequence.fromMap(result).put(source.getReference(), nodeRefs); } ListSequence.fromList(nodeRefs).addElement((SReference) staticRef); } } private void updateReference(Map<SNodeReference, List<SReference>> refMap) { for (SNodeReference nodeRef : SetSequence.fromSet(MapSequence.fromMap(refMap).keySet())) { final SNode node = nodeRef.resolve(myRepository); if (node == null) { continue; } final SModel sourceModel = node.getModel(); ListSequence.fromList(MapSequence.fromMap(refMap).get(nodeRef)).visitAll(new IVisitor<SReference>() { public void visit(SReference it) { SModelReference targetModelRef = it.getTargetSModelReference(); if (!(sourceModel.getReference().equals(targetModelRef))) { // avoiding self-import ((SModelInternal) sourceModel).addModelImport(targetModelRef, true); } node.setReference(it.getRole(), it); } }); } } public static Iterable<SReference> deepReferences(SNode node) { List<SReference> refs = ListSequence.fromList(new ArrayList<SReference>()); ListSequence.fromList(refs).addSequence(ListSequence.fromList(SNodeOperations.getReferences(node))); for (SNode child : ListSequence.fromList(SNodeOperations.getChildren(node))) { ListSequence.fromList(refs).addSequence(Sequence.fromIterable(deepReferences(child))); } return refs; // generator for yield broken? } private SModel getModel(String pkgFqName, IFile pkgDir) { for (SModel model : Sequence.fromIterable(myModule.getModels())) { // not handling stereotype on purpose: if there's my.pkg@java_stub, it shouldn't prevent us // from creating my.pkg if (pkgFqName.equals(model.getModelName())) { return model; } } return createModel(pkgFqName, pkgDir); } private SModel createModel(String pkgFqName, IFile pkgDir) { SModel modelDescr; if (myCreateInplace) { Tuples._2<DefaultModelRoot, SourceRoot> place = getRootContainingDir(pkgDir); DefaultModelRoot modelRoot = place._0(); SourceRoot sourceRoot = place._1(); if (modelRoot == null) { myMessageHandler.handle(new Message(MessageKind.ERROR, "Cannot convert to MPS in-place: java sources are not under proper model root")); return null; } try { DataSourceFactoryFromName dataSourceFactory = new JavaToMpsConverter.MyDataSourceFactory(pkgDir); ModelFactory modelFactory = ModelFactoryService.getInstance().getDefaultModelFactory(dataSourceFactory.getType()); SModelName newModelName = new SModelName(pkgFqName); modelDescr = modelRoot.createModel(newModelName, sourceRoot, dataSourceFactory, modelFactory); } catch (ModelCannotBeCreatedException e) { myMessageHandler.handle(new Message(MessageKind.ERROR, "Failed to create model " + pkgFqName, e.getMessage())); return null; } } else { DefaultModelRoot modelRoot = getFirstRootToCreateModel(pkgFqName); if (modelRoot == null) { myMessageHandler.handle(new Message(MessageKind.ERROR, "Failed to find model root to create model in")); return null; } modelDescr = modelRoot.createModel(pkgFqName); } if (modelDescr == null) { myMessageHandler.handle(new Message(MessageKind.ERROR, String.format("Failed to create model for package %s", pkgFqName))); return null; } modelDescr.load(); return modelDescr; } private static final class MyDataSourceFactory implements DataSourceFactoryFromName { private final IFile myPkgDir; public MyDataSourceFactory(IFile pkgDir) { myPkgDir = pkgDir; } @NotNull @Override public DataSource create(@NotNull SModelName name, @NotNull SourceRoot sourceRoot, @Nullable ModelRoot root) { return new FilePerRootDataSource(myPkgDir, root); } @NotNull @Override public DataSourceType getType() { return PreinstalledDataSourceTypes.FOLDER; } } @Nullable private DefaultModelRoot getFirstRootToCreateModel(String packageName) { for (ModelRoot root : Sequence.fromIterable(myModule.getModelRoots())) { if (!(root instanceof DefaultModelRoot)) { continue; } if (root.canCreateModel(packageName)) { return (DefaultModelRoot) root; } } return null; } private Tuples._2<DefaultModelRoot, SourceRoot> getRootContainingDir(IFile dir) { // returns modelRoot and sourceRoot within for (ModelRoot modelRoot : Sequence.fromIterable(myModule.getModelRoots())) { // or maybe more general: file based model root? if (!(modelRoot instanceof DefaultModelRoot)) { continue; } for (SourceRoot sourceRoot : ListSequence.fromList(((DefaultModelRoot) modelRoot).getSourceRoots(SourceRootKinds.SOURCES))) { if (FileUtil.isSubPath(sourceRoot.getAbsolutePath().getPath(), dir.getPath())) { return MultiTuple.<DefaultModelRoot,SourceRoot>from(((DefaultModelRoot) modelRoot), sourceRoot); } } } return MultiTuple.<DefaultModelRoot,SourceRoot>from((DefaultModelRoot) null, (SourceRoot) null); } }