mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
IDEA-19061 Integrate the Rearranger-plugin into core-IDEA
1. Arrangement core engine is provided; 2. Arrangement tests infrastructure is provided; 3. Added java-specific support for arrangement by type, name and modifier; 4. Corresponding tests are added;
This commit is contained in:
+195
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class JavaArrangementVisitor extends JavaElementVisitor {
|
||||
|
||||
private static final Map<String, ArrangementModifier> MODIFIERS = new HashMap<String, ArrangementModifier>();
|
||||
static {
|
||||
MODIFIERS.put(PsiModifier.PUBLIC, ArrangementModifier.PUBLIC);
|
||||
MODIFIERS.put(PsiModifier.PROTECTED, ArrangementModifier.PROTECTED);
|
||||
MODIFIERS.put(PsiModifier.PRIVATE, ArrangementModifier.PRIVATE);
|
||||
MODIFIERS.put(PsiModifier.PACKAGE_LOCAL, ArrangementModifier.PACKAGE_PRIVATE);
|
||||
MODIFIERS.put(PsiModifier.STATIC, ArrangementModifier.STATIC);
|
||||
MODIFIERS.put(PsiModifier.FINAL, ArrangementModifier.FINAL);
|
||||
}
|
||||
|
||||
private final Stack<JavaElementArrangementEntry> myStack = new Stack<JavaElementArrangementEntry>();
|
||||
|
||||
@NotNull private final List<JavaElementArrangementEntry> myRootEntries;
|
||||
@NotNull private Document myDocument;
|
||||
@NotNull private Collection<TextRange> myRanges;
|
||||
|
||||
public JavaArrangementVisitor(@NotNull List<JavaElementArrangementEntry> entries,
|
||||
@NotNull Document document,
|
||||
@NotNull Collection<TextRange> ranges)
|
||||
{
|
||||
myRootEntries = entries;
|
||||
myDocument = document;
|
||||
myRanges = ranges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClass(PsiClass aClass) {
|
||||
JavaElementArrangementEntry entry = createNewEntry(aClass.getTextRange(), ArrangementEntryType.CLASS, aClass.getName(), true);
|
||||
processEntry(entry, aClass, aClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAnonymousClass(PsiAnonymousClass aClass) {
|
||||
JavaElementArrangementEntry entry = createNewEntry(aClass.getTextRange(), ArrangementEntryType.CLASS, aClass.getName(), false);
|
||||
processEntry(entry, null, aClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJavaFile(PsiJavaFile file) {
|
||||
for (PsiClass psiClass : file.getClasses()) {
|
||||
visitClass(psiClass);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(PsiField field) {
|
||||
JavaElementArrangementEntry entry = createNewEntry(field.getTextRange(), ArrangementEntryType.FIELD, field.getName(), true);
|
||||
processEntry(entry, field, field.getInitializer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(PsiMethod method) {
|
||||
JavaElementArrangementEntry entry = createNewEntry(method.getTextRange(), ArrangementEntryType.METHOD, method.getName(), true);
|
||||
processEntry(entry, method, method.getBody());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpressionStatement(PsiExpressionStatement statement) {
|
||||
statement.getExpression().acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewExpression(PsiNewExpression expression) {
|
||||
PsiAnonymousClass anonymousClass = expression.getAnonymousClass();
|
||||
if (anonymousClass == null) {
|
||||
return;
|
||||
}
|
||||
JavaElementArrangementEntry entry =
|
||||
createNewEntry(anonymousClass.getTextRange(), ArrangementEntryType.CLASS, anonymousClass.getName(), false);
|
||||
processEntry(entry, null, anonymousClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpressionList(PsiExpressionList list) {
|
||||
for (PsiExpression expression : list.getExpressions()) {
|
||||
expression.acceptChildren(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDeclarationStatement(PsiDeclarationStatement statement) {
|
||||
for (PsiElement element : statement.getDeclaredElements()) {
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void processEntry(@Nullable JavaElementArrangementEntry entry,
|
||||
@Nullable PsiModifierListOwner modifier,
|
||||
@Nullable PsiElement nextPsiRoot)
|
||||
{
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
if (modifier != null) {
|
||||
parseModifiers(modifier.getModifierList(), entry);
|
||||
}
|
||||
if (nextPsiRoot == null) {
|
||||
return;
|
||||
}
|
||||
myStack.push(entry);
|
||||
try {
|
||||
nextPsiRoot.acceptChildren(this);
|
||||
}
|
||||
finally {
|
||||
myStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JavaElementArrangementEntry createNewEntry(@NotNull TextRange range,
|
||||
@NotNull ArrangementEntryType type,
|
||||
@Nullable String name,
|
||||
boolean canArrange)
|
||||
{
|
||||
if (!isWithinBounds(range)) {
|
||||
return null;
|
||||
}
|
||||
DefaultArrangementEntry current = getCurrent();
|
||||
JavaElementArrangementEntry entry;
|
||||
if (canArrange) {
|
||||
TextRange expandedRange = ArrangementUtil.expandToLine(range, myDocument.getCharsSequence());
|
||||
TextRange rangeToUse = expandedRange == null ? range : expandedRange;
|
||||
entry = new JavaElementArrangementEntry(current, rangeToUse, type, name, expandedRange != null);
|
||||
}
|
||||
else {
|
||||
entry = new JavaElementArrangementEntry(current, range, type, name, false);
|
||||
}
|
||||
if (current == null) {
|
||||
myRootEntries.add(entry);
|
||||
}
|
||||
else {
|
||||
current.addChild(entry);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
private boolean isWithinBounds(@NotNull TextRange range) {
|
||||
for (TextRange textRange : myRanges) {
|
||||
if (textRange.intersects(range)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DefaultArrangementEntry getCurrent() {
|
||||
return myStack.isEmpty() ? null : myStack.peek();
|
||||
}
|
||||
|
||||
private static void parseModifiers(@Nullable PsiModifierList modifierList, @NotNull JavaElementArrangementEntry entry) {
|
||||
if (modifierList == null) {
|
||||
return;
|
||||
}
|
||||
for (String modifier : PsiModifier.MODIFIERS) {
|
||||
if (modifierList.hasModifierProperty(modifier)) {
|
||||
entry.addModifier(MODIFIERS.get(modifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ModifierAwareArrangementEntry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 7/20/12 4:50 PM
|
||||
*/
|
||||
public class JavaElementArrangementEntry extends DefaultArrangementEntry
|
||||
implements TypeAwareArrangementEntry, NameAwareArrangementEntry,ModifierAwareArrangementEntry
|
||||
{
|
||||
|
||||
private final Set<ArrangementModifier> myModifiers = EnumSet.noneOf(ArrangementModifier.class);
|
||||
|
||||
@NotNull private final ArrangementEntryType myType;
|
||||
@Nullable private final String myName;
|
||||
|
||||
public JavaElementArrangementEntry(@Nullable ArrangementEntry parent,
|
||||
@NotNull TextRange range,
|
||||
@NotNull ArrangementEntryType type,
|
||||
@Nullable String name,
|
||||
boolean canBeMatched)
|
||||
{
|
||||
this(parent, range.getStartOffset(), range.getEndOffset(), type, name, canBeMatched);
|
||||
}
|
||||
|
||||
public JavaElementArrangementEntry(@Nullable ArrangementEntry parent,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull ArrangementEntryType type,
|
||||
@Nullable String name,
|
||||
boolean canBeArranged)
|
||||
{
|
||||
super(parent, startOffset, endOffset, canBeArranged);
|
||||
myType = type;
|
||||
myName = name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<ArrangementModifier> getModifiers() {
|
||||
return myModifiers;
|
||||
}
|
||||
|
||||
public void addModifier(@NotNull ArrangementModifier modifier) {
|
||||
myModifiers.add(modifier);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ArrangementEntryType getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"[%d; %d): %s %s %s",
|
||||
getStartOffset(), getEndOffset(), StringUtil.join(myModifiers, " ").toLowerCase(), myType.toString().toLowerCase(),
|
||||
myName == null ? "<no name>" : myName
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 7/20/12 2:31 PM
|
||||
*/
|
||||
public class JavaRearranger implements Rearranger<JavaElementArrangementEntry> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JavaElementArrangementEntry> parse(@NotNull PsiElement root,
|
||||
@NotNull Document document,
|
||||
@NotNull Collection<TextRange> ranges)
|
||||
{
|
||||
// Following entries are subject to arrangement: class, interface, field, method.
|
||||
List<JavaElementArrangementEntry> result = new ArrayList<JavaElementArrangementEntry>();
|
||||
root.accept(new JavaArrangementVisitor(result, document, ranges));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user