Rearrange and format annotations

Answered

Hi,

I'd like my plugin to offer support for sorting annotations (either alphabetically or by length) and collapsing multi-line annotations with only a single parameter to a single line. This could be done via an intention per annotated element or as part of the "Reformat" action, the latter being preferred.

For example:

@Setter (value = AccessLevel.NONE)
@Column (
nullable = false)
private String aField;

would be reformatted to:

@Column (nullable = false)
@Setter (value = AccessLevel.NONE)
private String aField;

Unfortunately the documentation on this topic is very sparse; I could only find a link to the Rearranger interface. Its JavaDoc isn't all that useful to figuring out how to implement the functionality that I'm after. Could someone give me a few pointers on where to start with this?

1
9 comments

Unfortunately existing Rearranger for language cannot be extended by 3rd party plugin with new rules/arrangement types like the one you proposed.

You can implement com.intellij.codeInspection.CleanupLocalInspectionTool in your inspection so that fully-automated quickfix to rearrange/sort can be applied to whole file/scope in one go.

0

Thanks,

I have implemented it as a LocalQuickFix that can be triggered from a corresponding AbstractBaseJavaLocalInspectionTool. This works fine and due to the latter implementing CleanupLocalInspectionTool as you described, the quick fix can be applied to the entire file. Is there a way to automatically do this when the file is reformatted, i.e. using the "Reformat Code" action?

Essentially my goal is to have the annotation sorting as part of the standard code formatting.

0

The option to invoke "Code Cleanup" is available in Reformat dialog

0

Unfortunately running "Code Cleanup" does not appear to execute my inspection's quick fix. When directly selecting any code highlighted by the inspection and invoking the quick fix popup, my fix is shown and provides a "Fix all 'x' problems in file" option in its sub-menu, which works. However, when I run the "Code Cleanup" action, the quick fix does not run (neither when running "Code Cleanup" on the file nor when checking it in the reformat dialog).

public class AnnotationOrderInspection extends AbstractBaseJavaLocalInspectionTool implements CleanupLocalInspectionTool {

@Nullable
@Override
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
List<ProblemDescriptor> problems = new ArrayList<>();

boolean ordered = areInOrder(method.getAnnotations());
if (!ordered) {
problems.add(manager.createProblemDescriptor(method.getModifierList(),
"Non-alphabetical annotation order on method: " + method.getName(),
new OrderAnnotationsQuickFix(), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, true));
}

if (!problems.isEmpty()) {
return problems.toArray(new ProblemDescriptor[0]);
}

return null;
}

// Pretty much duplicated for checkClass and checkField
}
public class OrderAnnotationsQuickFix implements LocalQuickFix {

@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
// Sort annotations on problem descriptor's PSI element
}

...
}
0

Could you please verify registration of Inspection has cleanupTool="true" in plugin.xml registration?

0

That was indeed missing, the inspection's quick fix is now run as part of the "Code Cleanup" action.

However I'd like to run the fix as part of only the standard "Reformat Code" action (Ctrl+Alt+L). The "Code Cleanup" action performs a lot of other, in my case not required, cleanup and can be very slow on large files.

I need the annotation sorting to be a lightweight formatting operation run when the file is formatted, without running any of the sometimes fairly expensive code cleanup actions. Also I don't want to require my users to open the "Reformat Code" dialog and enable an additional option or configure anything regarding the cleanup profile.

It should just be added as yet another step in the code formatting, just like that already indents code, adds/removes line breaks, etc. Is that possible?

0

Actually there is com.intellij.psi.impl.source.codeStyle.PostFormatProcessor which seems to be the most straightforward approach. You should be able to re-use a lot of your inspection's code though - sorry :-/

0

I have now implemented a PostFormatProcessor which uses a custom JavaRecursiveElementWalkingVisitor to visit all PsiModifierListOwners and sort their annotations. This works just like I need it, thanks for the advice!

0
Avatar
Permanently deleted user

@BVollmerhaus if possible, could you share your implementations (e.g. in a gist)? It would be much appreciated. 

0

Please sign in to leave a comment.