/*
* Copyright 2012-2014 Sergey Ignatov
*
* 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 org.intellij.erlang.rebar.importWizard;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.erlang.psi.*;
import org.intellij.erlang.rebar.util.ErlangTermFileUtil;
import org.intellij.erlang.rebar.util.RebarConfigUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
final class ImportedOtpApp {
private final String myName;
private final VirtualFile myRoot;
private final Set<String> myDeps = ContainerUtil.newHashSet();
private final Set<VirtualFile> myIncludePaths = ContainerUtil.newHashSet();
private final Set<String> myParseTransforms = ContainerUtil.newHashSet();
private VirtualFile myIdeaModuleFile;
private Module myModule;
public ImportedOtpApp(@NotNull VirtualFile root, @NotNull final VirtualFile appConfig) {
myName = StringUtil.trimEnd(StringUtil.trimEnd(appConfig.getName(), ".src"), ".app");
myRoot = root;
ApplicationManager.getApplication().runReadAction(() -> {
addDependenciesFromAppFile(appConfig);
addInfoFromRebarConfig();
addIncludePath("include");
});
}
@NotNull
public String getName() {
return myName;
}
@NotNull
public VirtualFile getRoot() {
return myRoot;
}
@NotNull
public Set<String> getDeps() {
return myDeps;
}
public Set<VirtualFile> getIncludePaths() {
return myIncludePaths;
}
public void setIdeaModuleFile(@Nullable VirtualFile ideaModuleFile) {
myIdeaModuleFile = ideaModuleFile;
}
@Nullable
public VirtualFile getIdeaModuleFile() {
return myIdeaModuleFile;
}
public Module getModule() {
return myModule;
}
public void setModule(Module module) {
myModule = module;
}
public Set<String> getParseTransforms() {
return myParseTransforms;
}
@Override
public String toString() {
return myName + " (" + myRoot.getPath() + ')';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ImportedOtpApp that = (ImportedOtpApp) o;
if (!myName.equals(that.myName)) return false;
if (!myRoot.equals(that.myRoot)) return false;
return true;
}
@Override
public int hashCode() {
int result = myName.hashCode();
result = 31 * result + myRoot.hashCode();
return result;
}
private void addInfoFromRebarConfig() {
VirtualFile rebarConfig = myRoot.findChild("rebar.config");
ErlangFile rebarConfigPsi = rebarConfig != null ? ErlangTermFileUtil.createPsi(rebarConfig) : null;
if (rebarConfigPsi == null) return;
addDependenciesFromRebarConfig(rebarConfigPsi);
addIncludePathsFromRebarConfig(rebarConfigPsi);
addParseTransformsFromRebarConfig(rebarConfigPsi);
}
private void addDependenciesFromAppFile(@NotNull VirtualFile appFile) {
ErlangFile appConfigPsi = ErlangTermFileUtil.createPsi(appFile);
List<ErlangTupleExpression> applicationDescriptors = ErlangTermFileUtil.getConfigSections(appConfigPsi, "application");
ErlangListExpression appAttributes = PsiTreeUtil.getChildOfType(ContainerUtil.getFirstItem(applicationDescriptors), ErlangListExpression.class);
ErlangTermFileUtil.processConfigSection(appAttributes, "applications", deps -> {
ErlangListExpression dependencyAppsList = deps instanceof ErlangListExpression ? (ErlangListExpression) deps : null;
if (dependencyAppsList != null) {
for (ErlangExpression depExpression : dependencyAppsList.getExpressionList()) {
ErlangQAtom depApp = PsiTreeUtil.getChildOfType(depExpression, ErlangQAtom.class);
ErlangAtom appNameAtom = depApp != null ? depApp.getAtom() : null;
if (appNameAtom != null) {
myDeps.add(appNameAtom.getName());
}
}
}
});
}
private void addDependenciesFromRebarConfig(ErlangFile rebarConfig) {
myDeps.addAll(RebarConfigUtil.getDependencyAppNames(rebarConfig));
}
private void addIncludePathsFromRebarConfig(ErlangFile rebarConfig) {
for (String includePath : RebarConfigUtil.getIncludePaths(rebarConfig)) {
addIncludePath(includePath);
}
}
private void addParseTransformsFromRebarConfig(ErlangFile rebarConfig) {
myParseTransforms.addAll(RebarConfigUtil.getParseTransforms(rebarConfig));
}
private void addIncludePath(String relativeIncludePath) {
VirtualFile path = VfsUtilCore.findRelativeFile(relativeIncludePath, myRoot);
if (path != null) {
myIncludePaths.add(path);
}
}
}