mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Remove experimental CodeStyleBean API
This commit is contained in:
@@ -1,84 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.application.options;
|
||||
|
||||
import com.intellij.formatting.WrapType;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Wraps language code style options defined in {@code CommonCodeStyleSettings} and {@code CustomCodeStyleSettings} with getter/setter
|
||||
* methods for external serialization.
|
||||
*
|
||||
* @see CommonCodeStyleSettings
|
||||
* @see CustomCodeStyleSettings
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@ApiStatus.Experimental
|
||||
public abstract class CodeStyleBean implements Serializable {
|
||||
|
||||
private @NotNull CodeStyleSettings myRootSettings;
|
||||
|
||||
public CodeStyleBean() {
|
||||
myRootSettings = new CodeStyleSettings();
|
||||
}
|
||||
|
||||
public void setRootSettings(@NotNull CodeStyleSettings settings) {
|
||||
myRootSettings = settings;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract Language getLanguage();
|
||||
|
||||
public int getRightMargin() {
|
||||
return myRootSettings.getRightMargin(getLanguage());
|
||||
}
|
||||
|
||||
public void setRightMargin(int rightMargin) {
|
||||
myRootSettings.setRightMargin(getLanguage(), rightMargin);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CommonCodeStyleSettings.WrapOnTyping getWrapOnTyping() {
|
||||
for (CommonCodeStyleSettings.WrapOnTyping c : CommonCodeStyleSettings.WrapOnTyping.values()) {
|
||||
if (c.intValue == getCommonSettings().WRAP_ON_TYPING) return c;
|
||||
}
|
||||
return CommonCodeStyleSettings.WrapOnTyping.NO_WRAP;
|
||||
}
|
||||
|
||||
public void setWrapOnTyping(@NotNull CommonCodeStyleSettings.WrapOnTyping value) {
|
||||
getCommonSettings().WRAP_ON_TYPING = value.intValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final CommonCodeStyleSettings getCommonSettings() {
|
||||
return myRootSettings.getCommonSettings(getLanguage());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final CommonCodeStyleSettings.IndentOptions getIndentOptions(boolean isWritable) {
|
||||
CommonCodeStyleSettings.IndentOptions indentOptions = getCommonSettings().getIndentOptions();
|
||||
if (indentOptions == null && isWritable) {
|
||||
indentOptions = getCommonSettings().initIndentOptions();
|
||||
}
|
||||
return indentOptions != null ? indentOptions : myRootSettings.OTHER_INDENT_OPTIONS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final <T extends CustomCodeStyleSettings> T getCustomSettings(@NotNull Class<T> settingsClass) {
|
||||
return myRootSettings.getCustomSettings(settingsClass);
|
||||
}
|
||||
|
||||
protected static WrapType intToWrapType(int wrap) {
|
||||
return WrapType.byLegacyRepresentation(wrap);
|
||||
}
|
||||
|
||||
protected static int wrapTypeToInt(@NotNull WrapType wrapType) {
|
||||
return wrapType.getLegacyRepresentation();
|
||||
}
|
||||
}
|
||||
@@ -185,10 +185,6 @@
|
||||
enabledByDefault="true" isInternal="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.idea.devkit.inspections.UnregisteredNamedColorInspection"/>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.idea.devkit.codeStyle.bean.CodeStyleBeanIntention</className>
|
||||
</intentionAction>
|
||||
|
||||
<moduleConfigurationEditorProvider implementation="org.jetbrains.idea.devkit.module.PluginModuleEditorsProvider"/>
|
||||
<implicitUsageProvider implementation="org.jetbrains.idea.devkit.inspections.DevKitImplicitUsageProvider"/>
|
||||
<psi.referenceContributor language="XML" implementation="org.jetbrains.idea.devkit.dom.impl.I18nReferenceContributor"/>
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.idea.devkit.codeStyle.bean;
|
||||
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CodeStyleBeanAccessorGenerator {
|
||||
|
||||
private enum ValueType {
|
||||
BOOLEAN,
|
||||
INT,
|
||||
STRING,
|
||||
WRAP,
|
||||
BRACE_STYLE,
|
||||
FORCE_BRACES,
|
||||
ENUM,
|
||||
OTHER
|
||||
}
|
||||
|
||||
private final static String BOOL_GETTER_PREFIX = "is";
|
||||
private final static String GETTER_PREFIX = "get";
|
||||
private final static String SETTER_PREFIX = "set";
|
||||
|
||||
private final @NotNull Field myField;
|
||||
private final @NotNull Class myContainerClass;
|
||||
private final @NotNull String myFieldName;
|
||||
private final @NotNull Set<String> myImports = ContainerUtil.newHashSet();
|
||||
|
||||
/**
|
||||
* Rules for method names which differ from field names for better readability.
|
||||
*/
|
||||
private final static Map<String, String> FIELD_TO_METHOD_NAME_MAP = ContainerUtilRt.newHashMap();
|
||||
|
||||
static {
|
||||
addMapping("SPACE_AFTER_SEMICOLON", "SpaceAfterForSemicolon");
|
||||
addMapping("SPACE_BEFORE_SEMICOLON", "SpaceBeforeForSemicolon");
|
||||
addMapping("LPAREN", "LeftParen");
|
||||
addMapping("RPAREN", "RightParen");
|
||||
addMapping("JD", "JavaDoc");
|
||||
addMapping("RBRACE", "RightBrace");
|
||||
addMapping("LBRACE", "LeftBrace");
|
||||
addMapping("INSTANCEOF", "InstanceOf");
|
||||
addMapping("DOWHILE", "DoWhile");
|
||||
addMapping("INDENT_SIZE", "Indent");
|
||||
addMapping("CONTINUATION_INDENT_SIZE", "ContinuationIndent");
|
||||
addMapping("PARM", "Param");
|
||||
}
|
||||
|
||||
public CodeStyleBeanAccessorGenerator(@NotNull Field field) {
|
||||
myField = field;
|
||||
myContainerClass = field.getDeclaringClass();
|
||||
myFieldName = field.getName();
|
||||
}
|
||||
|
||||
private static void addMapping(@NotNull String fieldName, @NotNull String methodName) {
|
||||
FIELD_TO_METHOD_NAME_MAP.put(fieldName, methodName);
|
||||
}
|
||||
|
||||
String getGetterName() {
|
||||
return (getValueType() == ValueType.BOOLEAN ? BOOL_GETTER_PREFIX : GETTER_PREFIX) + fieldToMethodName();
|
||||
}
|
||||
|
||||
private ValueType getValueType() {
|
||||
Class<?> fieldType = myField.getType();
|
||||
String name = fieldType.getName();
|
||||
if (fieldType.isPrimitive()) {
|
||||
if ("int".equals(name)) {
|
||||
if (myFieldName.endsWith("_WRAP")) {
|
||||
return ValueType.WRAP;
|
||||
}
|
||||
else if (myFieldName.endsWith("BRACE_STYLE")) {
|
||||
return ValueType.BRACE_STYLE;
|
||||
}
|
||||
else if (myFieldName.endsWith("_BRACE_FORCE")) {
|
||||
return ValueType.FORCE_BRACES;
|
||||
}
|
||||
return ValueType.INT;
|
||||
}
|
||||
else if ("boolean".equals(name)) {
|
||||
return ValueType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
else if ("java.lang.String".equals(name)) {
|
||||
return ValueType.STRING;
|
||||
}
|
||||
else if (fieldType.isEnum()) {
|
||||
return ValueType.ENUM;
|
||||
}
|
||||
return ValueType.OTHER;
|
||||
}
|
||||
|
||||
|
||||
private String fieldToMethodName() {
|
||||
if (FIELD_TO_METHOD_NAME_MAP.containsKey(myFieldName)) return FIELD_TO_METHOD_NAME_MAP.get(myFieldName);
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
String[] chunks = myFieldName.split("_");
|
||||
for (String chunk : chunks) {
|
||||
appendNamePart(nameBuilder, chunk);
|
||||
}
|
||||
return nameBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale")
|
||||
private static void appendNamePart(@NotNull StringBuilder nameBuilder, @NotNull String chunk) {
|
||||
if (chunk.length() > 0) {
|
||||
if (FIELD_TO_METHOD_NAME_MAP.containsKey(chunk)) {
|
||||
nameBuilder.append(FIELD_TO_METHOD_NAME_MAP.get(chunk));
|
||||
}
|
||||
else {
|
||||
nameBuilder.append(chunk.substring(0, 1).toUpperCase());
|
||||
if (chunk.length() > 1) {
|
||||
nameBuilder.append(chunk.substring(1).toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String getSetterName() {
|
||||
return SETTER_PREFIX + fieldToMethodName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getTypeString() {
|
||||
Class<?> fieldType = myField.getType();
|
||||
ValueType valueType = getValueType();
|
||||
switch (valueType) {
|
||||
case WRAP:
|
||||
myImports.add("com.intellij.formatting.WrapType");
|
||||
return "WrapType";
|
||||
case BRACE_STYLE:
|
||||
myImports.add("com.intellij.formatting.BraceStyle");
|
||||
return "BraceStyle";
|
||||
case FORCE_BRACES:
|
||||
myImports.add("com.intellij.formatting.ForceBraces");
|
||||
return "ForceBraces";
|
||||
case INT:
|
||||
case BOOLEAN:
|
||||
return fieldType.getSimpleName();
|
||||
case ENUM:
|
||||
case STRING:
|
||||
myImports.add(fieldType.getCanonicalName());
|
||||
return fieldType.getSimpleName();
|
||||
case OTHER:
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isFieldSupported() {
|
||||
return myField.getType().getCanonicalName() != null &&
|
||||
myField.getAnnotation(Deprecated.class) == null;
|
||||
}
|
||||
|
||||
String getContainerClassAccessor(boolean isWriteAccess) {
|
||||
if (myContainerClass == CommonCodeStyleSettings.class) {
|
||||
return "getCommonSettings()";
|
||||
}
|
||||
else if (myContainerClass == CommonCodeStyleSettings.IndentOptions.class) {
|
||||
return "getIndentOptions(" + isWriteAccess + ")";
|
||||
}
|
||||
myImports.add(myContainerClass.getName());
|
||||
return "getCustomSettings(" + myContainerClass.getSimpleName() + ".class)";
|
||||
}
|
||||
|
||||
void generateGetter(StringBuilder output) {
|
||||
String typeString = getTypeString();
|
||||
if (typeString != null) {
|
||||
output
|
||||
.append("public ")
|
||||
.append(getTypeString())
|
||||
.append(' ')
|
||||
.append(getGetterName())
|
||||
.append("() {\n");
|
||||
final ValueType valueType = getValueType();
|
||||
if (valueType == ValueType.WRAP) {
|
||||
output
|
||||
.append("return intToWrapType(")
|
||||
.append(getContainerClassAccessor(false))
|
||||
.append(".").append(myFieldName)
|
||||
.append(");\n");
|
||||
}
|
||||
else if (valueType == ValueType.BRACE_STYLE || valueType == ValueType.FORCE_BRACES) {
|
||||
output
|
||||
.append("return ").append(typeString).append(".fromInt(")
|
||||
.append(getContainerClassAccessor(false))
|
||||
.append(".").append(myFieldName)
|
||||
.append(");\n");
|
||||
}
|
||||
else {
|
||||
output
|
||||
.append("return ")
|
||||
.append((getContainerClassAccessor(false)))
|
||||
.append(".").append(myFieldName).append(";\n");
|
||||
}
|
||||
output
|
||||
.append("}\n");
|
||||
}
|
||||
else {
|
||||
output.append("\n // TODO: Implement ")
|
||||
.append(myFieldName)
|
||||
.append(" getter manually (unsupported type).\n");
|
||||
}
|
||||
}
|
||||
|
||||
void generateSetter(StringBuilder output) {
|
||||
final String typeString = getTypeString();
|
||||
if (typeString != null) {
|
||||
output
|
||||
.append("public void ")
|
||||
.append(getSetterName())
|
||||
.append("(")
|
||||
.append(typeString).append(" value")
|
||||
.append("){");
|
||||
output
|
||||
.append(getContainerClassAccessor(true))
|
||||
.append(".").append(myFieldName).append("= ");
|
||||
final ValueType valueType = getValueType();
|
||||
if (valueType == ValueType.WRAP) {
|
||||
output.append("wrapTypeToInt(");
|
||||
}
|
||||
output.append("value");
|
||||
if (valueType == ValueType.BRACE_STYLE || valueType == ValueType.FORCE_BRACES) {
|
||||
output.append(".intValue()");
|
||||
}
|
||||
if (valueType == ValueType.WRAP) {
|
||||
output.append(")");
|
||||
}
|
||||
output.append(";");
|
||||
output
|
||||
.append("}\n");
|
||||
}
|
||||
else {
|
||||
output.append("\n // TODO: Implement ")
|
||||
.append(myFieldName)
|
||||
.append(" setter manually (unsupported type).\n");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Set<String> getImports() {
|
||||
return myImports;
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.idea.devkit.codeStyle.bean;
|
||||
|
||||
import com.intellij.application.options.IndentOptionsEditor;
|
||||
import com.intellij.application.options.SmartIndentOptionsEditor;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class CodeStyleBeanGenerator {
|
||||
private final PsiFile myFile;
|
||||
private final PsiClass myBeanClass;
|
||||
private final Language myLanguage;
|
||||
private final Set<String> myImports = ContainerUtil.newHashSet();
|
||||
|
||||
public CodeStyleBeanGenerator(@NotNull PsiFile file, @NotNull PsiClass aClass, @NotNull Language language) {
|
||||
myFile = file;
|
||||
myBeanClass = aClass;
|
||||
myLanguage = language;
|
||||
}
|
||||
|
||||
public String generateBeanMethods() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
generateMethodsFor(CommonCodeStyleSettings.IndentOptions.class, sb, getSupportedIndentOptions());
|
||||
generateMethodsFor(CommonCodeStyleSettings.class, sb, getSupportedFields());
|
||||
for (CustomCodeStyleSettings customSettings : getCustomSettings()) {
|
||||
generateMethodsFor(customSettings.getClass(), sb, null);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Set<String> getSupportedIndentOptions() {
|
||||
LanguageCodeStyleSettingsProvider provider = LanguageCodeStyleSettingsProvider.forLanguage(myLanguage);
|
||||
if (provider == null) return Collections.emptySet();
|
||||
Set<String> indentOptions = ContainerUtil.newHashSet();
|
||||
IndentOptionsEditor editor = provider.getIndentOptionsEditor();
|
||||
if (editor != null) {
|
||||
indentOptions.add("TAB_SIZE");
|
||||
indentOptions.add("USE_TAB_CHARACTER");
|
||||
indentOptions.add("INDENT_SIZE");
|
||||
if (editor instanceof SmartIndentOptionsEditor) {
|
||||
indentOptions.add("CONTINUATION_INDENT_SIZE");
|
||||
indentOptions.add("SMART_TABS");
|
||||
indentOptions.add("KEEP_INDENTS_ON_EMPTY_LINES");
|
||||
}
|
||||
}
|
||||
return indentOptions;
|
||||
}
|
||||
|
||||
private Set<String> getSupportedFields() {
|
||||
LanguageCodeStyleSettingsProvider provider = LanguageCodeStyleSettingsProvider.forLanguage(myLanguage);
|
||||
return provider == null ? Collections.emptySet() : provider.getSupportedFields();
|
||||
}
|
||||
|
||||
private void generateMethodsFor(Class codeStyleClass, StringBuilder output, @Nullable Set<String> supportedFields) {
|
||||
for (Field field : getCodeStyleFields(codeStyleClass)) {
|
||||
CodeStyleBeanAccessorGenerator accessorGenerator = new CodeStyleBeanAccessorGenerator(field);
|
||||
String fieldName = field.getName();
|
||||
if ((supportedFields == null || supportedFields.contains(fieldName)) &&
|
||||
!beanContainsField(fieldName) &&
|
||||
accessorGenerator.isFieldSupported()) {
|
||||
String setterName = accessorGenerator.getSetterName();
|
||||
if (!superClassContainsMethod(setterName)) {
|
||||
accessorGenerator.generateGetter(output);
|
||||
}
|
||||
String getterName = accessorGenerator.getGetterName();
|
||||
if (!superClassContainsMethod(getterName)) {
|
||||
accessorGenerator.generateSetter(output);
|
||||
}
|
||||
}
|
||||
myImports.addAll(accessorGenerator.getImports());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Field> getCodeStyleFields(Class codeStyleClass) {
|
||||
List<Field> fields = new ArrayList<>();
|
||||
for (Field field : codeStyleClass.getFields()) {
|
||||
if (isPublic(field) && !isFinal(field)) {
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
private static boolean isPublic(final Field field) {
|
||||
return (field.getModifiers() & Modifier.PUBLIC) != 0;
|
||||
}
|
||||
|
||||
private static boolean isFinal(final Field field) {
|
||||
return (field.getModifiers() & Modifier.FINAL) != 0;
|
||||
}
|
||||
|
||||
private boolean beanContainsField(@NotNull String fieldName) {
|
||||
PsiMethod[] methods = myBeanClass.getMethods();
|
||||
for (PsiMethod method : methods) {
|
||||
if (methodContainsField(method, fieldName)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean superClassContainsMethod(@NotNull String methodName) {
|
||||
PsiClass superClass = myBeanClass.getSuperClass();
|
||||
if (superClass != null) {
|
||||
for (PsiMethod baseMethod : superClass.getMethods()) {
|
||||
if (methodName.equals(baseMethod.getName())) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean methodContainsField(@NotNull PsiMethod method, @NotNull String fieldName) {
|
||||
final Ref<Boolean> found = Ref.create(false);
|
||||
PsiRecursiveElementVisitor visitor = new PsiRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (element instanceof PsiIdentifier && fieldName.equals(element.getText())) {
|
||||
found.set(true);
|
||||
}
|
||||
else {
|
||||
super.visitElement(element);
|
||||
}
|
||||
}
|
||||
};
|
||||
method.accept(visitor);
|
||||
return found.get();
|
||||
}
|
||||
|
||||
private List<CustomCodeStyleSettings> getCustomSettings() {
|
||||
CodeStyleSettings rootSettings = new CodeStyleSettings();
|
||||
List<CustomCodeStyleSettings> customSettingsList = new ArrayList<>();
|
||||
addCustomSettings(customSettingsList, rootSettings, CodeStyleSettingsProvider.EXTENSION_POINT_NAME.getExtensionList());
|
||||
addCustomSettings(customSettingsList, rootSettings, LanguageCodeStyleSettingsProvider.getSettingsPagesProviders());
|
||||
return customSettingsList;
|
||||
}
|
||||
|
||||
private void addCustomSettings(@NotNull List<CustomCodeStyleSettings> list,
|
||||
@NotNull CodeStyleSettings rootSettings,
|
||||
@NotNull List<? extends CodeStyleSettingsProvider> providerList) {
|
||||
for (CodeStyleSettingsProvider provider : providerList) {
|
||||
if (provider.getLanguage() == myLanguage) {
|
||||
CustomCodeStyleSettings customSettings = provider.createCustomSettings(rootSettings);
|
||||
if (customSettings != null && resolveClass(customSettings.getClass().getName(), myFile) != null) {
|
||||
list.add(customSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PsiClass resolveClass(@NotNull String classFQN, @NotNull PsiFile file) {
|
||||
PsiResolveHelper resolveHelper = PsiResolveHelper.SERVICE.getInstance(file.getProject());
|
||||
return resolveHelper.resolveReferencedClass(classFQN, file);
|
||||
}
|
||||
|
||||
Set<String> getImports() {
|
||||
return myImports;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.idea.devkit.codeStyle.bean;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public class CodeStyleBeanIntention implements IntentionAction {
|
||||
@Nls(capitalization = Nls.Capitalization.Sentence)
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Generate CodeStyle methods";
|
||||
}
|
||||
|
||||
@Nls(capitalization = Nls.Capitalization.Sentence)
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Language plugin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
PsiClass beanClass = findBeanClass(file);
|
||||
if (beanClass != null) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
if (beanClass.getTextRange().contains(offset)) {
|
||||
PsiElement currElement = file.findElementAt(offset);
|
||||
if (currElement != null && currElement.getParent() == beanClass) {
|
||||
ASTNode leftBrace = TreeUtil.findSibling(currElement.getNode(), JavaTokenType.RBRACE);
|
||||
ASTNode rightBrace = TreeUtil.findSiblingBackward(currElement.getNode(), JavaTokenType.LBRACE);
|
||||
return leftBrace != null && rightBrace != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
PsiClass beanClass = findBeanClass(file);
|
||||
if (beanClass != null) {
|
||||
generateAccessors(beanClass, editor, file);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass findBeanClass(@NotNull PsiFile file) {
|
||||
if (file instanceof PsiJavaFile) {
|
||||
PsiClass[] classes = ((PsiJavaFile)file).getClasses();
|
||||
for (PsiClass javaClass : classes) {
|
||||
if (isCodeStyleBean(javaClass)) return javaClass;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isCodeStyleBean(@NotNull PsiClass javaClass) {
|
||||
PsiReferenceList extendsList = javaClass.getExtendsList();
|
||||
if (extendsList != null) {
|
||||
for (PsiClassType type : extendsList.getReferencedTypes()) {
|
||||
if ("CodeStyleBean".equals(type.getClassName())) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void generateAccessors(@NotNull PsiClass beanClass, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
Project project = editor.getProject();
|
||||
if (project != null) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
Language language = getLanguage(beanClass, file);
|
||||
if (language != null) {
|
||||
CodeStyleBeanGenerator beanGenerator = new CodeStyleBeanGenerator(file, beanClass, language);
|
||||
String accessorsText = beanGenerator.generateBeanMethods();
|
||||
editor.getDocument().insertString(offset, accessorsText);
|
||||
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
|
||||
CodeStyleManager.getInstance(project).reformatText(file, offset, offset + accessorsText.length());
|
||||
for (String requiredImport : beanGenerator.getImports()) {
|
||||
addImport(file, beanClass, requiredImport);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addImport(@NotNull PsiFile file, @NotNull PsiClass beanClass, @NotNull String classFQN) {
|
||||
PsiClass psiClass = CodeStyleBeanGenerator.resolveClass(classFQN, file);
|
||||
if (psiClass != null) {
|
||||
JavaCodeStyleManager.getInstance(beanClass.getProject()).addImport((PsiJavaFile)file, psiClass);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Language getLanguage(@NotNull PsiClass beanClass, @NotNull PsiFile file) {
|
||||
for (PsiMethod method : beanClass.getMethods()) {
|
||||
if ("getLanguage".equals(method.getName())) {
|
||||
PsiCodeBlock body = method.getBody();
|
||||
if (body != null) {
|
||||
for (PsiStatement statement : body.getStatements()) {
|
||||
if (statement instanceof PsiReturnStatement) {
|
||||
PsiExpression retValue = ((PsiReturnStatement)statement).getReturnValue();
|
||||
if (retValue instanceof PsiReferenceExpression) {
|
||||
PsiElement psiLangClass = retValue.getFirstChild();
|
||||
if (psiLangClass != null) {
|
||||
PsiClass resolved = CodeStyleBeanGenerator.resolveClass(psiLangClass.getText(), file);
|
||||
if (resolved != null) {
|
||||
try {
|
||||
Class langClass = Class.forName(resolved.getQualifiedName());
|
||||
if (Language.class.isAssignableFrom(langClass)) {
|
||||
//noinspection unchecked
|
||||
return Language.findInstance(langClass);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user