Skip to content

Commit 8530e80

Browse files
committed
feat: support 3rd party dependency
1 parent b8fce45 commit 8530e80

File tree

6 files changed

+289
-44
lines changed

6 files changed

+289
-44
lines changed

src/main/java/io/github/linyimin/plugin/compile/MybatisPojoCompile.java

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
package io.github.linyimin.plugin.compile;
22

33
import com.intellij.compiler.impl.ProjectCompileScope;
4+
import com.intellij.ide.plugins.cl.PluginClassLoader;
45
import com.intellij.openapi.compiler.CompilerManager;
56
import com.intellij.openapi.project.Project;
67
import com.intellij.openapi.roots.OrderEnumerator;
78
import com.intellij.openapi.ui.Messages;
89
import com.intellij.openapi.util.io.FileUtil;
910
import com.intellij.util.lang.UrlClassLoader;
11+
import io.github.linyimin.plugin.dom.Constant;
12+
import io.github.linyimin.plugin.utils.JavaUtils;
13+
import org.apache.commons.collections.CollectionUtils;
1014

1115
import java.io.File;
16+
import java.lang.reflect.Field;
1217
import java.net.MalformedURLException;
1318
import java.net.URL;
14-
import java.util.ArrayList;
15-
import java.util.List;
19+
import java.util.*;
20+
import java.util.stream.Collectors;
1621

1722

