diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index be52383..8049c68 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/plantuml-parser-cli/build.gradle b/plantuml-parser-cli/build.gradle index 2559f25..4414a60 100644 --- a/plantuml-parser-cli/build.gradle +++ b/plantuml-parser-cli/build.gradle @@ -11,8 +11,8 @@ repositories { } dependencies { - compile 'commons-cli:commons-cli:1.5.0' - compile project(":plantuml-parser-core") + implementation 'commons-cli:commons-cli:1.5.0' + implementation project(":plantuml-parser-core") } tasks.withType(JavaCompile) { diff --git a/plantuml-parser-core/build.gradle b/plantuml-parser-core/build.gradle index 290e7ea..b7bb8e5 100644 --- a/plantuml-parser-core/build.gradle +++ b/plantuml-parser-core/build.gradle @@ -1,6 +1,7 @@ plugins { id 'java' id 'maven-publish' + id 'org.jetbrains.kotlin.jvm' version '1.9.10' } group 'com.shuzijun' @@ -12,9 +13,10 @@ repositories { } dependencies { - compile "com.github.javaparser:javaparser-core:3.25.3" + api "com.github.javaparser:javaparser-core:3.25.3" - compile "commons-io:commons-io:2.8.0" + api "commons-io:commons-io:2.8.0" + api "org.jetbrains.kotlin:kotlin-compiler" } tasks.withType(JavaCompile) { diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ClassVoidVisitor.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ClassVoidVisitor.java index 56a5c40..75c0d5d 100644 --- a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ClassVoidVisitor.java +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ClassVoidVisitor.java @@ -16,7 +16,7 @@ * * @author shuzijun */ -public class ClassVoidVisitor extends VoidVisitorAdapter { +public class ClassVoidVisitor extends VoidVisitorAdapter implements MyVisitor { private final String packageName; @@ -340,16 +340,6 @@ public void visit(EnumConstantDeclaration enumConstantDeclaration, PUml pUml) { } } - private PUmlClass createUmlClass() { - PUmlClass pUmlClass = new PUmlClass(); - if (parserConfig.isShowPackage()) { - pUmlClass.setPackageName(packageName); - } else { - pUmlClass.setPackageName(""); - } - return pUmlClass; - } - private NodeList parseImport(Node node, PUmlClass pUmlClass, PUmlView pUmlView) { if (node instanceof CompilationUnit) { return ((CompilationUnit) node).getImports(); @@ -369,11 +359,14 @@ private NodeList parseImport(Node node, PUmlClass pUmlClass, return null; } - private String getPackageNamePrefix(String packageName) { - if (packageName == null || packageName.trim().equals("")) { - return ""; - } else { - return packageName + "."; - } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public ParserConfig getParserConfig() { + return parserConfig; } } diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/Constant.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/Constant.java new file mode 100644 index 0000000..0ee7602 --- /dev/null +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/Constant.java @@ -0,0 +1,13 @@ +package com.shuzijun.plantumlparser.core; + +public class Constant { + + public static String VisibilityAll = "*"; + public static String VisibilityPrivate = "private"; + public static String VisibilityDefault = "default"; + public static String VisibilityProtected = "protected"; + public static String VisibilityPublic = "public"; + + + +} diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/KtClassVOidVisitor.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/KtClassVOidVisitor.java new file mode 100644 index 0000000..e1f6e7f --- /dev/null +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/KtClassVOidVisitor.java @@ -0,0 +1,317 @@ +package com.shuzijun.plantumlparser.core; + + +import com.intellij.psi.PsiElement; +import org.jetbrains.kotlin.lexer.KtTokens; +import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes; +import org.jetbrains.kotlin.resolve.ImportPath; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class KtClassVOidVisitor extends KtTreeVisitor implements MyVisitor { + + private final String packageName; + + private final ParserConfig parserConfig; + + public KtClassVOidVisitor(String packageName, ParserConfig parserConfig) { + this.packageName = packageName; + this.parserConfig = parserConfig; + } + + + @Override + public Void visitClassOrObject(KtClassOrObject ktClass, PUml pUml) { + + if (!(pUml instanceof PUmlView)) { + super.visitClassOrObject(ktClass, pUml); + return null; + } + + if (parserConfig.isExcludeClass(ktClass.getName())) { + return null; + } + + + PUmlView pUmlView = (PUmlView) pUml; + PUmlClass pUmlClass = createUmlClass(); + + pUmlClass.setClassName(ktClass.getName()); + if (ktClass instanceof KtObjectDeclaration) { + pUmlClass.setClassType("class"); + } else { + if (((KtClass) ktClass).isInterface()) { + pUmlClass.setClassType("interface"); + } else if (((KtClass) ktClass).isEnum()) { + pUmlClass.setClassType("enum"); + } else { + if (ktClass.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { + pUmlClass.setClassType("abstract class"); + } else { + pUmlClass.setClassType("class"); + } + + } + } + + if (parserConfig.isShowComment()) { + if (ktClass.getDocComment() != null) { + pUmlClass.setClassComment(ktClass.getDocComment().getText()); + } + } + + if (ktClass.getPrimaryConstructor() != null) { + ktClass.getPrimaryConstructor().accept(this, pUmlClass); + } + + ktClass.getDeclarations().forEach(p -> { + if (p instanceof KtProperty) { + p.accept(this, pUmlClass); + } else if (p instanceof KtConstructor) { + p.accept(this, pUmlClass); + } else if (p instanceof KtNamedFunction) { + p.accept(this, pUmlClass); + } else if (p instanceof KtEnumEntry) { + p.accept(this, pUmlClass); + } else if (p instanceof KtObjectDeclaration) { + p.accept(this, pUml); + } else if (p instanceof KtClassOrObject) { + p.accept(this, pUml); + } + }); + + pUmlView.addPUmlClass(pUmlClass); + + + PsiElement node = ktClass.getParent(); + + List importDeclarations = parseImport(node, pUmlClass, pUmlView); + + Map importMap = new HashMap<>(); + if (importDeclarations != null) { + for (KtImportDirective importDeclaration : importDeclarations) { + ImportPath importPath = importDeclaration.getImportPath(); + if (importPath.getAlias() == null) { + importMap.put(importPath.getImportedName().asString(), importPath.getFqName().toString()); + } else { + importMap.put(importPath.getAlias().asString(), importPath.getFqName().toString()); + } + + } + } + + List superClassEntries = ktClass.getSuperTypeListEntries(); + for (KtSuperTypeListEntry superClassEntry : superClassEntries) { + if (superClassEntry != null) { + if (superClassEntry.getElementType() == KtStubElementTypes.SUPER_TYPE_ENTRY) { + PUmlRelation pUmlRelation = new PUmlRelation(); + pUmlRelation.setTarget(getPackageNamePrefix(pUmlClass.getPackageName()) + pUmlClass.getClassName()); + if (importMap.containsKey(superClassEntry.getText())) { + if (parserConfig.isShowPackage()) { + pUmlRelation.setSource(importMap.get(superClassEntry.getText())); + } else { + pUmlRelation.setSource(superClassEntry.getText()); + } + } else { + pUmlRelation.setSource(getPackageNamePrefix(pUmlClass.getPackageName()) + superClassEntry.getText()); + } + pUmlRelation.setRelation("<|.."); + pUmlView.addPUmlRelation(pUmlRelation); + } else if (superClassEntry.getElementType() == KtStubElementTypes.SUPER_TYPE_CALL_ENTRY) { + PUmlRelation pUmlRelation = new PUmlRelation(); + pUmlRelation.setTarget(getPackageNamePrefix(pUmlClass.getPackageName()) + pUmlClass.getClassName()); + if (importMap.containsKey(superClassEntry.getTypeReference().getText())) { + if (parserConfig.isShowPackage()) { + pUmlRelation.setSource(importMap.get(superClassEntry.getTypeReference().getText())); + } else { + pUmlRelation.setSource(superClassEntry.getTypeReference().getText()); + } + } else { + pUmlRelation.setSource(getPackageNamePrefix(pUmlClass.getPackageName()) + superClassEntry.getTypeReference().getText()); + } + pUmlRelation.setRelation("<|--"); + pUmlView.addPUmlRelation(pUmlRelation); + } + + } + } + return null; + } + + @Override + public Void visitProperty(KtProperty property, PUml pUml) { + if (!(pUml instanceof PUmlClass)) { + super.visitProperty(property, pUml); + return null; + } + PUmlClass pUmlClass = (PUmlClass) pUml; + PUmlField pUmlField = new PUmlField(); + + pUmlField.setVisibility(VisibilityUtils.toVisibility(property)); + + if (parserConfig.isFieldModifier(pUmlField.getVisibility())) { + pUmlField.setType(getKtTypeReference(property.getTypeReference(), "")); + pUmlField.setName(property.getName()); + pUmlClass.addPUmlFieldList(pUmlField); + } + + if (parserConfig.isShowComment()) { + if (property.getDocComment() != null) { + pUmlField.setComment(property.getDocComment().getText()); + } + } + return null; + } + + @Override + public Void visitEnumEntry(KtEnumEntry enumEntry, PUml pUml) { + + if (!(pUml instanceof PUmlClass)) { + super.visitEnumEntry(enumEntry, pUml); + return null; + } + PUmlClass pUmlClass = (PUmlClass) pUml; + PUmlField pUmlField = new PUmlField(); + + pUmlField.setVisibility(Constant.VisibilityPublic); + + if (parserConfig.isFieldModifier(pUmlField.getVisibility())) { + pUmlField.setType(""); + pUmlField.setName(enumEntry.getName()); + pUmlClass.addPUmlFieldList(pUmlField); + } + + if (parserConfig.isShowComment()) { + if (enumEntry.getDocComment() != null) { + pUmlField.setComment(enumEntry.getDocComment().getText()); + } + } + return null; + } + + private String getKtTypeReference(KtTypeReference reference, String defaultValue) { + + if (reference != null) { + return reference.getText(); + } + + return defaultValue; + } + + public Void visitPrimaryConstructor(KtPrimaryConstructor constructor, PUml pUml) { + return this.visitConstructor(constructor, pUml); + } + + public Void visitSecondaryConstructor(KtSecondaryConstructor constructor, PUml pUml) { + return this.visitConstructor(constructor, pUml); + } + + public Void visitConstructor(KtConstructor constructor, PUml pUml) { + if (!(pUml instanceof PUmlClass)) { + return null; + } + if (!parserConfig.isShowConstructors()) { + return null; + } + PUmlClass pUmlClass = (PUmlClass) pUml; + PUmlMethod pUmlMethod = new PUmlMethod(); + + + pUmlMethod.setVisibility(VisibilityUtils.toVisibility(constructor)); + + if (parserConfig.isMethodModifier(pUmlMethod.getVisibility())) { + pUmlMethod.setReturnType("<>"); + pUmlMethod.setName(constructor.getName()); + + for (Object parameter : constructor.getValueParameters()) { + pUmlMethod.addParam(getKtTypeReference(((KtParameter) parameter).getTypeReference(), "")); + } + pUmlClass.addPUmlMethodList(pUmlMethod); + } + if (parserConfig.isShowComment()) { + if (constructor.getDocComment() != null) { + pUmlMethod.setComment(constructor.getDocComment().getText()); + } + } + + return null; + } + + @Override + public Void visitNamedFunction(KtNamedFunction function, PUml pUml) { + if (!(pUml instanceof PUmlClass)) { + super.visitNamedFunction(function, pUml); + return null; + } + PUmlClass pUmlClass = (PUmlClass) pUml; + + PUmlMethod pUmlMethod = new PUmlMethod(); + + pUmlMethod.setVisibility(VisibilityUtils.toVisibility(function)); + + if (parserConfig.isMethodModifier(pUmlMethod.getVisibility())) { + pUmlMethod.setReturnType(getKtTypeReference(function.getTypeReference(), "void")); + pUmlMethod.setName(function.getName()); + for (Object parameter : function.getValueParameters()) { + pUmlMethod.addParam(getKtTypeReference(((KtParameter) parameter).getTypeReference(), "void")); + } + pUmlClass.addPUmlMethodList(pUmlMethod); + } + + if (parserConfig.isShowComment()) { + if (function.getDocComment() != null) { + pUmlMethod.setComment(function.getDocComment().getText()); + } + } + return null; + } + + @Override + public Void visitKtElement(KtElement element, PUml pUml) { + super.visitKtElement(element, pUml); + return null; + } + + @Override + public Void visitKtFile(KtFile file, PUml pUml) { + super.visitKtFile(file, pUml); + return null; + } + + @Override + public Void visitDeclaration(KtDeclaration dcl, PUml pUml) { + super.visitDeclaration(dcl, pUml); + return null; + } + + private List parseImport(PsiElement node, PUmlClass pUmlClass, PUmlView pUmlView) { + if (node instanceof KtFile) { + return ((KtFile) node).getImportDirectives(); + } else if (node != null) { + if (node instanceof KtClassBody && node.getParent() instanceof KtClassOrObject) { + pUmlClass.setClassName(((KtClassOrObject) node.getParent()).getName() + "$" + pUmlClass.getClassName()); + + PUmlRelation pUmlRelation = new PUmlRelation(); + pUmlRelation.setTarget(getPackageNamePrefix(pUmlClass.getPackageName()) + pUmlClass.getClassName()); + pUmlRelation.setSource(getPackageNamePrefix(pUmlClass.getPackageName()) + pUmlClass.getClassName().substring(0, pUmlClass.getClassName().lastIndexOf("$"))); + pUmlRelation.setRelation("+.."); + pUmlView.addPUmlRelation(pUmlRelation); + } + parseImport(node.getParent(), pUmlClass, pUmlView); + } + return null; + } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public ParserConfig getParserConfig() { + return parserConfig; + } +} diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/KtParserProgram.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/KtParserProgram.java new file mode 100644 index 0000000..1781681 --- /dev/null +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/KtParserProgram.java @@ -0,0 +1,38 @@ +package com.shuzijun.plantumlparser.core; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; +import org.apache.commons.io.FileUtils; +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.config.CompilerConfiguration; +import org.jetbrains.kotlin.idea.KotlinFileType; +import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.psi.KtFile; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +public class KtParserProgram { + + public static void execute(ParserConfig parserConfig, File file,PUmlView pUmlView) throws IOException { + if (parserConfig.getProject() == null) { + Disposable disposable = Disposer.newDisposable(); + KotlinCoreEnvironment env = KotlinCoreEnvironment.createForProduction( + disposable, new CompilerConfiguration(), EnvironmentConfigFiles.JVM_CONFIG_FILES); + parserConfig.setProject( env.getProject()); + + } + + PsiFile ktFile = PsiFileFactory.getInstance(parserConfig.getProject()).createFileFromText(file.getName(), KotlinFileType.INSTANCE, FileUtils.readFileToString(file, Charset.defaultCharset())); + if (!(ktFile instanceof KtFile)) { + return; + } + FqName packageFqName = ((KtFile)ktFile).getPackageFqName(); + KtClassVOidVisitor ktClassVOidVisitor = new KtClassVOidVisitor(packageFqName.asString(),parserConfig); + ((KtFile) ktFile).accept(ktClassVOidVisitor,pUmlView); + } +} diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/MyVisitor.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/MyVisitor.java new file mode 100644 index 0000000..da1b49e --- /dev/null +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/MyVisitor.java @@ -0,0 +1,25 @@ +package com.shuzijun.plantumlparser.core; + +public interface MyVisitor { + + default PUmlClass createUmlClass() { + PUmlClass pUmlClass = new PUmlClass(); + if (getParserConfig().isShowPackage()) { + pUmlClass.setPackageName(getPackageName()); + } else { + pUmlClass.setPackageName(""); + } + return pUmlClass; + } + default String getPackageNamePrefix(String packageName) { + if (packageName == null || packageName.trim().equals("")) { + return ""; + } else { + return packageName + "."; + } + } + + String getPackageName(); + ParserConfig getParserConfig(); + +} diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserConfig.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserConfig.java index fd279cd..7a1c11c 100644 --- a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserConfig.java +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserConfig.java @@ -1,7 +1,13 @@ package com.shuzijun.plantumlparser.core; import com.github.javaparser.ParserConfiguration; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import org.apache.commons.io.FileUtils; +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.config.CompilerConfiguration; import java.io.File; import java.util.*; @@ -37,6 +43,16 @@ public class ParserConfig { private boolean showComment = false; + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + private Project project; + private ParserConfiguration.LanguageLevel languageLevel = ParserConfiguration.LanguageLevel.JAVA_8; public String getOutFilePath() { @@ -56,9 +72,9 @@ public void addFilePath(String filePath) { if (!file.exists()) { return; } else if (file.isDirectory()) { - Collection files = FileUtils.listFiles(file, new String[]{"java"}, Boolean.TRUE); + Collection files = FileUtils.listFiles(file, new String[]{"java","kt"}, Boolean.TRUE); files.forEach(fileTemp -> fileMap.put(fileTemp.getPath(), fileTemp)); - } else if (filePath.endsWith("java")) { + } else if (filePath.endsWith("java") || filePath.endsWith("kt")) { fileMap.put(file.getPath(), file); } } @@ -68,6 +84,9 @@ public void addFieldModifier(String modifier) { } public boolean isFieldModifier(String modifier) { + if (fieldModifier.contains(Constant.VisibilityAll)){ + return true; + } return fieldModifier.contains(modifier); } @@ -76,6 +95,9 @@ public void addMethodModifier(String modifier) { } public boolean isMethodModifier(String modifier) { + if (methodModifier.contains(Constant.VisibilityAll)){ + return true; + } return methodModifier.contains(modifier); } @@ -140,4 +162,6 @@ public boolean isExcludeClass(String className) { } return false; } + + } diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserProgram.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserProgram.java index 07734cd..4c7ef0a 100644 --- a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserProgram.java +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/ParserProgram.java @@ -35,13 +35,21 @@ public void execute() throws IOException { StaticJavaParser.getConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_8); } Set files = this.parserConfig.getFilePaths(); + PUmlView pUmlView = new PUmlView(); for (File file : files) { - CompilationUnit compilationUnit = StaticJavaParser.parse(file); - Optional packageDeclaration = compilationUnit.getPackageDeclaration(); - VoidVisitor classNameCollector = new ClassVoidVisitor(packageDeclaration.isPresent() ? packageDeclaration.get().getNameAsString() : "", parserConfig); - classNameCollector.visit(compilationUnit, pUmlView); - + if (file.getPath().endsWith("java")){ + CompilationUnit compilationUnit = StaticJavaParser.parse(file); + Optional packageDeclaration = compilationUnit.getPackageDeclaration(); + VoidVisitor classNameCollector = new ClassVoidVisitor(packageDeclaration.isPresent() ? packageDeclaration.get().getNameAsString() : "", parserConfig); + classNameCollector.visit(compilationUnit, pUmlView); + } else if (file.getPath().endsWith("kt")){ + try { + KtParserProgram.execute(parserConfig,file,pUmlView); + }catch (NoClassDefFoundError e){ + throw new IOException("Environment not support kotlin"); + } + } } if (this.parserConfig.getOutFilePath() == null) { diff --git a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/VisibilityUtils.java b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/VisibilityUtils.java index f1380b3..9f5eb4d 100644 --- a/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/VisibilityUtils.java +++ b/plantuml-parser-core/src/main/java/com/shuzijun/plantumlparser/core/VisibilityUtils.java @@ -1,5 +1,8 @@ package com.shuzijun.plantumlparser.core; +import org.jetbrains.kotlin.lexer.KtTokens; +import org.jetbrains.kotlin.psi.KtModifierListOwner; + /** * 转换限定符 * @@ -36,4 +39,16 @@ public static boolean isVisibility(String visibility) { return false; } } + + public static String toVisibility(KtModifierListOwner ktModifierListOwner) { + if (ktModifierListOwner.hasModifier(KtTokens.PRIVATE_KEYWORD)){ + return "private"; + } else if (ktModifierListOwner.hasModifier(KtTokens.INTERNAL_KEYWORD)){ + return "private"; + } else if (ktModifierListOwner.hasModifier(KtTokens.PROTECTED_KEYWORD)){ + return "protected"; + } else { + return "public"; + } + } } diff --git a/plantuml-parser-core/src/test/java/com/shuzijun/plantumlparser/core/KtTester.java b/plantuml-parser-core/src/test/java/com/shuzijun/plantumlparser/core/KtTester.java new file mode 100644 index 0000000..7c76f06 --- /dev/null +++ b/plantuml-parser-core/src/test/java/com/shuzijun/plantumlparser/core/KtTester.java @@ -0,0 +1,31 @@ +package com.shuzijun.plantumlparser.core; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.config.CompilerConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.Objects; + +public class KtTester { + + public static void main(String[]args)throws IOException { + String filePath = KtTester.class.getClassLoader().getResource("kt").getPath(); + + ParserConfig parserConfig=new ParserConfig(); + parserConfig.addFilePath(filePath); + parserConfig.setShowPackage(true); + parserConfig.setShowComment(true); + parserConfig.setShowConstructors(true); + + parserConfig.addFieldModifier(Constant.VisibilityAll); + parserConfig.addMethodModifier(Constant.VisibilityAll); + + ParserProgram parserProgram=new ParserProgram(parserConfig); + parserProgram.execute(); + } + +} diff --git a/plantuml-parser-core/src/test/resources/kt/CompanionObject.kt b/plantuml-parser-core/src/test/resources/kt/CompanionObject.kt new file mode 100644 index 0000000..fe842af --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/CompanionObject.kt @@ -0,0 +1,16 @@ +package kt + +class MyClass { + companion object { + const val staticField = "This is a static field" + + fun staticFunction() { + println("This is a static function") + } + } +} + +fun main() { + println(MyClass.staticField) // 访问静态字段 + MyClass.staticFunction() // 调用静态函数 +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/Enum.kt b/plantuml-parser-core/src/test/resources/kt/Enum.kt new file mode 100644 index 0000000..24334a3 --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/Enum.kt @@ -0,0 +1,23 @@ +package kt +enum class DayOfWeek { + MONDAY, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY, + SUNDAY +} + +fun main() { + val today = DayOfWeek.WEDNESDAY + + // 使用 when 表达式匹配枚举值 + val message = when (today) { + DayOfWeek.MONDAY -> "It's Monday!" + DayOfWeek.WEDNESDAY -> "It's Wednesday!" + else -> "It's not Monday or Wednesday." + } + + println(message) // 输出: It's Wednesday! +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/Factory.kt b/plantuml-parser-core/src/test/resources/kt/Factory.kt new file mode 100644 index 0000000..b088d87 --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/Factory.kt @@ -0,0 +1,35 @@ +package kt + +interface Product { + fun create() +} + +class ConcreteProductA : Product { + override fun create() { + println("Product A is created") + } +} + +class ConcreteProductB : Product { + override fun create() { + println("Product B is created") + } +} + +object Factory { + fun createProduct(type: String): Product { + return when (type) { + "A" -> ConcreteProductA() + "B" -> ConcreteProductB() + else -> throw IllegalArgumentException("Invalid product type") + } + } +} + +fun main() { + val productA = Factory.createProduct("A") + val productB = Factory.createProduct("B") + + productA.create() + productB.create() +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/InnerClass.kt b/plantuml-parser-core/src/test/resources/kt/InnerClass.kt new file mode 100644 index 0000000..8be5184 --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/InnerClass.kt @@ -0,0 +1,27 @@ +package kt + +class OuterClass { + private val outerProperty = "Outer Property" + + class NestedClass { + fun accessOuterProperty() { + // 无法访问外部类的属性 + // println(outerProperty) // 错误:无法访问外部类的属性 + } + } + + inner class InnerClass { + fun accessOuterProperty() { + // 可以访问外部类的属性 + println(outerProperty) // 可以访问外部类的属性 + } + } +} + +fun main() { + val nested = OuterClass.NestedClass() + val inner = OuterClass().InnerClass() + + nested.accessOuterProperty() // 无法访问外部类的属性 + inner.accessOuterProperty() // 可以访问外部类的属性 +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/KtClass.kt b/plantuml-parser-core/src/test/resources/kt/KtClass.kt new file mode 100644 index 0000000..85b9501 --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/KtClass.kt @@ -0,0 +1,17 @@ +package kt + +/** + * This is a documentation comment for MyClass. + */ +class KtClass { + val myVal: Int = 42 + var myVar: String = "Hello" + lateinit var myLateInitVar: String + + /** + * This is a documentation comment for myFunction. + */ + fun myFunction(): String? { + return null + } +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/KtExtend.kt b/plantuml-parser-core/src/test/resources/kt/KtExtend.kt new file mode 100644 index 0000000..72b35cf --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/KtExtend.kt @@ -0,0 +1,26 @@ +package kt + +open class Animal(val name: String) { + open fun makeSound() { + println("$name makes a sound") + } +} + +class Dog(name: String) : Animal(name) { + override fun makeSound() { + println("$name barks") + } + + fun fetch() { + println("$name is fetching a ball") + } +} + +fun main() { + val animal = Animal("Generic Animal") + val dog = Dog("Buddy") + + animal.makeSound() // 输出: Generic Animal makes a sound + dog.makeSound() // 输出: Buddy barks + dog.fetch() // 输出: Buddy is fetching a ball +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/KtExtend2.kt b/plantuml-parser-core/src/test/resources/kt/KtExtend2.kt new file mode 100644 index 0000000..b315f68 --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/KtExtend2.kt @@ -0,0 +1,7 @@ +package kt2 + +open class Animal(val name: String) { + open fun makeSound() { + println("$name makes a sound") + } +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/KtExtend3.kt b/plantuml-parser-core/src/test/resources/kt/KtExtend3.kt new file mode 100644 index 0000000..10bb11b --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/KtExtend3.kt @@ -0,0 +1,20 @@ +package kt3 +import kt2.Animal as Animal2 +class Dog(name: String) : Animal2(name) { + override fun makeSound() { + println("$name barks") + } + + fun fetch() { + println("$name is fetching a ball") + } +} + +fun main() { + val animal = Animal2("Generic Animal") + val dog = Dog("Buddy") + + animal.makeSound() // 输出: Generic Animal makes a sound + dog.makeSound() // 输出: Buddy barks + dog.fetch() // 输出: Buddy is fetching a ball +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/KtObject.kt b/plantuml-parser-core/src/test/resources/kt/KtObject.kt new file mode 100644 index 0000000..8dbea7f --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/KtObject.kt @@ -0,0 +1,9 @@ +package kt +object KtObject { + val field1 = "Value 1" + val field2 = "Value 2" + + fun createProduct(type: String): String { + return "" + } +} \ No newline at end of file diff --git a/plantuml-parser-core/src/test/resources/kt/Observer.kt b/plantuml-parser-core/src/test/resources/kt/Observer.kt new file mode 100644 index 0000000..3953ae9 --- /dev/null +++ b/plantuml-parser-core/src/test/resources/kt/Observer.kt @@ -0,0 +1,37 @@ +package kt +interface Observer { + fun update(message: String) +} + +class ConcreteObserver(private val name: String) : Observer { + override fun update(message: String) { + println("$name received message: $message") + } +} + +class Subject { + private val observers = mutableListOf() + + fun addObserver(observer: Observer) { + observers.add(observer) + } + + fun removeObserver(observer: Observer) { + observers.remove(observer) + } + + fun notifyObservers(message: String) { + observers.forEach { it.update(message) } + } +} + +fun main() { + val subject = Subject() + val observer1 = ConcreteObserver("Observer 1") + val observer2 = ConcreteObserver("Observer 2") + + subject.addObserver(observer1) + subject.addObserver(observer2) + + subject.notifyObservers("Hello, observers!") +} \ No newline at end of file diff --git a/plantuml-parser-plugin/build.gradle b/plantuml-parser-plugin/build.gradle index e0200be..b8d3dc8 100644 --- a/plantuml-parser-plugin/build.gradle +++ b/plantuml-parser-plugin/build.gradle @@ -4,14 +4,16 @@ plugins { } group 'com.shuzijun' -version '0.0.5' +version '0.0.6' repositories { mavenCentral() } dependencies { - compile project(":plantuml-parser-core") + implementation (project(path: ":plantuml-parser-core")) { + exclude (group: 'org.jetbrains.kotlin', module: 'kotlin-compiler') + } } intellij { @@ -21,6 +23,7 @@ intellij { downloadSources false updateSinceUntilBuild false buildSearchableOptions.enabled(false) + plugins ['org.jetbrains.kotlin'] } tasks.withType(JavaCompile) { diff --git a/plantuml-parser-plugin/src/main/java/com/shuzijun/plantumlparser/plugin/action/ParserProgramAction.java b/plantuml-parser-plugin/src/main/java/com/shuzijun/plantumlparser/plugin/action/ParserProgramAction.java index 13e51b2..57e8352 100644 --- a/plantuml-parser-plugin/src/main/java/com/shuzijun/plantumlparser/plugin/action/ParserProgramAction.java +++ b/plantuml-parser-plugin/src/main/java/com/shuzijun/plantumlparser/plugin/action/ParserProgramAction.java @@ -76,10 +76,13 @@ class ParserConfigDialog extends DialogWrapper { private ParserConfig parserConfig; + private Project project; + public ParserConfigDialog(@Nullable Project project, ParserConfig parserConfig) { super(project, true); parserConfigPanel = new ParserConfigPanel(project); this.parserConfig = parserConfig; + this.project = project; setModal(true); init(); setTitle("ParserConfig"); @@ -132,6 +135,7 @@ public ParserConfig getParserConfig() { parserConfig.setShowPackage(parserConfigPanel.getShowPackage()); parserConfig.setShowConstructors(parserConfigPanel.getConstructors()); parserConfig.setShowComment(parserConfigPanel.getShowComment()); + parserConfig.setProject(this.project); parserConfigPanel.getExcludeClass().forEach(s -> parserConfig.addExcludeClassRegex(s)); return parserConfig; } diff --git a/plantuml-parser-plugin/src/main/resources/META-INF/plantuml-parser-withKotlin.xml b/plantuml-parser-plugin/src/main/resources/META-INF/plantuml-parser-withKotlin.xml new file mode 100644 index 0000000..e92fdc8 --- /dev/null +++ b/plantuml-parser-plugin/src/main/resources/META-INF/plantuml-parser-withKotlin.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/plantuml-parser-plugin/src/main/resources/META-INF/plugin.xml b/plantuml-parser-plugin/src/main/resources/META-INF/plugin.xml index 508ed9f..38233ec 100644 --- a/plantuml-parser-plugin/src/main/resources/META-INF/plugin.xml +++ b/plantuml-parser-plugin/src/main/resources/META-INF/plugin.xml @@ -6,7 +6,7 @@ -

Convert the Java source code to Plantuml.

+

Convert the Java(or kotlin) source code to Plantuml.


@@ -29,10 +29,7 @@ - 2.fix bugs - -
  • - 1.Convert the Java source code to Plantuml + 1.support kotlin
  • ]]>
    @@ -40,6 +37,9 @@ com.intellij.modules.platform + org.jetbrains.kotlin +