diff --git a/README.md b/README.md index 67abaa3..da6c373 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ GoogleMockのコード出力機能も持ちます。 変換ルールなどについては、次のWEBサイトを参照ください。 - - [組込みソフト開発 ノウハウ集](http://y-philly.bitbucket.org/embedded-know-how/index.html) + - [組込みソフトウェア開発 ノウハウ集](http://y-philly.bitbucket.org/embedded-know-how/index.html) ## 1. インストール方法 @@ -52,6 +52,17 @@ Abstractなクラスを、型による動的インターフェイスとしてコ ## 3. テンプレートファイルについて - テンプレートファイルの文字コードは、UTF-8 としてください。 +## 4. オプション + +本プラグインは、 コードフォーマッタ [Uncrustify](http://uncrustify.sourceforge.net/http://uncrustify.sourceforge.net/) +と連携して、生成コードを任意(プロジェクトごとのコーディングルールなど)の書式に整形することができます。 + +一度以下の手順を行えば、その後は生成コードに対する整形が自動で行われます。 + +1. Uncrustify のコンフィグファイルを作成し、 `custom.cfg` という名前で保存します。 +1. フォルダ `[ホームフォルダ]/.astah/[astahのエディション名]/plugins/uml2c/uncrustify` を作成します。 +1. 上記フォルダに Uncrustify の実行ファイルと、`custom.cfg` を保存します。 + ## ライセンス Copyright 2016 ChangeVision,Inc. diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCSkeletonAction.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCSkeletonAction.java index 031cb3d..fc530a7 100755 --- a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCSkeletonAction.java +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCSkeletonAction.java @@ -7,7 +7,8 @@ public class GenerateCSkeletonAction extends GenerateCodeAction { @Override - protected void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException { + protected void generateCode(AbstractCModule cModule, String outputDirPath) + throws IOException, InterruptedException { CSkeletonGenerator cSkeletonGenerator = new CSkeletonGenerator(cModule); cSkeletonGenerator.outputHeader(outputDirPath); cSkeletonGenerator.outputSource(outputDirPath); diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCodeAction.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCodeAction.java index ce00a80..e078e31 100644 --- a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCodeAction.java +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateCodeAction.java @@ -16,6 +16,7 @@ import com.change_vision.astah.extension.plugin.uml2c.cmodule.AbstractCModule; import com.change_vision.astah.extension.plugin.uml2c.cmodule.CModuleFactory; import com.change_vision.astah.extension.plugin.uml2c.codegenerator.CodeGenerator; +import com.change_vision.astah.extension.plugin.uml2c.astahutil.AstahUtil; import com.change_vision.jude.api.inf.AstahAPI; import com.change_vision.jude.api.inf.exception.InvalidUsingException; import com.change_vision.jude.api.inf.exception.ProjectNotFoundException; @@ -28,6 +29,7 @@ import com.change_vision.jude.api.inf.view.IDiagramViewManager; import com.change_vision.jude.api.inf.view.IViewManager; + public abstract class GenerateCodeAction implements IPluginActionDelegate { private static Logger logger = LoggerFactory.getLogger(CodeGenerator.class); @@ -41,7 +43,7 @@ public Object run(IWindow window) throws UnExpectedException { List targetClasses = getTargetClasses(api); if (targetClasses.isEmpty()) { JOptionPane.showMessageDialog(window.getParent(), - Messages.getMessage("message.select_class"), + Messages.getMessage("message.select_class"), Messages.getMessage("title.select_class"), JOptionPane.WARNING_MESSAGE); logger.warn("No target class was selected"); @@ -52,34 +54,34 @@ public Object run(IWindow window) throws UnExpectedException { String outputDirPath = getOutputDirPath(window, projectAccessor); logger.info("Output Path = {}", outputDirPath); if (outputDirPath == null) return null; //canceled - + if (!ensureWritableOutputFolder(outputDirPath, window)) { return null; } - + for (IClass iClass: targetClasses) { AbstractCModule cModule = CModuleFactory.getCModule(iClass); logger.info("Module = {}", cModule.getClass().getSimpleName()); generateCode(cModule, outputDirPath); } - JOptionPane.showMessageDialog(window.getParent(), - Messages.getMessage("message.finish_generating"), + JOptionPane.showMessageDialog(window.getParent(), + Messages.getMessage("message.finish_generating"), Messages.getMessage("title.finish_generating"), JOptionPane.INFORMATION_MESSAGE); logger.info("Finished."); } catch (ProjectNotFoundException e) { logger.warn("Project Not Found."); - JOptionPane.showMessageDialog(window.getParent(), - Messages.getMessage("message.project_not_found"), + JOptionPane.showMessageDialog(window.getParent(), + Messages.getMessage("message.project_not_found"), Messages.getMessage("title.project_not_found"), JOptionPane.WARNING_MESSAGE); } catch (ResourceNotFoundException e) { logger.warn("Template Not Found."); - logger.warn(" - Template Search Path = {}", CodeGenerator.getAstahConfigPath()); + logger.warn(" - Template Search Path = {}", AstahUtil.getFullPathOfConfigDir()); logger.warn(" - Exception = {}", e.getLocalizedMessage()); - JOptionPane.showMessageDialog(window.getParent(), - Messages.getMessage("message.not_found_template", CodeGenerator.getAstahConfigPath(), e.getLocalizedMessage()), + JOptionPane.showMessageDialog(window.getParent(), + Messages.getMessage("message.not_found_template", AstahUtil.getFullPathOfConfigDir(), e.getLocalizedMessage()), Messages.getMessage("title.not_found_template"), JOptionPane.WARNING_MESSAGE); } catch (Throwable e) { @@ -92,8 +94,9 @@ public Object run(IWindow window) throws UnExpectedException { return null; } - - protected abstract void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException; + + protected abstract void generateCode(AbstractCModule cModule, String outputDirPath) + throws IOException, InterruptedException; private boolean ensureWritableOutputFolder(String outputDirPath, IWindow window) { File outputDir = new File(outputDirPath); @@ -102,7 +105,7 @@ private boolean ensureWritableOutputFolder(String outputDirPath, IWindow window) if (!wasSucceeded) { logger.warn("Failed to create a folder to output. path = {}", outputDir.getAbsolutePath()); JOptionPane.showMessageDialog(window.getParent(), - Messages.getMessage("message.failed_mkdirs", outputDir.getAbsolutePath()), + Messages.getMessage("message.failed_mkdirs", outputDir.getAbsolutePath()), Messages.getMessage("title.failed_mkdirs"), JOptionPane.WARNING_MESSAGE); return false; @@ -112,7 +115,7 @@ private boolean ensureWritableOutputFolder(String outputDirPath, IWindow window) if (!outputDir.canWrite()) { logger.warn("The output folder is not writable. path = {}", outputDir.getAbsolutePath()); JOptionPane.showMessageDialog(window.getParent(), - Messages.getMessage("message.not_writable_output_folder", outputDir.getAbsolutePath()), + Messages.getMessage("message.not_writable_output_folder", outputDir.getAbsolutePath()), Messages.getMessage("title.not_writable_output_folder"), JOptionPane.WARNING_MESSAGE); return false; @@ -136,8 +139,8 @@ private String getOutputDirPath(IWindow window, ProjectAccessor projectAccessor) JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fileChooser.setDialogTitle(Messages.getMessage("title.choose_output_dir")); - - File projectDir = new File(projectAccessor.getProjectPath()).getParentFile(); + + File projectDir = new File(projectAccessor.getProjectPath()).getParentFile(); if (projectDir != null && projectDir.exists() && projectDir.canWrite()) { fileChooser.setSelectedFile(projectDir); } diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateGoogleMockAction.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateGoogleMockAction.java index 936b14d..3eba9d6 100755 --- a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateGoogleMockAction.java +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/actions/GenerateGoogleMockAction.java @@ -7,7 +7,7 @@ public class GenerateGoogleMockAction extends GenerateCodeAction { @Override - protected void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException { + protected void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException, InterruptedException { GoogleMockGenerator googleMockGenerator = new GoogleMockGenerator(cModule); googleMockGenerator.outputHeader(outputDirPath); googleMockGenerator.outputSource(outputDirPath); diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/astahutil/AstahUtil.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/astahutil/AstahUtil.java new file mode 100644 index 0000000..297933b --- /dev/null +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/astahutil/AstahUtil.java @@ -0,0 +1,17 @@ +package com.change_vision.astah.extension.plugin.uml2c.astahutil; + +import com.change_vision.jude.api.inf.AstahAPI; + +public class AstahUtil { + public static String getFullPathOfConfigDir() { + String edition; + try { + edition = AstahAPI.getAstahAPI().getProjectAccessor().getAstahEdition(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return ""; + } + String userHomeDir = System.getProperty("user.home"); + return userHomeDir + "/.astah/" + edition; + } +} diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codeformatter/CodeFormatter.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codeformatter/CodeFormatter.java new file mode 100644 index 0000000..b92a489 --- /dev/null +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codeformatter/CodeFormatter.java @@ -0,0 +1,61 @@ +package com.change_vision.astah.extension.plugin.uml2c.codeformatter; + +import java.io.File; +import java.io.IOException; + +import java.lang.InterruptedException; +import java.lang.ProcessBuilder; +import java.lang.Process; + +import javax.management.RuntimeErrorException; + +import com.change_vision.astah.extension.plugin.uml2c.astahutil.AstahUtil; + +public class CodeFormatter { + + public static void format(String codePath) throws IOException, InterruptedException { + if (!hasUncrustify()) { + return; + } + + ProcessBuilder pb = new ProcessBuilder( + getUncrustifyExePath(), + "-c", getUncrustifyCfgPath(), + "-f", codePath, + "-o", codePath); + + Process process = pb.start(); + int procRet = process.waitFor(); + if (procRet != 0) { + throw new RuntimeErrorException(new Error("Uncrustify fails: " + String.valueOf(procRet))); + } + + // Cleanup temporary files. + new File(codePath + ".unc-backup.md5~").delete(); + new File(codePath + ".unc-backup~").delete(); + } + + private static boolean hasUncrustify() { + String astahConfigPath = AstahUtil.getFullPathOfConfigDir(); + + File exeFile = new File(getUncrustifyExePath()); + if (!exeFile.exists()) { + return false; + } + + File cfgFile = new File(getUncrustifyCfgPath()); + if (!cfgFile.exists()) { + return false; + } + + return true; + } + + private static String getUncrustifyExePath() { + return AstahUtil.getFullPathOfConfigDir() + "/plugins/uml2c/uncrustify/uncrustify.exe"; + }; + + private static String getUncrustifyCfgPath() { + return AstahUtil.getFullPathOfConfigDir() + "/plugins/uml2c/uncrustify/custom.cfg"; + }; +} diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CSkeletonGenerator.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CSkeletonGenerator.java index a790b21..0e0982d 100755 --- a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CSkeletonGenerator.java +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CSkeletonGenerator.java @@ -10,19 +10,19 @@ public CSkeletonGenerator(AbstractCModule cModule) { this.codeGenerator = new CodeGenerator(cModule); } - public void outputHeader(String dirPath) throws IOException { + public void outputHeader(String dirPath) throws IOException, InterruptedException { String codePath = dirPath + "/" + codeGenerator.getCModuleName() + ".h"; String templatePath = codeGenerator.getTemplateDirPath() + "header.vm"; codeGenerator.outputCode(codePath, templatePath); } - public void outputPrivateHeader(String dirPath) throws IOException { + public void outputPrivateHeader(String dirPath) throws IOException, InterruptedException { String codePath = dirPath + "/" + codeGenerator.getCModuleName() + "Private.h"; String templatePath = codeGenerator.getTemplateDirPath() + "private-header.vm"; codeGenerator.outputCode(codePath, templatePath); } - public void outputSource(String dirPath) throws IOException { + public void outputSource(String dirPath) throws IOException, InterruptedException { String codePath = dirPath + "/" + codeGenerator.getCModuleName() + ".c"; String templatePath = codeGenerator.getTemplateDirPath() + "source.vm"; codeGenerator.outputCode(codePath, templatePath); diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CodeGenerator.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CodeGenerator.java index 763b072..b21a493 100755 --- a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CodeGenerator.java +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/CodeGenerator.java @@ -7,6 +7,8 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.lang.InterruptedException; + import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; @@ -14,13 +16,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.change_vision.astah.extension.plugin.uml2c.codeformatter.CodeFormatter; +import com.change_vision.astah.extension.plugin.uml2c.astahutil.AstahUtil; import com.change_vision.astah.extension.plugin.uml2c.cmodule.AbstractCModule; -import com.change_vision.jude.api.inf.AstahAPI; + public class CodeGenerator { private static final String TEMPLATE_ENCODING = "UTF-8"; //"UTF-8", "Windows-31J" private static final String OUTPUT_ENCODING = "UTF-8"; //"UTF-8", "Windows-31J" - private static final String templateDirPath = "plugins/uml2c/"; + private static final String TEMPLATE_DIR_PATH = "plugins/uml2c/"; private static Logger logger = LoggerFactory.getLogger(CodeGenerator.class); private AbstractCModule cModule; @@ -33,7 +37,7 @@ public CodeGenerator(AbstractCModule cModule) { Velocity.init(); } - public void outputCode(String codePath, String templatePath) throws IOException { + public void outputCode(String codePath, String templatePath) throws IOException, InterruptedException { VelocityContext context = new VelocityContext(); context.put("cModule", cModule); @@ -43,13 +47,15 @@ public void outputCode(String codePath, String templatePath) throws IOException } catch (ResourceNotFoundException e) { throw e; } - + File file = new File(codePath); logger.info("Generating {} ({})", file.getName(), templatePath); PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), OUTPUT_ENCODING))); template.merge(context, pw); pw.close(); + + CodeFormatter.format(codePath); } public String getCModuleName() { @@ -57,22 +63,10 @@ public String getCModuleName() { } public String getTemplateSearchDirPath() { - return getAstahConfigPath() + ",."; - } - - public static String getAstahConfigPath() { - String edition; - try { - edition = AstahAPI.getAstahAPI().getProjectAccessor().getAstahEdition(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - return ""; - } - String userHomeDir = System.getProperty("user.home"); - return userHomeDir + "/.astah/" + edition; + return AstahUtil.getFullPathOfConfigDir() + ",."; } public String getTemplateDirPath() { - return templateDirPath; + return TEMPLATE_DIR_PATH; } } diff --git a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/GoogleMockGenerator.java b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/GoogleMockGenerator.java index bf45415..06318d5 100755 --- a/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/GoogleMockGenerator.java +++ b/src/main/java/com/change_vision/astah/extension/plugin/uml2c/codegenerator/GoogleMockGenerator.java @@ -10,13 +10,13 @@ public GoogleMockGenerator(AbstractCModule cModule) { this.codeGenerator = new CodeGenerator(cModule); } - public void outputHeader(String dirPath) throws IOException { + public void outputHeader(String dirPath) throws IOException, InterruptedException { String codePath = dirPath + "/Mock_" + codeGenerator.getCModuleName() + ".h"; String templatePath = codeGenerator.getTemplateDirPath() + "mock-header.vm"; codeGenerator.outputCode(codePath, templatePath); } - public void outputSource(String dirPath) throws IOException { + public void outputSource(String dirPath) throws IOException, InterruptedException { String codePath = dirPath + "/Mock_" + codeGenerator.getCModuleName() + ".cpp"; String templatePath = codeGenerator.getTemplateDirPath() + "mock-source.vm"; codeGenerator.outputCode(codePath, templatePath);