package com.star.easydoc.service; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiParameter; import com.intellij.psi.PsiTypeParameter; import com.star.easydoc.config.EasyJavadocConfigComponent; import com.star.easydoc.model.EasyJavadocConfiguration; import com.star.easydoc.model.EasyJavadocConfiguration.CustomValue; import com.star.easydoc.service.variable.VariableGenerator; import com.star.easydoc.service.variable.impl.AuthorVariableGenerator; import com.star.easydoc.service.variable.impl.DateVariableGenerator; import com.star.easydoc.service.variable.impl.DocVariableGenerator; import com.star.easydoc.service.variable.impl.ParamsVariableGenerator; import com.star.easydoc.service.variable.impl.ReturnVariableGenerator; import com.star.easydoc.service.variable.impl.SeeVariableGenerator; import com.star.easydoc.service.variable.impl.SinceVariableGenerator; import com.star.easydoc.service.variable.impl.ThrowsVariableGenerator; import com.star.easydoc.service.variable.impl.VersionVariableGenerator; import groovy.lang.Binding; import groovy.lang.GroovyShell; import org.apache.commons.lang3.StringUtils; /** * 变量生成器服务 * * @author wangchao * @date 2019/12/08 */ public class VariableGeneratorService { private static final Logger LOGGER = Logger.getInstance(VariableGeneratorService.class); private Pattern pattern = Pattern.compile("\\$[a-zA-Z0-9_-]*\\$"); private EasyJavadocConfiguration config = ServiceManager.getService(EasyJavadocConfigComponent.class).getState(); /** * 变量生成器映射 */ private Map<String, VariableGenerator> variableGeneratorMap = ImmutableMap.<String, VariableGenerator>builder() .put("author", new AuthorVariableGenerator()) .put("date", new DateVariableGenerator()) .put("doc", new DocVariableGenerator()) .put("params", new ParamsVariableGenerator()) .put("return", new ReturnVariableGenerator()) .put("see", new SeeVariableGenerator()) .put("since", new SinceVariableGenerator()) .put("throws", new ThrowsVariableGenerator()) .put("version", new VersionVariableGenerator()) .build(); /** * 生成 * * @param psiElement 当前元素 * @return {@link java.lang.String} */ public String generate(PsiElement psiElement) { // 获取当前模板信息 String template = null; Map<String, CustomValue> customValueMap = Maps.newHashMap(); Map<String, Object> innerVariableMap = Maps.newHashMap(); if (psiElement instanceof PsiClass) { template = config.getClassTemplateConfig().getTemplate(); customValueMap = config.getClassTemplateConfig().getCustomMap(); innerVariableMap = getClassInnerVariable((PsiClass)psiElement); } else if (psiElement instanceof PsiMethod) { template = config.getMethodTemplateConfig().getTemplate(); customValueMap = config.getMethodTemplateConfig().getCustomMap(); innerVariableMap = getMethodInnerVariable((PsiMethod)psiElement); } else if (psiElement instanceof PsiField) { template = config.getFieldTemplateConfig().getTemplate(); customValueMap = config.getFieldTemplateConfig().getCustomMap(); innerVariableMap = getFieldInnerVariable((PsiField)psiElement); } if (StringUtils.isBlank(template)) { return ""; } // 匹配占位符 Matcher matcher = pattern.matcher(template); Map<String, String> variableMap = Maps.newHashMap(); while (matcher.find()) { String placeholder = matcher.group(); String key = StringUtils.substring(placeholder, 1, -1); if (StringUtils.isBlank(key)) { return ""; } VariableGenerator variableGenerator = variableGeneratorMap.get(key.toLowerCase()); if (variableGenerator == null) { variableMap.put(placeholder, generateCustomVariable(customValueMap, innerVariableMap, placeholder)); } else { variableMap.put(placeholder, variableGenerator.generate(psiElement)); } } // 占位符替换 List<String> keyList = Lists.newArrayList(); List<String> valueList = Lists.newArrayList(); for (Entry<String, String> entry : variableMap.entrySet()) { keyList.add(entry.getKey()); valueList.add(entry.getValue()); } return StringUtils.replaceEach(template, keyList.toArray(new String[0]), valueList.toArray(new String[0])); } /** * 生成自定义变量 * * @param customValueMap 自定义值 * @param placeholder 占位符 * @param innerVariableMap 内部变量映射 * @return {@link String} */ private String generateCustomVariable(Map<String, CustomValue> customValueMap, Map<String, Object> innerVariableMap, String placeholder) { Optional<CustomValue> valueOptional = customValueMap.entrySet().stream() .filter(entry -> placeholder.equalsIgnoreCase(entry.getKey())).map(Entry::getValue).findAny(); // 找不到自定义方法,返回原占位符 if (!valueOptional.isPresent()) { return placeholder; } CustomValue value = valueOptional.get(); switch (value.getType()) { case STRING: return value.getValue(); case GROOVY: try { return new GroovyShell(new Binding(innerVariableMap)).evaluate(value.getValue()).toString(); } catch (Exception e) { LOGGER.error(String.format("自定义变量%s的groovy脚本执行异常,请检查语法是否正确且有正确返回值:%s", placeholder, value.getValue()), e); return value.getValue(); } default: return ""; } } /** * 获取类内部变量 * * @param psiClass psi类 * @return {@link java.util.Map<java.lang.String,java.lang.Object>} */ private Map<String, Object> getClassInnerVariable(PsiClass psiClass) { Map<String, Object> map = Maps.newHashMap(); map.put("author", config.getAuthor()); map.put("className", psiClass.getQualifiedName()); map.put("simpleClassName", psiClass.getName()); return map; } /** * 获取方法内部的变量 * * @param psiMethod psi方法 * @return {@link java.util.Map<java.lang.String,java.lang.Object>} */ private Map<String, Object> getMethodInnerVariable(PsiMethod psiMethod) { Map<String, Object> map = Maps.newHashMap(); map.put("author", config.getAuthor()); map.put("methodName", psiMethod.getName()); map.put("methodReturnType", psiMethod.getReturnType() == null ? "" : psiMethod.getReturnType().getPresentableText()); map.put("methodParamTypes", Arrays.stream(psiMethod.getTypeParameters()).map(PsiTypeParameter::getQualifiedName).toArray(String[]::new)); map.put("methodParamNames", Arrays.stream(psiMethod.getParameterList().getParameters()).map(PsiParameter::getName).toArray(String[]::new)); return map; } /** * 获取字段内部的变量 * * @param psiField psi属性 * @return {@link java.util.Map<java.lang.String,java.lang.Object>} */ private Map<String, Object> getFieldInnerVariable(PsiField psiField) { Map<String, Object> map = Maps.newHashMap(); map.put("author", config.getAuthor()); map.put("fieldName", psiField.getName()); map.put("fieldType", psiField.getType().getCanonicalText()); return map; } }