1823
/**
@@ -23,7 +28,8 @@ public class MybatisPojoCompile {
2328

2429
// TODO: 需要优化成只编译Mybatis需要的类
2530

26-
public static ClassLoader classLoader;
31+
public static UrlClassLoader classLoader;
32+
public static List<String> preDependencies;
2733

2834
public static void compile(Project project) {
2935

@@ -35,16 +41,103 @@ public static void compile(Project project) {
3541
}
3642

3743
public static void setClassLoader(Project project) {
38-
final List<URL> urls = new ArrayList<>();
44+
45+
List<String> dependencies = getProjectDependencies(project);
46+
47+
List<URL> urls = new ArrayList<>();
3948
final List<String> list = OrderEnumerator.orderEntries(project).recursively().runtimeOnly().getPathsList().getPathList();
40-
for (String path : list) {
49+
for (String path : dependencies) {
4150
try {
4251
urls.add(new File(FileUtil.toSystemIndependentName(path)).toURI().toURL());
4352
}
4453
catch (MalformedURLException e) {
4554
Messages.showErrorDialog(e.getMessage(), "MalformedURLException");
4655
}
4756
}
57+
58+
if (Objects.nonNull(classLoader)) {
59+
changeLoaderUrls(preDependencies, dependencies);
60+
} else {
61+
createProjectLoader(urls);
62+
preDependencies = dependencies;
63+
}
64+
}
65+
66+
private static List<String> getProjectDependencies(Project project) {
67+
68+
Set<String> mapperDependencies = JavaUtils.getAllDependenciesRecursive(project);
69+
70+
List<String> list = OrderEnumerator
71+
.orderEntries(project)
72+
.recursively()
73+
.runtimeOnly()
74+
.withoutSdk()
75+
.getPathsList()
76+
.getPathList()
77+
.stream()
78+
.filter(path -> path.contains(Constant.MYBATIS_LOGGING_LOG4J)
79+
|| path.contains(Constant.MYBATIS_LOGGING_SLF4J)
80+
|| path.contains(project.getName())
81+
).collect(Collectors.toList());
82+
83+
84+
list.addAll(mapperDependencies);
85+
86+
return list;
87+
}
88+
89+
private static void createProjectLoader(List<URL> urls) {
4890
classLoader = UrlClassLoader.build().urls(urls).parent(ClassLoader.getSystemClassLoader()).get();
91+
attachPluginParentLoader(classLoader);
4992
}
93+
94+
private static void attachPluginParentLoader(UrlClassLoader classLoader) {
95+
PluginClassLoader pluginClassLoader = (PluginClassLoader) MybatisPojoCompile.class.getClassLoader();
96+
97+
Class<? extends PluginClassLoader> pluginClassLoaderClass = pluginClassLoader.getClass();
98+
99+
try {
100+
Field field = pluginClassLoaderClass.getDeclaredField(Constant.PLUGIN_CLASS_LOADER_PARENTS);
101+
field.setAccessible(true);
102+
103+
ClassLoader[] parents = (ClassLoader[]) field.get(pluginClassLoader);
104+
if (Objects.isNull(parents)) {
105+
parents = new ClassLoader[] {classLoader};
106+
field.set(pluginClassLoader, parents);
107+
} else {
108+
ClassLoader[] newParents = new ClassLoader[parents.length + 1];
109+
newParents[parents.length] = classLoader;
110+
System.arraycopy(parents, 0, newParents, 0, parents.length);
111+
field.set(pluginClassLoader, newParents);
112+
}
113+
114+
} catch (NoSuchFieldException | IllegalAccessException e) {
115+
e.printStackTrace();
116+
}
117+
118+
}
119+
120+
private static void changeLoaderUrls(List<String> preDependencies, List<String> dependencies) {
121+
122+
List<String> list = new ArrayList<>(dependencies);
123+
124+
for (String preDependency : preDependencies) {
125+
list.remove(preDependency);
126+
}
127+
128+
if (CollectionUtils.isEmpty(list)) {
129+
return;
130+
}
131+
132+
for (String path : list) {
133+
try {
134+
URL url = new File(FileUtil.toSystemIndependentName(path)).toURI().toURL();
135+
classLoader.addURL(url);
136+
}
137+
catch (MalformedURLException e) {
138+
Messages.showErrorDialog(e.getMessage(), "MalformedURLException");
139+
}
140+
}
141+
}
142+
50143
}

src/main/java/io/github/linyimin/plugin/dom/Constant.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public class Constant {
2929

3030
public static final String DATABASE_URL_TEMPLATE = "jdbc:mysql://%s:%s/%s";
3131

32+
public static final String PLUGIN_CLASS_LOADER_PARENTS = "parents";
33+
34+
public static final String MYBATIS_LOGGING_SLF4J = "slf4j";
35+
public static final String MYBATIS_LOGGING_LOG4J = "log4j";
36+
3237
private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
3338
private static final DateFormat DF = new SimpleDateFormat(PATTERN);
3439
public static Map<String, Object> normalTypes = new ContainerUtil.ImmutableMapBuilder<String, Object>()

src/main/java/io/github/linyimin/plugin/service/SqlParamGenerateService.java

Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package io.github.linyimin.plugin.service;
22

33
import com.alibaba.fastjson.JSON;
4-
import com.google.common.collect.ConcurrentHashMultiset;
54
import com.google.common.collect.Lists;
65
import com.intellij.openapi.project.Project;
76
import com.intellij.openapi.ui.Messages;
87
import com.intellij.psi.*;
98
import com.intellij.psi.impl.source.PsiClassReferenceType;
109
import com.intellij.psi.util.PsiUtil;
10+
import com.intellij.psi.xml.XmlElement;
1111
import com.intellij.psi.xml.XmlTag;
1212
import com.intellij.psi.xml.XmlToken;
1313
import com.siyeh.ig.psiutils.CollectionUtils;
@@ -16,6 +16,7 @@
1616
import io.github.linyimin.plugin.dom.model.MybatisConfiguration;
1717
import io.github.linyimin.plugin.provider.MapperXmlProcessor;
1818
import io.github.linyimin.plugin.service.model.MybatisSqlConfiguration;
19+
import io.github.linyimin.plugin.utils.JavaUtils;
1920
import io.github.linyimin.plugin.utils.MapperDomUtils;
2021
import io.github.linyimin.plugin.utils.MybatisSqlUtils;
2122
import org.apache.commons.collections.MapUtils;
@@ -34,7 +35,42 @@ public void generate(PsiElement psiElement) {
3435

3536
public String generateSql(Project project, String methodQualifiedName, String params) {
3637

37-
MybatisConfiguration mybatisConfiguration = MapperDomUtils.findConfiguration(project);
38+
List<PsiMethod> psiMethods = JavaUtils.findMethod(project, methodQualifiedName);
39+
40+
if (org.apache.commons.collections.CollectionUtils.isEmpty(psiMethods)) {
41+
Messages.showInfoMessage(String.format("method %s is not exist.", methodQualifiedName), Constant.APPLICATION_NAME);
42+
return StringUtils.EMPTY;
43+
}
44+
45+
String mybatisConfig = getMybatisConfiguration(project, psiMethods.get(0));
46+
47+
boolean isNeedCompile = checkNeedCompile(mybatisConfig, methodQualifiedName, params);
48+
49+
if (isNeedCompile) {
50+
MybatisPojoCompile.compile(project);
51+
}
52+
53+
return MybatisSqlUtils.getSql(mybatisConfig, methodQualifiedName, params);
54+
55+
}
56+
57+
private boolean checkNeedCompile(String mybatisConfig, String methodQualifiedName, String params) {
58+
if (Objects.isNull(MybatisPojoCompile.classLoader)) {
59+
return true;
60+
}
61+
62+
try {
63+
MybatisSqlUtils.getSql(mybatisConfig, methodQualifiedName, params);
64+
} catch (Exception e) {
65+
return true;
66+
}
67+
68+
return false;
69+
}
70+
71+
private String getMybatisConfiguration(Project project, PsiMethod psiMethod) {
72+
73+
MybatisConfiguration mybatisConfiguration = MapperDomUtils.findConfiguration(project, psiMethod);
3874
if (Objects.isNull(mybatisConfiguration)) {
3975
Messages.showInfoMessage("Mybatis配置文件不存在", Constant.APPLICATION_NAME);
4076
return StringUtils.EMPTY;
@@ -47,10 +83,18 @@ public String generateSql(Project project, String methodQualifiedName, String pa
4783

4884
String mybatisConfig = mybatisConfiguration.getParent().getXmlElement().getText();
4985

50-
MybatisPojoCompile.compile(project);
86+
// 不处理plugins
87+
XmlElement xmlElement = mybatisConfiguration.getXmlElement();
5188

52-
return MybatisSqlUtils.getSql(mybatisConfig, methodQualifiedName, params);
89+
if (Objects.nonNull(xmlElement) && xmlElement instanceof XmlTag) {
90+
XmlTag[] tags = ((XmlTag) xmlElement).findSubTags("plugins");
91+
if (tags.length > 0) {
92+
String plugins = tags[0].getText();
93+
mybatisConfig = mybatisConfig.replace(plugins, StringUtils.EMPTY);
94+
}
95+
}
5396

97+
return mybatisConfig;
5498
}
5599

56100

@@ -112,10 +156,25 @@ private String parseParamNameTypeList(List<ParamNameType> paramNameTypes) {
112156

113157
Map<String, Object> param = new HashMap<>();
114158

115-
if (isNormalType(psiClass.getQualifiedName())) {
116-
param.put(name, getPrimitiveDefaultValue(name, psiClass.getQualifiedName()));
159+
if (Objects.isNull(psiClass) || isNormalType(psiClass.getQualifiedName())) {
160+
String paramType;
161+
if (Objects.isNull(psiClass)) {
162+
if (type instanceof PsiArrayType) {
163+
paramType = ((PsiArrayType) type).getComponentType().getCanonicalText();
164+
} else {
165+
paramType = type.getCanonicalText();
166+
}
167+
} else {
168+
paramType = psiClass.getQualifiedName();
169+
}
170+
param.put(name, getPrimitiveDefaultValue(name, paramType));
117171
} else {
118-
param = getFieldFromClass(paramNameType.psiClass);
172+
Map<String, Object> classParam = getFieldFromClass(psiClass);
173+
if (paramNameType.isParamAnnotation) {
174+
param.putAll(classParam);
175+
} else {
176+
param.put(name, classParam);
177+
}
119178
}
120179

121180
// 数组或者列表
@@ -157,9 +216,11 @@ private Map<String, Object> getFieldFromClass(PsiClass psiClass) {
157216
list.add(value);
158217
} else {
159218
PsiClass psiClassInArray = PsiUtil.resolveClassInType(deepType);
160-
Map<String, Object> temp = getFieldFromClass(psiClassInArray);
161-
if (MapUtils.isNotEmpty(temp)) {
162-
list.add(temp);
219+
if (Objects.nonNull(psiClassInArray) && !StringUtils.equals(psiClassInArray.getQualifiedName(), psiClass.getQualifiedName())) {
220+
Map<String, Object> temp = getFieldFromClass(psiClassInArray);
221+
if (MapUtils.isNotEmpty(temp)) {
222+
list.add(temp);
223+
}
163224
}
164225
}
165226

@@ -184,9 +245,11 @@ private Map<String, Object> getFieldFromClass(PsiClass psiClass) {
184245
list.add(value);
185246
} else {
186247
PsiClass iterableClass = PsiUtil.resolveClassInClassTypeOnly(iterableType);
187-
Map<String, Object> temp = getFieldFromClass(iterableClass);
188-
if (MapUtils.isNotEmpty(temp)) {
189-
list.add(temp);
248+
if (Objects.nonNull(iterableClass) && !StringUtils.equals(iterableClass.getQualifiedName(), psiClass.getQualifiedName())) {
249+
Map<String, Object> temp = getFieldFromClass(iterableClass);
250+
if (MapUtils.isNotEmpty(temp)) {
251+
list.add(temp);
252+
}
190253
}
191254
}
192255

@@ -196,11 +259,17 @@ private Map<String, Object> getFieldFromClass(PsiClass psiClass) {
196259
}
197260

198261
// class
199-
Map<String, Object> temp = getFieldFromClass(PsiUtil.resolveClassInType(type));
200-
if (MapUtils.isNotEmpty(temp)) {
201-
param.put(fieldName, temp);
262+
PsiClass typePsiClass = PsiUtil.resolveClassInType(type);
263+
if (Objects.nonNull(typePsiClass) && StringUtils.equals(typePsiClass.getQualifiedName(), psiClass.getQualifiedName())) {
264+
param.put(fieldName, new HashMap<>());
265+
} else {
266+
Map<String, Object> temp = getFieldFromClass(typePsiClass);
267+
if (MapUtils.isNotEmpty(temp)) {
268+
param.put(fieldName, temp);
269+
}
202270
}
203271

272+
204273
}
205274

206275
return param;
@@ -235,7 +304,7 @@ public List<ParamNameType> getMethodBodyParamList(PsiMethod psiMethod) {
235304
String paramAnnotationValue = getParamAnnotationValue(param);
236305
String name = StringUtils.isBlank(paramAnnotationValue) ? param.getName() : paramAnnotationValue;
237306

238-
ParamNameType paramNameType = new ParamNameType(name, psiClass, param.getType());
307+
ParamNameType paramNameType = new ParamNameType(name, psiClass, param.getType(), StringUtils.isNotEmpty(paramAnnotationValue));
239308
result.add(paramNameType);
240309
}
241310
return result;
@@ -290,11 +359,13 @@ static class ParamNameType {
290359
private final String name;
291360
private final PsiClass psiClass;
292361
private final PsiType psiType;
362+
private final boolean isParamAnnotation;
293363

294-
public ParamNameType(String name, PsiClass psiClass, PsiType psiType) {
364+
public ParamNameType(String name, PsiClass psiClass, PsiType psiType, boolean isParamAnnotation) {
295365
this.name = name;
296366
this.psiClass = psiClass;
297367
this.psiType = psiType;
368+
this.isParamAnnotation = isParamAnnotation;
298369
}
299370
}
300371

0 commit comments

Comments
 (0)