-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Sergey A Volkov
committed
Jan 20, 2015
0 parents
commit 6b80a33
Showing
5 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
out | ||
*.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<idea-plugin version="2"> | ||
<id>com.yourcompany.unique.plugin.id</id> | ||
<name>Plugin display name here</name> | ||
<version>1.0</version> | ||
<vendor email="[email protected]" url="http://www.yourcompany.com">YourCompany</vendor> | ||
|
||
<description><![CDATA[ | ||
Enter short description for your plugin here.<br> | ||
<em>most HTML tags may be used</em> | ||
]]></description> | ||
|
||
<change-notes><![CDATA[ | ||
Add change notes here.<br> | ||
<em>most HTML tags may be used</em> | ||
]]> | ||
</change-notes> | ||
|
||
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description --> | ||
<idea-version since-build="131"/> | ||
|
||
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products | ||
on how to target different products --> | ||
<!-- uncomment to enable plugin in all products | ||
<depends>com.intellij.modules.lang</depends> | ||
--> | ||
|
||
<extensions defaultExtensionNs="com.intellij"> | ||
<!-- Add your extensions here --> | ||
</extensions> | ||
|
||
<application-components> | ||
<!-- Add your application components here --> | ||
</application-components> | ||
|
||
<project-components> | ||
<!-- Add your project components here --> | ||
</project-components> | ||
|
||
<actions> | ||
<!-- Add your actions here --> | ||
<action id="jsoncreator.jsoncreator" class="ru.volkov.idea.jsoncreator.JsonCreatorAction" text="JsonCreator" description="creates json"> | ||
<add-to-group group-id="GenerateGroup" anchor="last"/> | ||
<keyboard-shortcut keymap="$default" first-keystroke="shift alt J" second-keystroke="shift alt K"/> | ||
</action> | ||
</actions> | ||
|
||
</idea-plugin> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<module type="PLUGIN_MODULE" version="4"> | ||
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/META-INF/plugin.xml" /> | ||
<component name="NewModuleRootManager" inherit-compiler-output="true"> | ||
<exclude-output /> | ||
<content url="file://$MODULE_DIR$"> | ||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||
</content> | ||
<orderEntry type="inheritedJdk" /> | ||
<orderEntry type="sourceFolder" forTests="false" /> | ||
</component> | ||
</module> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package ru.volkov.idea.jsoncreator; | ||
|
||
import com.intellij.codeInsight.generation.actions.BaseGenerateAction; | ||
import com.intellij.psi.PsiAnonymousClass; | ||
import com.intellij.psi.PsiClass; | ||
|
||
/** | ||
* User: serg-v | ||
* Date: 12/15/14 | ||
* Time: 3:07 AM | ||
*/ | ||
public class JsonCreatorAction extends BaseGenerateAction { | ||
|
||
public JsonCreatorAction() { | ||
super(new JsonCreatorHandler()); | ||
} | ||
|
||
@Override | ||
protected boolean isValidForClass(final PsiClass targetClass) { | ||
return super.isValidForClass(targetClass) && !(targetClass instanceof PsiAnonymousClass); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package ru.volkov.idea.jsoncreator; | ||
|
||
import org.jetbrains.annotations.NonNls; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
|
||
import com.intellij.codeInsight.NullableNotNullManager; | ||
import com.intellij.codeInsight.generation.*; | ||
import com.intellij.openapi.diagnostic.Logger; | ||
import com.intellij.psi.*; | ||
import com.intellij.psi.codeStyle.CodeStyleManager; | ||
import com.intellij.psi.codeStyle.JavaCodeStyleManager; | ||
import com.intellij.psi.codeStyle.VariableKind; | ||
import com.intellij.psi.javadoc.PsiDocComment; | ||
import com.intellij.psi.util.TypeConversionUtil; | ||
import com.intellij.util.IncorrectOperationException; | ||
|
||
/** | ||
* User: serg-v | ||
* Date: 12/15/14 | ||
* Time: 3:12 AM | ||
*/ | ||
public class JsonCreatorHandler extends GenerateConstructorHandler { | ||
|
||
private static final Logger LOG = Logger.getInstance("#ru.volkov.idea.jsoncreator.JsonCreatorHandler"); | ||
|
||
@Override | ||
@NotNull | ||
protected List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] members) throws | ||
IncorrectOperationException | ||
{ | ||
List<PsiMethod> baseConstructors = new ArrayList<PsiMethod>(); | ||
List<PsiField> fieldsVector = new ArrayList<PsiField>(); | ||
for (ClassMember member1 : members) { | ||
PsiElement member = ((PsiElementClassMember) member1).getElement(); | ||
if (member instanceof PsiMethod) { | ||
baseConstructors.add((PsiMethod) member); | ||
} else { | ||
fieldsVector.add((PsiField) member); | ||
} | ||
} | ||
PsiField[] fields = fieldsVector.toArray(new PsiField[fieldsVector.size()]); | ||
|
||
if (!baseConstructors.isEmpty()) { | ||
List<GenerationInfo> constructors = new ArrayList<GenerationInfo>(baseConstructors.size()); | ||
final PsiClass superClass = aClass.getSuperClass(); | ||
assert superClass != null; | ||
PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); | ||
for (PsiMethod baseConstructor : baseConstructors) { | ||
baseConstructor = GenerateMembersUtil.substituteGenericMethod(baseConstructor, substitutor, aClass); | ||
constructors.add(new PsiGenerationInfo(generateConstructorPrototype(aClass, baseConstructor, false, fields))); | ||
} | ||
return filterOutAlreadyInsertedConstructors(aClass, constructors); | ||
} | ||
final List<GenerationInfo> constructors = | ||
Collections.<GenerationInfo>singletonList(new PsiGenerationInfo(generateConstructorPrototype(aClass, null, false, fields))); | ||
return filterOutAlreadyInsertedConstructors(aClass, constructors); | ||
} | ||
|
||
private static List<? extends GenerationInfo> filterOutAlreadyInsertedConstructors(PsiClass aClass, | ||
List<? extends GenerationInfo> constructors) | ||
{ | ||
boolean alreadyExist = true; | ||
for (GenerationInfo constructor : constructors) { | ||
alreadyExist &= aClass.findMethodBySignature((PsiMethod) constructor.getPsiMember(), false) != null; | ||
} | ||
if (alreadyExist) { | ||
return Collections.emptyList(); | ||
} | ||
return constructors; | ||
} | ||
|
||
public static PsiMethod generateConstructorPrototype(PsiClass aClass, PsiMethod baseConstructor, boolean copyJavaDoc, | ||
PsiField[] fields) throws | ||
IncorrectOperationException | ||
{ | ||
PsiManager manager = aClass.getManager(); | ||
JVMElementFactory factory = JVMElementFactories.requireFactory(aClass.getLanguage(), aClass.getProject()); | ||
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); | ||
|
||
|
||
PsiMethod constructor = factory.createConstructor(aClass.getName(), aClass); | ||
constructor.getModifierList().addAnnotation("com.fasterxml.jackson.annotation.JsonCreator"); | ||
|
||
GenerateMembersUtil.setVisibility(aClass, constructor); | ||
|
||
if (baseConstructor != null) { | ||
PsiJavaCodeReferenceElement[] throwRefs = baseConstructor.getThrowsList().getReferenceElements(); | ||
for (PsiJavaCodeReferenceElement ref : throwRefs) { | ||
constructor.getThrowsList().add(ref); | ||
} | ||
|
||
if (copyJavaDoc) { | ||
final PsiDocComment docComment = ((PsiMethod) baseConstructor.getNavigationElement()).getDocComment(); | ||
if (docComment != null) { | ||
constructor.addAfter(docComment, null); | ||
} | ||
} | ||
} | ||
|
||
boolean isNotEnum = false; | ||
if (baseConstructor != null) { | ||
PsiClass superClass = aClass.getSuperClass(); | ||
LOG.assertTrue(superClass != null); | ||
if (!CommonClassNames.JAVA_LANG_ENUM.equals(superClass.getQualifiedName())) { | ||
isNotEnum = true; | ||
if (baseConstructor instanceof PsiCompiledElement) { // to get some parameter names | ||
PsiClass dummyClass = JVMElementFactories.requireFactory(baseConstructor.getLanguage(), baseConstructor.getProject()).createClass("Dummy"); | ||
baseConstructor = (PsiMethod) dummyClass.add(baseConstructor); | ||
} | ||
PsiParameter[] params = baseConstructor.getParameterList().getParameters(); | ||
for (PsiParameter param : params) { | ||
PsiParameter newParam = factory.createParameter(param.getName(), param.getType(), aClass); | ||
GenerateMembersUtil.copyOrReplaceModifierList(param, newParam); | ||
constructor.getParameterList().add(newParam); | ||
} | ||
} | ||
} | ||
|
||
JavaCodeStyleManager javaStyle = JavaCodeStyleManager.getInstance(aClass.getProject()); | ||
|
||
final PsiMethod dummyConstructor = factory.createConstructor(aClass.getName()); | ||
dummyConstructor.getParameterList().replace(constructor.getParameterList().copy()); | ||
List<PsiParameter> fieldParams = new ArrayList<PsiParameter>(); | ||
for (PsiField field : fields) { | ||
String fieldName = field.getName(); | ||
String name = javaStyle.variableNameToPropertyName(fieldName, VariableKind.FIELD); | ||
String parmName = javaStyle.propertyNameToVariableName(name, VariableKind.PARAMETER); | ||
parmName = javaStyle.suggestUniqueVariableName(parmName, dummyConstructor, true); | ||
PsiParameter parm = factory.createParameter(parmName, field.getType(), aClass); | ||
|
||
|
||
final PsiAnnotation annotation = parm.getModifierList().addAnnotation("com.fasterxml.jackson.annotation.JsonProperty"); | ||
PsiAnnotationSupport support = LanguageAnnotationSupport.INSTANCE.forLanguage(annotation.getLanguage()); | ||
annotation.setDeclaredAttributeValue("value", support.createLiteralValue(name, annotation)); | ||
final NullableNotNullManager nullableManager = NullableNotNullManager.getInstance(field.getProject()); | ||
final PsiAnnotation notNull = nullableManager.copyNotNullAnnotation(field); | ||
if (notNull != null) { | ||
parm.getModifierList().addAfter(notNull, null); | ||
} | ||
|
||
constructor.getParameterList().add(parm); | ||
dummyConstructor.getParameterList().add(parm.copy()); | ||
fieldParams.add(parm); | ||
} | ||
|
||
ConstructorBodyGenerator generator = ConstructorBodyGenerator.INSTANCE.forLanguage(aClass.getLanguage()); | ||
if (generator != null) { | ||
@NonNls StringBuilder buffer = new StringBuilder(); | ||
generator.start(buffer, constructor.getName(), PsiParameter.EMPTY_ARRAY); | ||
if (isNotEnum) { | ||
generator.generateSuperCallIfNeeded(buffer, baseConstructor.getParameterList().getParameters()); | ||
} | ||
generator.generateFieldInitialization(buffer, fields, fieldParams.toArray(new PsiParameter[fieldParams.size()])); | ||
generator.finish(buffer); | ||
PsiMethod stub = factory.createMethodFromText(buffer.toString(), aClass); | ||
constructor.getBody().replace(stub.getBody()); | ||
} | ||
|
||
constructor = (PsiMethod) codeStyleManager.reformat(constructor); | ||
return constructor; | ||
} | ||
|
||
} |