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);
}
}