package org.dlangplugin.sdk; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.CapturingProcessHandler; import com.intellij.execution.process.ProcessOutput; import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.util.SystemInfo; import org.dlangplugin.DLangIcons; import org.dlangplugin.library.LibFileRootType; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.File; import java.nio.charset.Charset; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /* DLang SDK class. * This SDK could be added to any project. */ public class DLangSdkType extends SdkType { public static final String SDK_TYPE_ID = "DMD2 SDK"; public static final String SDK_NAME = "DMD v2 SDK"; @NotNull public static DLangSdkType getInstance() { DLangSdkType sdkType = SdkType.findInstance(DLangSdkType.class); if(sdkType == null) { return new DLangSdkType(); } else { return sdkType; } } public DLangSdkType() { super(SDK_TYPE_ID); } @NotNull @Override public Icon getIconForAddAction() { return DLangIcons.SDK_ADD; } @NotNull @Override public Icon getIcon() { return DLangIcons.SDK; } @Nullable @Override public String suggestHomePath() { if(SystemInfo.isMac || SystemInfo.isLinux) { //By default DMD is installed in /usr/bin directory. File binFolder = new File("/usr/bin"); return binFolder.getAbsolutePath(); } return null; } /* When user set up DMD SDK path this method checks if specified path contains DMD compiler executable. */ @Override public boolean isValidSdkHome(String sdkHome) { String executableName = SystemInfo.isWindows ? "dmd.exe" : "dmd"; File dmdCompilerFile = new File(sdkHome, executableName); return dmdCompilerFile.canExecute(); } @Override public String suggestSdkName(String s, String sdkHome) { String executableName = SystemInfo.isWindows ? "dmd.exe" : "dmd"; String guessedVersion = getSdkVersion(sdkHome, executableName); if(guessedVersion == null) { return SDK_NAME; } else { return "DMD v"+guessedVersion+" SDK"; } } @Nullable @Override public String getVersionString(@NotNull String sdkHome) { String executableName = SystemInfo.isWindows ? "dmd.exe" : "dmd"; String guessedVersion = getSdkVersion(sdkHome, executableName); return (guessedVersion!=null) ? guessedVersion : "2.0"; } @Nullable @Override public AdditionalDataConfigurable createAdditionalDataConfigurable(SdkModel sdkModel, SdkModificator sdkModificator) { return null; } @Override public String getPresentableName() { return "Digital Mars D compiler"; } @Override public void saveAdditionalData(@NotNull SdkAdditionalData sdkAdditionalData, @NotNull Element element) { //pass } @Override public boolean isRootTypeApplicable(OrderRootType type) { return type != LibFileRootType.getInstance() && super.isRootTypeApplicable(type); } /* Try to execute DMD compiler and parse first line to get a version * @returns String with DMD version or null in case of any error. */ @Nullable public String getSdkVersion(String sdkHome, String executableName) { File compilerFolder = new File(sdkHome); File compilerFile = new File(sdkHome, executableName); GeneralCommandLine commandLine = new GeneralCommandLine(); commandLine.withWorkDirectory(compilerFolder.getAbsolutePath()); commandLine.setExePath(compilerFile.getAbsolutePath()); ProcessOutput output = null; try { output = new CapturingProcessHandler(commandLine.createProcess(), Charset.defaultCharset(), commandLine.getCommandLineString()).runProcess(); } catch (ExecutionException e) { return null; } //Parse output of a DMD compiler List<String> outputLines = output.getStdoutLines(); if(outputLines.size()>0) { String firstLine = outputLines.get(0).trim(); // line in format: "DMD32 D Compiler v2.058" Pattern pattern = Pattern.compile(".*v(\\d+\\.\\d+).*"); Matcher m = pattern.matcher(firstLine); if(m.matches()) { return m.group(1); } } return null; } /* Returns full path to DMD compiler executable */ public static String getDmdPath(Sdk sdk) { String sdkHome = sdk.getHomePath(); String executableName = SystemInfo.isWindows ? "dmd.exe" : "dmd"; File dmdCompilerFile = new File(sdkHome, executableName); return dmdCompilerFile.getAbsolutePath(); } }