package jetbrains.mps.ide.java.newparser; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import java.util.List; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.vfs.IFile; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.module.ModelAccess; import java.io.IOException; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import jetbrains.mps.progress.EmptyProgressMonitor; import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; import jetbrains.mps.smodel.SModelInternal; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.vfs.IFileUtils; import jetbrains.mps.project.SModuleOperations; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.persistence.ModelRoot; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.util.NameUtil; public class DirParser { private static final Logger LOG = LogManager.getLogger(DirParser.class); private List<SModel> myAffectedModels = ListSequence.fromList(new ArrayList<SModel>()); private List<IFile> mySourceDirs; private List<IFile> mySuccessfulFiles; private SModule myModule; private ModelAccess myModelAccess; private JavaParser myJavaParser = new JavaParser(); public DirParser(SModule module, ModelAccess modelAccess) { myModule = module; myModelAccess = modelAccess; } public DirParser(SModule module, ModelAccess modelAccess, IFile sourceDir) { this(module, modelAccess); mySourceDirs = ListSequence.fromListAndArray(new ArrayList<IFile>(), sourceDir); mySuccessfulFiles = ListSequence.fromList(new ArrayList<IFile>()); } public void addDirectory(IFile dir) { ListSequence.fromList(mySourceDirs).addElement(dir); } public void parseDirs() throws IOException, JavaParseException { for (IFile sourceDir : ListSequence.fromList(mySourceDirs)) { addSourceFromDirectory(sourceDir); } Runnable finalize = new Runnable() { @Override public void run() { for (SModel m : ListSequence.fromList(myAffectedModels)) { Iterable<SNode> roots = SModelOperations.roots(m, null); JavaParser.tryResolveUnknowns(roots, new EmptyProgressMonitor(), IncrementalModelAccess.INSIDE_COMMAND_OR_UPDATE_MODE); JavaParser.tryResolveDynamicRefs(roots); } } }; if (myModelAccess.isCommandAction()) { finalize.run(); } else { myModelAccess.executeUndoTransparentCommand(finalize); } } public List<IFile> getSuccessfulFiles() { return mySuccessfulFiles; } public List<SModel> getAffectedModels() { return myAffectedModels; } public void addSourceFromDirectory(final IFile dir) throws IOException, JavaParseException { assert dir.isDirectory(); // packages which match the directory // in the proper case: there should be only one final Wrappers._T<String> pkg = new Wrappers._T<String>(null); final Wrappers._T<JavaParseException> javaParseException = new Wrappers._T<JavaParseException>(null); final Wrappers._boolean wasDefaultPkg = new Wrappers._boolean(false); final List<SNode> roots = new ArrayList<SNode>(); for (final IFile file : dir.getChildren()) { if (file.isDirectory()) { addSourceFromDirectory(file); } else if (file.getName().endsWith(".java")) { myModelAccess.runReadAction(new Runnable() { public void run() { try { JavaParser.JavaParseResult parseRes = parseFile(file); String p = parseRes.getPackage(); if (p == null) { // default package (i.e. none), bad if (!(wasDefaultPkg.value)) { LOG.error("default package is not supported in java source directory input (first such file in dir: " + file.getName() + ")"); wasDefaultPkg.value = true; } return; } if (pkg.value == null) { if (DirParser.checkPackageMatchesSourceDirectory(p, dir)) { pkg.value = p; } else { LOG.error("package " + p + " doesn't match directory " + dir.getPath() + " (in file " + file.getName() + ")"); return; } } else if (!(pkg.value.equals(p))) { LOG.error("different packages in directory " + dir.getPath() + ", namely " + pkg.value + " and " + p); return; } ListSequence.fromList(roots).addSequence(ListSequence.fromList(parseRes.getNodes())); ListSequence.fromList(mySuccessfulFiles).addElement(file); } catch (JavaParseException e) { javaParseException.value = e; } catch (IOException e) { // FIXME throw new RuntimeException(e); } } }); if (javaParseException.value != null) { throw new JavaParseException(javaParseException.value); } } } // do model stuff final String finalPkg = pkg.value; if (pkg.value != null && ListSequence.fromList(roots).isNotEmpty()) { myModelAccess.executeCommand(new Runnable() { @Override public void run() { SModel mdl = registerModelForPackage(finalPkg); if (mdl != null) { ((SModelInternal) mdl).addLanguage(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage")); for (SNode r : ListSequence.fromList(roots)) { SModelOperations.addRootNode(mdl, r); } ListSequence.fromList(myAffectedModels).addElement(mdl); } } }); } else { LOG.info("skipping directory " + dir.getPath()); } } private JavaParser.JavaParseResult parseFile(IFile file) throws IOException, JavaParseException { String contents = IFileUtils.getTextContents(file); return myJavaParser.parseCompilationUnit(contents); } private SModel registerModelForPackage(String fqName) { for (SModel model : myModule.getModels()) { if (fqName.equals(model.getName().getLongName())) { // package is already present... // maybe we shouldn't touch it then, maybe it should be an option return model; } } return createModel(fqName); } private SModel createModel(String packageName) { // first check if it is possible if (getRootToCreateModel(packageName) == null) { LOG.error("Cannot create model " + packageName + " in module " + myModule.getModuleName()); return null; } SModel modelDescr = SModuleOperations.createModelWithAdjustments(packageName, getRootToCreateModel(packageName)); assert modelDescr != null; return modelDescr; } @Nullable private ModelRoot getRootToCreateModel(String packageName) { for (ModelRoot root : Sequence.fromIterable(myModule.getModelRoots())) { if (root.canCreateModel(packageName)) { return root; } } return null; } public static boolean checkPackageMatchesSourceDirectory(String pkg, IFile sourceDir) { String pathPostfix = NameUtil.pathFromNamespace(pkg); // pathFromNamespace returns system-dependent path // while IdeaFile.getPath() returns system-independent String sourceDirSysDep = NameUtil.toSystemDependentPath(sourceDir.getPath()); return sourceDirSysDep.endsWith(pathPostfix); } }