/*
* Copyright 2003-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.excluded;
import jetbrains.mps.library.ModulesMiner;
import jetbrains.mps.project.MPSExtentions;
import jetbrains.mps.project.ProjectPathUtil;
import jetbrains.mps.project.facets.TestsFacetImpl;
import jetbrains.mps.project.persistence.LanguageDescriptorPersistence;
import jetbrains.mps.project.persistence.SolutionDescriptorPersistence;
import jetbrains.mps.project.structure.modules.GeneratorDescriptor;
import jetbrains.mps.project.structure.modules.LanguageDescriptor;
import jetbrains.mps.project.structure.modules.SolutionDescriptor;
import jetbrains.mps.util.FileUtil;
import jetbrains.mps.util.MacroHelper;
import jetbrains.mps.util.MacrosFactory;
import jetbrains.mps.util.containers.MultiMap;
import jetbrains.mps.vfs.IFile;
import jetbrains.mps.vfs.IFileUtils;
import jetbrains.mps.vfs.impl.IoFileSystem;
import org.jdom.Document;
import org.jdom.Element;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Utils {
private static final String COMPONENT = "component";
private static final String NAME = "name";
private static String rootPath;
static {
rootPath = new File(".").getAbsolutePath();
rootPath = rootPath.substring(0, rootPath.length() - 1);
}
public static String getRelativeProjectPath(String absolutePath) {
// file should be under project
if (!absolutePath.startsWith(rootPath)) {
throw new IllegalStateException("Module path: " + absolutePath + "; root path: " + rootPath);
}
return absolutePath.substring(rootPath.length()).replace("\\", "/");
}
public static Element getComponentWithName(Document doc, String name) {
Element result = getChildByAttribute(doc.getRootElement(), COMPONENT, NAME, name);
if (result != null) {
return result;
} else {
throw new IllegalStateException();
}
}
public static Element getChildByAttribute(Element element, String tagName, String attributeName, String attributeValue) {
Element result = null;
for (Element component : element.getChildren(tagName)) {
if (component.getAttributeValue(attributeName).equals(attributeValue)) {
if (result == null) {
result = component;
} else {
return null;
}
}
}
return result;
}
public static File[] files(String... paths) {
File[] files = new File[paths.length];
for (int i = 0; i < paths.length; i++) {
files[i] = new File(paths[i]);
}
return files;
}
public static MultiMap<String, String> collectMPSCompiledModulesInfo(File... dirs) {
MultiMap<String, String> result = new MultiMap<String, String>();
for (File dir : dirs) {
collectMPSCompiledModulesInfoRecursively(dir, result);
}
return result;
}
private static void collectMPSCompiledModulesInfoRecursively(File dir, MultiMap<String, String> result) {
for (File child : dir.listFiles()) {
if (child.isDirectory()) {
collectMPSCompiledModulesInfoRecursively(child, result);
continue;
}
boolean solution = child.getName().endsWith(MPSExtentions.DOT_SOLUTION);
boolean language = child.getName().endsWith(MPSExtentions.DOT_LANGUAGE);
if (!(solution || language)) continue;
final IFile moduleIFile = IoFileSystem.INSTANCE.getFile(child.getAbsolutePath());
IFile moduleDir = moduleIFile.getParent();
// XXX what's the reason for custom MyMacroHelper, why not MacrosFactory.forModuleFile()
MacroHelper expander = new MyMacroHelper(moduleIFile);
if (solution) {
SolutionDescriptor sd = SolutionDescriptorPersistence.loadSolutionDescriptor(moduleIFile, expander);
if (!sd.getCompileInMPS()) continue;
String srcPath = ProjectPathUtil.getGeneratorOutputPath(sd);
result.putValue(getCanonicalPath(moduleDir.getPath()), getCanonicalPath(srcPath));
String testPath = TestsFacetImpl.getTestsOutputPath(sd, moduleIFile).getPath();
result.putValue(getCanonicalPath(moduleDir.getPath()), getCanonicalPath(testPath));
} else {
LanguageDescriptor ld = LanguageDescriptorPersistence.loadLanguageDescriptor(moduleIFile, expander);
String srcPath = ProjectPathUtil.getGeneratorOutputPath(ld);
result.putValue(getCanonicalPath(moduleDir.getPath()), getCanonicalPath(srcPath));
// currently same getGeneratorOutputPath used for all generators, so generatorSrcPath will be the same for
// all generators in the language. Using only first one for now.
boolean generatorAdded = false;
for (GeneratorDescriptor generator : ld.getGenerators()) {
if (generatorAdded) {
break;
}
String generatorSrcPath = ProjectPathUtil.getGeneratorOutputPath(generator);
result.putValue(getCanonicalPath(moduleDir.getPath() + "/generator"), getCanonicalPath(generatorSrcPath));
generatorAdded = true;
}
}
}
}
private static String getCanonicalPath(String path) {
return FileUtil.getCanonicalPath(path);
}
public static File root() {
return new File(".");
}
public static List<File> files(File root) {
List<File> result = new ArrayList<File>();
collectFiles(root, result);
return result;
}
private static void collectFiles(File file, List<File> result) {
if (file.isFile()) {
result.add(file);
} else {
for (File inner : file.listFiles()) {
collectFiles(inner, result);
}
}
}
public static List<File> withExtension(String ext, List<File> files) {
List<File> result = new ArrayList<File>();
for (File file : files) {
if (file.getName().endsWith(ext)) {
result.add(file);
}
}
return result;
}
private static class MyMacroHelper implements MacroHelper {
private final IFile myModuleIFile;
public MyMacroHelper(IFile moduleIFile) {
myModuleIFile = moduleIFile;
}
@Override
public String expandPath(String path) {
if (path.startsWith(MacrosFactory.MODULE)) {
IFile anchorFolder = myModuleIFile.getParent();
if (myModuleIFile.getPath().endsWith(ModulesMiner.META_INF_MODULE_XML)) {
anchorFolder = anchorFolder.getParent();
}
String modelRelativePath = removePrefix(path);
return IFileUtils.getCanonicalPath(anchorFolder.getDescendant(modelRelativePath));
}
if (path.startsWith(MacrosFactory.MPS_HOME)) {
String relativePath = removePrefix(path);
try {
return new File("./" + relativePath).getCanonicalPath();
} catch (IOException e) {
e.printStackTrace();
}
}
return path;
}
@Override
public String shrinkPath(String absolutePath) {
throw new UnsupportedOperationException();
}
private String removePrefix(String path) {
String result = path.substring(path.indexOf("}") + 1);
if (result.startsWith(File.separator)) result = result.substring(1);
return result;
}
}
}