mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -30,6 +30,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor {
|
||||
|
||||
private JCheckBox myLabelIndentAbsolute;
|
||||
private JCheckBox myCbDontIndentTopLevelMembers;
|
||||
private JCheckBox myCbUseRelativeIndent;
|
||||
|
||||
protected void addComponents() {
|
||||
super.addComponents();
|
||||
@@ -42,6 +43,9 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor {
|
||||
|
||||
myCbDontIndentTopLevelMembers = new JCheckBox(ApplicationBundle.message("checkbox.do.not.indent.top.level.class.members"));
|
||||
add(myCbDontIndentTopLevelMembers);
|
||||
|
||||
myCbUseRelativeIndent = new JCheckBox(ApplicationBundle.message("checkbox.use.relative.indents"));
|
||||
add(myCbUseRelativeIndent);
|
||||
}
|
||||
|
||||
public boolean isModified(final CodeStyleSettings settings, final CodeStyleSettings.IndentOptions options) {
|
||||
@@ -50,6 +54,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor {
|
||||
isModified |= isFieldModified(myLabelIndent, options.LABEL_INDENT_SIZE);
|
||||
isModified |= isFieldModified(myLabelIndentAbsolute, options.LABEL_INDENT_ABSOLUTE);
|
||||
isModified |= isFieldModified(myCbDontIndentTopLevelMembers, settings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS);
|
||||
isModified |= isFieldModified(myCbUseRelativeIndent, options.USE_RELATIVE_INDENTS);
|
||||
|
||||
return isModified;
|
||||
}
|
||||
@@ -64,6 +69,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor {
|
||||
}
|
||||
options.LABEL_INDENT_ABSOLUTE = myLabelIndentAbsolute.isSelected();
|
||||
settings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS = myCbDontIndentTopLevelMembers.isSelected();
|
||||
options.USE_RELATIVE_INDENTS = myCbUseRelativeIndent.isSelected();
|
||||
}
|
||||
|
||||
public void reset(@NotNull final CodeStyleSettings settings, @NotNull final CodeStyleSettings.IndentOptions options) {
|
||||
@@ -71,6 +77,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor {
|
||||
myLabelIndent.setText(Integer.toString(options.LABEL_INDENT_SIZE));
|
||||
myLabelIndentAbsolute.setSelected(options.LABEL_INDENT_ABSOLUTE);
|
||||
myCbDontIndentTopLevelMembers.setSelected(settings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS);
|
||||
myCbUseRelativeIndent.setSelected(options.USE_RELATIVE_INDENTS);
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
|
||||
+3
@@ -154,6 +154,9 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
|
||||
|
||||
@Override
|
||||
protected void reformat(PsiElement atCaret) throws IncorrectOperationException {
|
||||
if (atCaret == null) {
|
||||
return;
|
||||
}
|
||||
PsiElement parent = atCaret.getParent();
|
||||
if (parent instanceof PsiCodeBlock) {
|
||||
final PsiCodeBlock block = (PsiCodeBlock) parent;
|
||||
|
||||
@@ -430,22 +430,26 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public PsiComment findExistingDocComment(final PsiComment _element) {
|
||||
PsiElement parentElement = _element.getParent();
|
||||
|
||||
return parentElement instanceof PsiDocCommentOwner ? ((PsiDocCommentOwner)parentElement).getDocComment() : null;
|
||||
public PsiComment findExistingDocComment(final PsiComment comment) {
|
||||
if (comment instanceof PsiDocComment) {
|
||||
final PsiDocCommentOwner owner = ((PsiDocComment)comment).getOwner();
|
||||
if (owner != null) {
|
||||
return owner.getDocComment();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String generateDocumentationContentStub(PsiComment _element) {
|
||||
PsiElement parentElement = _element.getParent();
|
||||
final Project project = _element.getProject();
|
||||
public String generateDocumentationContentStub(PsiComment _comment) {
|
||||
final PsiDocCommentOwner commentOwner = ((PsiDocComment)_comment).getOwner();
|
||||
final Project project = commentOwner.getProject();
|
||||
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
if (parentElement instanceof PsiMethod) {
|
||||
PsiMethod psiMethod = (PsiMethod)parentElement;
|
||||
final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)LanguageCommenters.INSTANCE
|
||||
.forLanguage(commentOwner.getLanguage());
|
||||
if (commentOwner instanceof PsiMethod) {
|
||||
PsiMethod psiMethod = (PsiMethod)commentOwner;
|
||||
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
|
||||
final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)LanguageCommenters.INSTANCE
|
||||
.forLanguage(parentElement.getLanguage());
|
||||
final Map<String, String> param2Description = new HashMap<String, String>();
|
||||
final PsiMethod[] superMethods = psiMethod.findSuperMethods();
|
||||
for (PsiMethod superMethod : superMethods) {
|
||||
@@ -499,11 +503,9 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
|
||||
builder.append(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
else if (parentElement instanceof PsiClass) {
|
||||
final PsiTypeParameterList typeParameterList = ((PsiClass)parentElement).getTypeParameterList();
|
||||
else if (commentOwner instanceof PsiClass) {
|
||||
final PsiTypeParameterList typeParameterList = ((PsiClass)commentOwner).getTypeParameterList();
|
||||
if (typeParameterList != null) {
|
||||
final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)LanguageCommenters.INSTANCE
|
||||
.forLanguage(parentElement.getLanguage());
|
||||
createTypeParamsListComment(builder, project, commenter, typeParameterList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,10 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean isRBrace(final ASTNode child) {
|
||||
return child.getElementType() == ElementType.RBRACE;
|
||||
}
|
||||
|
||||
public Spacing getSpacing(Block child1, Block child2) {
|
||||
return JavaSpacePropertyProcessor.getSpacing(getTreeNode(child2), mySettings);
|
||||
}
|
||||
@@ -1080,4 +1084,32 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
return JavaBlockUtil.mayShiftIndentInside(myNode);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ASTNode composeCodeBlock(final ArrayList<Block> result, ASTNode child, final Indent indent, final int childrenIndent) {
|
||||
final ArrayList<Block> localResult = new ArrayList<Block>();
|
||||
processChild(localResult, child, null, null, Indent.getNoneIndent());
|
||||
child = child.getTreeNext();
|
||||
while (child != null) {
|
||||
if (!FormatterUtil.containsWhiteSpacesOnly(child)) {
|
||||
final boolean rBrace = isRBrace(child);
|
||||
final Indent childIndent = rBrace ? Indent.getNoneIndent() : getCodeBlockInternalIndent(childrenIndent);
|
||||
child = processChild(localResult, child, null, null, childIndent);
|
||||
if (rBrace) {
|
||||
result.add(createCodeBlockBlock(localResult, indent, childrenIndent));
|
||||
return child;
|
||||
}
|
||||
}
|
||||
if (child != null) {
|
||||
child = child.getTreeNext();
|
||||
}
|
||||
}
|
||||
result.add(createCodeBlockBlock(localResult, indent, childrenIndent));
|
||||
return null;
|
||||
}
|
||||
|
||||
private SyntheticCodeBlock createCodeBlockBlock(final ArrayList<Block> localResult, final Indent indent, final int childrenIndent) {
|
||||
final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), indent, null);
|
||||
result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(childrenIndent), null));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.psi.formatter.java;
|
||||
|
||||
import com.intellij.formatting.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.FormatterUtil;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
@@ -52,6 +53,7 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{
|
||||
|
||||
private void buildChildren(final ArrayList<Block> result, final Alignment childAlignment, final Wrap childWrap) {
|
||||
ASTNode child = myNode.getFirstChildNode();
|
||||
ASTNode prevChild = null;
|
||||
|
||||
int state = BEFORE_FIRST;
|
||||
|
||||
@@ -60,7 +62,26 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{
|
||||
final Indent indent = calcIndent(child, state);
|
||||
myIndentsBefore.add(calcIndentBefore(child, state));
|
||||
state = calcNewState(child, state);
|
||||
child = processChild(result, child, childAlignment, childWrap, indent);
|
||||
|
||||
// The general idea is that it's possible that there are comment lines before method declaration line and that they have
|
||||
// different indents. Example:
|
||||
//
|
||||
// // This is comment before method
|
||||
// void foo() {}
|
||||
//
|
||||
// We want to have the comment and method as distinct blocks then in order to correctly process indentation for inner method
|
||||
// elements. See IDEA-53778 for example of situation when it is significant.
|
||||
if (prevChild != null && myNode.getElementType() == ElementType.METHOD
|
||||
&& JavaTokenType.COMMENT_BIT_SET.contains(prevChild.getElementType())
|
||||
&& !JavaTokenType.COMMENT_BIT_SET.contains(child.getElementType()))
|
||||
{
|
||||
prevChild = child;
|
||||
child = composeCodeBlock(result, child, Indent.getNoneIndent(), 0);
|
||||
}
|
||||
else {
|
||||
prevChild = child;
|
||||
child = processChild(result, child, childAlignment, childWrap, indent);
|
||||
}
|
||||
for (int i = myIndentsBefore.size(); i < result.size(); i++) {
|
||||
myIndentsBefore.add(Indent.getContinuationIndent());
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
child = processCaseAndStatementAfter(result, child, childAlignment, childWrap, indent);
|
||||
}
|
||||
else if (myNode.getElementType() == ElementType.CLASS && child.getElementType() == ElementType.LBRACE) {
|
||||
child = composeCodeBlock(result, child, getCodeBlockExternalIndent());
|
||||
child = composeCodeBlock(result, child, getCodeBlockExternalIndent(), myChildrenIndent);
|
||||
}
|
||||
else {
|
||||
child = processChild(result, child, childAlignment, childWrap, indent);
|
||||
@@ -98,35 +98,6 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ASTNode composeCodeBlock(final ArrayList<Block> result, ASTNode child, final Indent indent) {
|
||||
final ArrayList<Block> localResult = new ArrayList<Block>();
|
||||
processChild(localResult, child, null, null, Indent.getNoneIndent());
|
||||
child = child.getTreeNext();
|
||||
while (child != null) {
|
||||
if (!FormatterUtil.containsWhiteSpacesOnly(child)) {
|
||||
final boolean rBrace = isRBrace(child);
|
||||
final Indent childIndent = rBrace ? Indent.getNoneIndent() : getCodeBlockInternalIndent(myChildrenIndent);
|
||||
child = processChild(localResult, child, null, null, childIndent);
|
||||
if (rBrace) {
|
||||
result.add(createCodeBlockBlock(localResult, indent));
|
||||
return child;
|
||||
}
|
||||
}
|
||||
if (child != null) {
|
||||
child = child.getTreeNext();
|
||||
}
|
||||
}
|
||||
result.add(createCodeBlockBlock(localResult, indent));
|
||||
return null;
|
||||
}
|
||||
|
||||
private SyntheticCodeBlock createCodeBlockBlock(final ArrayList<Block> localResult, final Indent indent) {
|
||||
final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), indent, null);
|
||||
result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(myChildrenIndent), null));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ASTNode processCaseAndStatementAfter(final ArrayList<Block> result,
|
||||
ASTNode child,
|
||||
@@ -253,10 +224,6 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isRBrace(final ASTNode child) {
|
||||
return child.getElementType() == ElementType.RBRACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ChildAttributes getChildAttributes(final int newChildIndex) {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.JavaDocElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
@@ -26,12 +25,10 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class ClsDocCommentImpl extends ClsElementImpl implements PsiDocComment, JavaTokenType, PsiJavaToken {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsDocCommentImpl");
|
||||
|
||||
private final ClsElementImpl myParent;
|
||||
private final PsiDocCommentOwner myParent;
|
||||
private final PsiDocTag[] myTags;
|
||||
|
||||
ClsDocCommentImpl(ClsElementImpl parent) {
|
||||
ClsDocCommentImpl(PsiDocCommentOwner parent) {
|
||||
myParent = parent;
|
||||
|
||||
PsiDocTag[] tags = new PsiDocTag[1];
|
||||
@@ -63,10 +60,16 @@ class ClsDocCommentImpl extends ClsElementImpl implements PsiDocComment, JavaTok
|
||||
return myParent;
|
||||
}
|
||||
|
||||
public PsiDocCommentOwner getOwner() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getDescriptionElements() {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiDocTag[] getTags() {
|
||||
return myTags;
|
||||
}
|
||||
@@ -76,6 +79,7 @@ class ClsDocCommentImpl extends ClsElementImpl implements PsiDocComment, JavaTok
|
||||
return getTags()[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiDocTag[] findTagsByName(@NonNls String name) {
|
||||
if (!name.equals("deprecated")) return PsiDocTag.EMPTY_ARRAY;
|
||||
return getTags();
|
||||
|
||||
@@ -18,10 +18,7 @@ package com.intellij.psi.impl.source.javadoc;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.JavaElementVisitor;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.impl.source.Constants;
|
||||
import com.intellij.psi.impl.source.PsiElementArrayConstructor;
|
||||
@@ -57,18 +54,32 @@ public class PsiDocCommentImpl extends LazyParseablePsiElement implements PsiDoc
|
||||
super(JavaDocElementType.DOC_COMMENT, text);
|
||||
}
|
||||
|
||||
public PsiDocCommentOwner getOwner() {
|
||||
final PsiElement parent = getParent();
|
||||
if (parent instanceof PsiDocCommentOwner) {
|
||||
final PsiDocCommentOwner owner = (PsiDocCommentOwner)parent;
|
||||
if (owner.getDocComment() == this) {
|
||||
return owner;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getDescriptionElements() {
|
||||
ArrayList<ASTNode> array = new ArrayList<ASTNode>();
|
||||
ArrayList<PsiElement> array = new ArrayList<PsiElement>();
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
IElementType i = child.getElementType();
|
||||
if (i == DOC_TAG) break;
|
||||
if (i != DOC_COMMENT_START && i != DOC_COMMENT_END && i != DOC_COMMENT_LEADING_ASTERISKS) {
|
||||
array.add(child);
|
||||
array.add(child.getPsi());
|
||||
}
|
||||
}
|
||||
return array.toArray(new PsiElement[array.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiDocTag[] getTags() {
|
||||
return getChildrenAsPsiElements(TAG_BIT_SET, PSI_TAG_ARRAY_CONSTRUCTOR);
|
||||
}
|
||||
@@ -92,6 +103,7 @@ public class PsiDocCommentImpl extends LazyParseablePsiElement implements PsiDoc
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiDocTag[] findTagsByName(String name) {
|
||||
ArrayList<PsiDocTag> array = new ArrayList<PsiDocTag>();
|
||||
PsiDocTag[] tags = getTags();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class X {
|
||||
|
||||
/**
|
||||
* Has a method called {@link #mymethod(int,int)}.
|
||||
* Has a method called {@link #mymethod(int, int)}.
|
||||
*/
|
||||
public class TestRefactorLink {
|
||||
public void <caret>mymethod(int y, int z) { }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class X {
|
||||
|
||||
/**
|
||||
* Has a method called {@link #mymethod(int,boolean)}.
|
||||
* Has a method called {@link #mymethod(int, boolean)}.
|
||||
*/
|
||||
public class TestRefactorLink {
|
||||
public void mymethod(int y, boolean b) { }
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -74,6 +75,10 @@ public abstract class AbstractJavaFormatterTest extends LightIdeaTestCase {
|
||||
return CodeStyleSettingsManager.getSettings(getProject());
|
||||
}
|
||||
|
||||
public static CodeStyleSettings.IndentOptions getIndentOptions() {
|
||||
return getSettings().getIndentOptions(StdFileTypes.JAVA);
|
||||
}
|
||||
|
||||
public void doTest() throws Exception {
|
||||
doTest(getTestName(false) + ".java", getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
+98
-29
@@ -173,34 +173,103 @@ public class JavaFormatterIndentationTest extends AbstractJavaFormatterTest {
|
||||
public void testCaseFromSwitch() throws IncorrectOperationException {
|
||||
// Inspired by IDEADEV-22920
|
||||
getSettings().INDENT_CASE_FROM_SWITCH = false;
|
||||
doTextTest("class Foo{\n" +
|
||||
"void foo () {\n" +
|
||||
"switch(someValue) {\n" +
|
||||
" // This comment is correctly not-indented\n" +
|
||||
" case 1:\n" +
|
||||
" doSomething();\n" +
|
||||
" break;\n" +
|
||||
"\n" +
|
||||
" // This comment should not be indented, but it is\n" +
|
||||
" case 2:\n" +
|
||||
" doSomethingElse();\n" +
|
||||
" break;\n" +
|
||||
"}\n" +
|
||||
"}\n" +
|
||||
"}", "class Foo {\n" +
|
||||
" void foo() {\n" +
|
||||
" switch (someValue) {\n" +
|
||||
" // This comment is correctly not-indented\n" +
|
||||
" case 1:\n" +
|
||||
" doSomething();\n" +
|
||||
" break;\n" +
|
||||
"\n" +
|
||||
" // This comment should not be indented, but it is\n" +
|
||||
" case 2:\n" +
|
||||
" doSomethingElse();\n" +
|
||||
" break;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
doTextTest(
|
||||
"class Foo{\n" +
|
||||
"void foo () {\n" +
|
||||
"switch(someValue) {\n" +
|
||||
" // This comment is correctly not-indented\n" +
|
||||
" case 1:\n" +
|
||||
" doSomething();\n" +
|
||||
" break;\n" +
|
||||
"\n" +
|
||||
" // This comment should not be indented, but it is\n" +
|
||||
" case 2:\n" +
|
||||
" doSomethingElse();\n" +
|
||||
" break;\n" +
|
||||
"}\n" +
|
||||
"}\n" +
|
||||
"}",
|
||||
|
||||
"class Foo {\n" +
|
||||
" void foo() {\n" +
|
||||
" switch (someValue) {\n" +
|
||||
" // This comment is correctly not-indented\n" +
|
||||
" case 1:\n" +
|
||||
" doSomething();\n" +
|
||||
" break;\n" +
|
||||
"\n" +
|
||||
" // This comment should not be indented, but it is\n" +
|
||||
" case 2:\n" +
|
||||
" doSomethingElse();\n" +
|
||||
" break;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testBinaryExpressionsWithRelativeIndents() {
|
||||
// Inspired by IDEA-21795
|
||||
getIndentOptions().USE_RELATIVE_INDENTS = true;
|
||||
getIndentOptions().CONTINUATION_INDENT_SIZE = 4;
|
||||
|
||||
doTextTest(
|
||||
"public class FormattingTest {\n" +
|
||||
"\n" +
|
||||
" public boolean test1(int a, int b, int c, int d) {\n" +
|
||||
" return a == 1 &&\n" +
|
||||
" b == 2;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public boolean multilineSignOnCurrent(int a, int b, int c, int d) {\n" +
|
||||
" return a == 0 &&\n" +
|
||||
" (b == 0 ||\n" +
|
||||
" c == 0) &&\n" +
|
||||
" d == 0;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public boolean multilineSignOnNext(int a, int b, int c, int d) {\n" +
|
||||
" return a == 0\n" +
|
||||
" && (b == 0\n" +
|
||||
" || c == 0)\n" +
|
||||
" && d == 0;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public boolean expectedMultilineSignOnNext(int a, int b, int c, int d) {\n" +
|
||||
" return a == 0\n" +
|
||||
" && (b == 0\n" +
|
||||
" || c == 0)\n" +
|
||||
" && d == 0;\n" +
|
||||
" }\n" +
|
||||
"}",
|
||||
|
||||
"public class FormattingTest {\n" +
|
||||
"\n" +
|
||||
" public boolean test1(int a, int b, int c, int d) {\n" +
|
||||
" return a == 1 &&\n" +
|
||||
" b == 2;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public boolean multilineSignOnCurrent(int a, int b, int c, int d) {\n" +
|
||||
" return a == 0 &&\n" +
|
||||
" (b == 0 ||\n" +
|
||||
" c == 0) &&\n" +
|
||||
" d == 0;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public boolean multilineSignOnNext(int a, int b, int c, int d) {\n" +
|
||||
" return a == 0\n" +
|
||||
" && (b == 0\n" +
|
||||
" || c == 0)\n" +
|
||||
" && d == 0;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public boolean expectedMultilineSignOnNext(int a, int b, int c, int d) {\n" +
|
||||
" return a == 0\n" +
|
||||
" && (b == 0\n" +
|
||||
" || c == 0)\n" +
|
||||
" && d == 0;\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+38
-3
@@ -22,7 +22,9 @@ import com.intellij.util.IncorrectOperationException;
|
||||
* @author Denis Zhdanov
|
||||
* @since May 11, 2010 5:30:28 PM
|
||||
*/
|
||||
public class AutoIndentLinesTest extends AbstractJavaFormatterTest {
|
||||
public class JavaIndenterTest extends AbstractJavaFormatterTest {
|
||||
|
||||
private static final String CARET_TOKEN = "<caret>";
|
||||
|
||||
public void testIndentAlignedMethodParameter() {
|
||||
// Inspired by IDEA-22020
|
||||
@@ -41,7 +43,7 @@ public class AutoIndentLinesTest extends AbstractJavaFormatterTest {
|
||||
int end = initial.indexOf("\n", start);
|
||||
myTextRange = new TextRange(start, end);
|
||||
|
||||
doTextTest(Action.INDENT, initial,
|
||||
doTextTest(initial,
|
||||
"class BrokenAlignment {\n" +
|
||||
" public\n" +
|
||||
"\tstatic int foo(String a, String b, String c,\n" +
|
||||
@@ -52,8 +54,41 @@ public class AutoIndentLinesTest extends AbstractJavaFormatterTest {
|
||||
);
|
||||
}
|
||||
|
||||
public void testMethodBodyShiftedToComment() {
|
||||
// Inspired by IDEA-53778
|
||||
|
||||
doTextTest(
|
||||
"class Test {\n" +
|
||||
" // some comment\n" +
|
||||
" public void doSmth(int[] p) {\n" +
|
||||
"<caret>\n" +
|
||||
" }" +
|
||||
"}",
|
||||
|
||||
"class Test {\n" +
|
||||
" // some comment\n" +
|
||||
" public void doSmth(int[] p) {\n" +
|
||||
" \n" +
|
||||
" }" +
|
||||
"}");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doTextTest(String text, String textAfter) throws IncorrectOperationException {
|
||||
doTextTest(Action.INDENT, text, textAfter);
|
||||
doTextTest(Action.INDENT, adjustTextIfNecessary(text), textAfter);
|
||||
}
|
||||
|
||||
private String adjustTextIfNecessary(String text) {
|
||||
int caretIndex = text.indexOf(CARET_TOKEN);
|
||||
if (caretIndex < 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
if (caretIndex < text.length() && text.indexOf(CARET_TOKEN, caretIndex + 1) >= 0) {
|
||||
fail(String.format("Invalid indentation test 'before' text - it contains more than one caret meta-token (%s). Text: %n%s",
|
||||
CARET_TOKEN, text));
|
||||
}
|
||||
myTextRange = new TextRange(caretIndex, caretIndex);
|
||||
return text.substring(0, caretIndex) + text.substring(caretIndex + CARET_TOKEN.length());
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,6 @@ import java.util.Set;
|
||||
*/
|
||||
public abstract class JspManager implements IBaseJspManager {
|
||||
|
||||
public static final Key<VirtualFile[]> DIRECTORIES_KEY = Key.create("TagDirOriginalDirs");
|
||||
|
||||
public static JspManager getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, JspManager.class);
|
||||
}
|
||||
|
||||
@@ -16,13 +16,25 @@
|
||||
package com.intellij.psi.javadoc;
|
||||
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiDocCommentOwner;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PsiDocComment extends PsiComment {
|
||||
@Nullable
|
||||
PsiDocCommentOwner getOwner();
|
||||
|
||||
@NotNull
|
||||
PsiElement[] getDescriptionElements();
|
||||
|
||||
@NotNull
|
||||
PsiDocTag[] getTags();
|
||||
|
||||
@Nullable
|
||||
PsiDocTag findTagByName(@NonNls String name);
|
||||
|
||||
@NotNull
|
||||
PsiDocTag[] findTagsByName(@NonNls String name);
|
||||
}
|
||||
@@ -199,6 +199,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
|
||||
public boolean SMART_TABS = false;
|
||||
public int LABEL_INDENT_SIZE = 0;
|
||||
public boolean LABEL_INDENT_ABSOLUTE = false;
|
||||
public boolean USE_RELATIVE_INDENTS = false;
|
||||
|
||||
public void readExternal(Element element) throws InvalidDataException {
|
||||
DefaultJDOMExternalizer.readExternal(this, element);
|
||||
@@ -228,6 +229,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
|
||||
if (CONTINUATION_INDENT_SIZE != that.CONTINUATION_INDENT_SIZE) return false;
|
||||
if (INDENT_SIZE != that.INDENT_SIZE) return false;
|
||||
if (LABEL_INDENT_ABSOLUTE != that.LABEL_INDENT_ABSOLUTE) return false;
|
||||
if (USE_RELATIVE_INDENTS != that.USE_RELATIVE_INDENTS) return false;
|
||||
if (LABEL_INDENT_SIZE != that.LABEL_INDENT_SIZE) return false;
|
||||
if (SMART_TABS != that.SMART_TABS) return false;
|
||||
if (TAB_SIZE != that.TAB_SIZE) return false;
|
||||
@@ -245,6 +247,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
|
||||
result = 31 * result + (SMART_TABS ? 1 : 0);
|
||||
result = 31 * result + LABEL_INDENT_SIZE;
|
||||
result = 31 * result + (LABEL_INDENT_ABSOLUTE ? 1 : 0);
|
||||
result = 31 * result + (USE_RELATIVE_INDENTS ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+20
-158
@@ -15,27 +15,14 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle;
|
||||
|
||||
import com.intellij.application.options.CodeStyleAbstractPanel;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.*;
|
||||
@@ -46,7 +33,6 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -54,8 +40,8 @@ import java.util.Arrays;
|
||||
public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleAbstractPanel {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.CodeStyleSpacesPanel");
|
||||
private final JTree myOptionsTree;
|
||||
private final HashMap myKeyToFieldMap = new HashMap();
|
||||
private final ArrayList myKeys = new ArrayList();
|
||||
private final HashMap<BooleanOptionKey, Field> myKeyToFieldMap = new HashMap<BooleanOptionKey, Field>();
|
||||
private final ArrayList<BooleanOptionKey> myKeys = new ArrayList<BooleanOptionKey>();
|
||||
private final JPanel myPanel = new JPanel(new GridBagLayout());
|
||||
|
||||
public OptionTreeWithPreviewPanel(CodeStyleSettings settings) {
|
||||
@@ -84,32 +70,14 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
|
||||
String groupName = "";
|
||||
DefaultMutableTreeNode groupNode = null;
|
||||
for (int i = 0; i < myKeys.size(); i++) {
|
||||
if (myKeys.get(i) instanceof BooleanOptionKey) {
|
||||
BooleanOptionKey key = (BooleanOptionKey)myKeys.get(i);
|
||||
String newGroupName = key.groupName;
|
||||
if (!newGroupName.equals(groupName) || groupNode == null) {
|
||||
groupName = newGroupName;
|
||||
groupNode = new DefaultMutableTreeNode(newGroupName);
|
||||
rootNode.add(groupNode);
|
||||
}
|
||||
groupNode.add(new MyToggleTreeNode(key, key.cbName));
|
||||
}
|
||||
else if (myKeys.get(i) instanceof IntSelectionOptionKey) {
|
||||
IntSelectionOptionKey key = (IntSelectionOptionKey)myKeys.get(i);
|
||||
String newGroupName = key.groupName;
|
||||
if (!newGroupName.equals(groupName) || groupNode == null) {
|
||||
groupName = newGroupName;
|
||||
groupNode = new DefaultMutableTreeNode(newGroupName);
|
||||
rootNode.add(groupNode);
|
||||
}
|
||||
MyToggleTreeNode[] nodes = new MyToggleTreeNode[key.rbNames.length];
|
||||
for (int j = 0; j < nodes.length; j++) {
|
||||
nodes[j] = new MyToggleTreeNode(key, key.rbNames[j]);
|
||||
groupNode.add(nodes[j]);
|
||||
}
|
||||
key.setCreatedNodes(nodes);
|
||||
for (BooleanOptionKey key: myKeys) {
|
||||
String newGroupName = key.groupName;
|
||||
if (!newGroupName.equals(groupName) || groupNode == null) {
|
||||
groupName = newGroupName;
|
||||
groupNode = new DefaultMutableTreeNode(newGroupName);
|
||||
rootNode.add(groupNode);
|
||||
}
|
||||
groupNode.add(new MyToggleTreeNode(key, key.cbName));
|
||||
}
|
||||
|
||||
DefaultTreeModel model = new DefaultTreeModel(rootNode);
|
||||
@@ -156,19 +124,7 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
Object o = treePath.getLastPathComponent();
|
||||
if (o instanceof MyToggleTreeNode) {
|
||||
MyToggleTreeNode node = (MyToggleTreeNode)o;
|
||||
if (node.isCheckbox()) {
|
||||
node.setSelected(!node.isSelected());
|
||||
}
|
||||
else {
|
||||
MyToggleTreeNode[] group = node.getGroup();
|
||||
for (int i = 0; i < group.length; i++) {
|
||||
MyToggleTreeNode groupNode = group[i];
|
||||
groupNode.setSelected(false);
|
||||
int row = myOptionsTree.getRowForPath(new TreePath(groupNode.getPath()));
|
||||
myOptionsTree.repaint(myOptionsTree.getRowBounds(row));
|
||||
}
|
||||
node.setSelected(true);
|
||||
}
|
||||
node.setSelected(!node.isSelected());
|
||||
int row = myOptionsTree.getRowForPath(treePath);
|
||||
myOptionsTree.repaint(myOptionsTree.getRowBounds(row));
|
||||
//updatePreview();
|
||||
@@ -201,21 +157,9 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
|
||||
private void resetMyTreeNode(MyToggleTreeNode childNode, final CodeStyleSettings settings) {
|
||||
try {
|
||||
if (childNode.getKey() instanceof BooleanOptionKey) {
|
||||
BooleanOptionKey key = (BooleanOptionKey)childNode.getKey();
|
||||
Field field = (Field)myKeyToFieldMap.get(key);
|
||||
childNode.setSelected(field.getBoolean(settings));
|
||||
}
|
||||
else if (childNode.getKey() instanceof IntSelectionOptionKey) {
|
||||
IntSelectionOptionKey key = (IntSelectionOptionKey)childNode.getKey();
|
||||
Field field = (Field)myKeyToFieldMap.get(key);
|
||||
int fieldValue = field.getInt(settings);
|
||||
for (int i = 0; i < key.rbNames.length; i++) {
|
||||
if (childNode.getText().equals(key.rbNames[i])) {
|
||||
childNode.setSelected(fieldValue == key.values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
BooleanOptionKey key = (BooleanOptionKey)childNode.getKey();
|
||||
Field field = myKeyToFieldMap.get(key);
|
||||
childNode.setSelected(field.getBoolean(settings));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.error(e);
|
||||
@@ -244,22 +188,9 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
|
||||
private void applyToggleNode(MyToggleTreeNode childNode, final CodeStyleSettings settings) {
|
||||
try {
|
||||
if (childNode.getKey() instanceof BooleanOptionKey) {
|
||||
BooleanOptionKey key = (BooleanOptionKey)childNode.getKey();
|
||||
Field field = (Field)myKeyToFieldMap.get(key);
|
||||
field.set(settings, childNode.isSelected() ? Boolean.TRUE : Boolean.FALSE);
|
||||
}
|
||||
else if (childNode.getKey() instanceof IntSelectionOptionKey) {
|
||||
if (!childNode.isSelected()) return;
|
||||
IntSelectionOptionKey key = (IntSelectionOptionKey)childNode.getKey();
|
||||
Field field = (Field)myKeyToFieldMap.get(key);
|
||||
for (int i = 0; i < key.rbNames.length; i++) {
|
||||
if (childNode.getText().equals(key.rbNames[i])) {
|
||||
field.set(settings, new Integer(key.values[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
BooleanOptionKey key = (BooleanOptionKey)childNode.getKey();
|
||||
Field field = myKeyToFieldMap.get(key);
|
||||
field.set(settings, childNode.isSelected() ? Boolean.TRUE : Boolean.FALSE);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.error(e);
|
||||
@@ -296,21 +227,9 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
|
||||
private boolean isToggleNodeModified(MyToggleTreeNode childNode, final CodeStyleSettings settings) {
|
||||
try {
|
||||
if (childNode.getKey() instanceof BooleanOptionKey) {
|
||||
BooleanOptionKey key = (BooleanOptionKey)childNode.getKey();
|
||||
Field field = (Field)myKeyToFieldMap.get(key);
|
||||
return childNode.isSelected() != field.getBoolean(settings);
|
||||
}
|
||||
else if (childNode.getKey() instanceof IntSelectionOptionKey) {
|
||||
if (!childNode.isSelected()) return false;
|
||||
IntSelectionOptionKey key = (IntSelectionOptionKey)childNode.getKey();
|
||||
Field field = (Field)myKeyToFieldMap.get(key);
|
||||
for (int i = 0; i < key.rbNames.length; i++) {
|
||||
if (childNode.getText().equals(key.rbNames[i])) {
|
||||
return field.getInt(settings) != key.values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
BooleanOptionKey key = (BooleanOptionKey)childNode.getKey();
|
||||
Field field = myKeyToFieldMap.get(key);
|
||||
return childNode.isSelected() != field.getBoolean(settings);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.error(e);
|
||||
@@ -335,20 +254,6 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
}
|
||||
}
|
||||
|
||||
protected void initRadioGroupField(String fieldName, String groupName, String[] rbNames, int[] values) {
|
||||
try {
|
||||
Class styleSettingsClass = CodeStyleSettings.class;
|
||||
Field field = styleSettingsClass.getField(fieldName);
|
||||
IntSelectionOptionKey key = new IntSelectionOptionKey(groupName, rbNames, values);
|
||||
myKeyToFieldMap.put(key, field);
|
||||
myKeys.add(key);
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void prepareForReformat(final PsiFile psiFile) {
|
||||
//psiFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, LanguageLevel.HIGHEST);
|
||||
}
|
||||
@@ -356,12 +261,10 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
protected class MyTreeCellRenderer implements TreeCellRenderer {
|
||||
private final MyLabelPanel myLabel;
|
||||
private final JCheckBox myCheckBox;
|
||||
private final JRadioButton myRadioButton;
|
||||
|
||||
public MyTreeCellRenderer() {
|
||||
myLabel = new MyLabelPanel();
|
||||
myCheckBox = new JCheckBox();
|
||||
myRadioButton = new JRadioButton();
|
||||
myCheckBox.setMargin(new Insets(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
@@ -370,7 +273,7 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
|
||||
if (value instanceof MyToggleTreeNode) {
|
||||
MyToggleTreeNode treeNode = (MyToggleTreeNode)value;
|
||||
JToggleButton button = treeNode.isCheckbox() ? (JToggleButton)myCheckBox : (JToggleButton)myRadioButton;
|
||||
JToggleButton button = myCheckBox;
|
||||
button.setText(treeNode.getText());
|
||||
button.setSelected(treeNode.isSelected);
|
||||
if (isSelected) {
|
||||
@@ -473,64 +376,23 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA
|
||||
}
|
||||
}
|
||||
|
||||
private static class IntSelectionOptionKey {
|
||||
final String groupName;
|
||||
final String[] rbNames;
|
||||
final int[] values;
|
||||
private MyToggleTreeNode[] myNodes;
|
||||
|
||||
public IntSelectionOptionKey(String groupName, String[] rbNames, int[] values) {
|
||||
this.groupName = groupName;
|
||||
this.rbNames = rbNames;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof IntSelectionOptionKey)) return false;
|
||||
|
||||
final IntSelectionOptionKey intSelectionOptionKey = (IntSelectionOptionKey)o;
|
||||
|
||||
if (!groupName.equals(intSelectionOptionKey.groupName)) return false;
|
||||
if (!Arrays.equals(rbNames, intSelectionOptionKey.rbNames)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return groupName.hashCode() + rbNames[0].hashCode() * 29;
|
||||
}
|
||||
|
||||
public void setCreatedNodes(MyToggleTreeNode[] nodes) { myNodes = nodes; }
|
||||
|
||||
public MyToggleTreeNode[] getNodes() { return myNodes; }
|
||||
}
|
||||
|
||||
private static class MyToggleTreeNode extends DefaultMutableTreeNode {
|
||||
private final Object myKey;
|
||||
private final String myText;
|
||||
private boolean isSelected;
|
||||
private final boolean isCheckbox;
|
||||
|
||||
public MyToggleTreeNode(Object key, String text) {
|
||||
myKey = key;
|
||||
myText = text;
|
||||
isCheckbox = true;
|
||||
}
|
||||
|
||||
public Object getKey() { return myKey; }
|
||||
|
||||
public String getText() { return myText; }
|
||||
|
||||
public boolean isCheckbox() { return isCheckbox; }
|
||||
|
||||
public void setSelected(boolean val) { isSelected = val; }
|
||||
|
||||
public boolean isSelected() { return isSelected; }
|
||||
|
||||
public MyToggleTreeNode[] getGroup() {
|
||||
return ((IntSelectionOptionKey)myKey).getNodes();
|
||||
}
|
||||
}
|
||||
|
||||
public JComponent getInternalPanel() {
|
||||
|
||||
@@ -222,6 +222,35 @@ public class CustomTemplateCallback {
|
||||
myBuilder.insertText(offset, text);
|
||||
}
|
||||
|
||||
public void insertNewLine() {
|
||||
myBuilder.insertText(myOffset, "\n");
|
||||
myOffset++;
|
||||
}
|
||||
|
||||
public boolean newLineBefore() {
|
||||
int i = myOffset - 1;
|
||||
CharSequence text = myBuilder.getText();
|
||||
while (i >= 0 && Character.isWhitespace(text.charAt(i))) {
|
||||
if (text.charAt(i) == '\n') {
|
||||
return true;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return i < 0;
|
||||
}
|
||||
|
||||
public boolean newLineAfter() {
|
||||
int i = myOffset;
|
||||
CharSequence text = myBuilder.getText();
|
||||
while (i < text.length() && Character.isWhitespace(text.charAt(i))) {
|
||||
if (text.charAt(i) == '\n') {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i == text.length();
|
||||
}
|
||||
|
||||
public void deleteTemplateKey(String key) {
|
||||
int caretAt = myEditor.getCaretModel().getOffset();
|
||||
myEditor.getDocument().deleteString(caretAt - key.length(), caretAt);
|
||||
|
||||
@@ -21,11 +21,24 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* @author lesya
|
||||
*/
|
||||
public abstract class AbstractBlockWrapper {
|
||||
|
||||
private static final Set<IndentImpl.Type> RELATIVE_INDENT_TYPES = new HashSet<IndentImpl.Type>(asList(
|
||||
IndentImpl.Type.NORMAL, IndentImpl.Type.CONTINUATION, IndentImpl.Type.CONTINUATION_WITHOUT_FIRST
|
||||
));
|
||||
|
||||
private static final Set<IndentImpl.Type> CONTINUATION_INDENT_TYPES = new HashSet<IndentImpl.Type>(asList(
|
||||
IndentImpl.Type.CONTINUATION, IndentImpl.Type.CONTINUATION_WITHOUT_FIRST
|
||||
));
|
||||
|
||||
protected WhiteSpace myWhiteSpace;
|
||||
protected CompositeBlockWrapper myParent;
|
||||
protected int myStart;
|
||||
@@ -154,36 +167,38 @@ public abstract class AbstractBlockWrapper {
|
||||
|
||||
}
|
||||
|
||||
public IndentData getChildOffset(AbstractBlockWrapper child, CodeStyleSettings.IndentOptions options, final int tokenBlockStartOffset) {
|
||||
final boolean childOnNewLine = child.getWhiteSpace().containsLineFeeds();
|
||||
public IndentData getChildOffset(AbstractBlockWrapper child, CodeStyleSettings.IndentOptions options, int targetBlockStartOffset) {
|
||||
final boolean childStartsNewLine = child.getWhiteSpace().containsLineFeeds();
|
||||
IndentImpl.Type childIndentType = child.getIndent().getType();
|
||||
final IndentData childIndent;
|
||||
|
||||
// Calculate child indent.
|
||||
if (childOnNewLine) {
|
||||
childIndent = getIndent(options, child, tokenBlockStartOffset);
|
||||
if (childStartsNewLine
|
||||
|| (!getWhiteSpace().containsLineFeeds() && RELATIVE_INDENT_TYPES.contains(childIndentType) && indentAlreadyUsedBefore(child)))
|
||||
{
|
||||
childIndent = getIndent(options, child, targetBlockStartOffset);
|
||||
}
|
||||
else {
|
||||
IndentImpl.Type type = child.getIndent().getType();
|
||||
if (!getWhiteSpace().containsLineFeeds()
|
||||
&& (type == IndentImpl.Type.NORMAL || type == IndentImpl.Type.CONTINUATION || type == IndentImpl.Type.CONTINUATION_WITHOUT_FIRST)
|
||||
&& indentAlreadyUsedBefore(child))
|
||||
{
|
||||
childIndent = getIndent(options, child, tokenBlockStartOffset);
|
||||
}
|
||||
else {
|
||||
childIndent = new IndentData(0);
|
||||
}
|
||||
childIndent = new IndentData(0);
|
||||
}
|
||||
|
||||
|
||||
// Use child indent if it's absolute and the child is contained on new line.
|
||||
if (childOnNewLine && child.getIndent().isAbsolute()) {
|
||||
myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
|
||||
AbstractBlockWrapper current = this;
|
||||
while (current != null && current.getStartOffset() == getStartOffset()) {
|
||||
current.myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
|
||||
current = current.myParent;
|
||||
if (childStartsNewLine) {
|
||||
if (child.getIndent().isAbsolute()) {
|
||||
myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
|
||||
AbstractBlockWrapper current = this;
|
||||
while (current != null && current.getStartOffset() == getStartOffset()) {
|
||||
current.myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
|
||||
current = current.myParent;
|
||||
}
|
||||
return childIndent;
|
||||
}
|
||||
else if (options.USE_RELATIVE_INDENTS && child.getStartOffset() > getStartOffset()
|
||||
&& (CONTINUATION_INDENT_TYPES.contains(childIndentType)))
|
||||
{
|
||||
return childIndent.add(getNumberOfSymbolsBeforeBlock());
|
||||
}
|
||||
return childIndent;
|
||||
}
|
||||
|
||||
if (child.getStartOffset() == getStartOffset()) {
|
||||
@@ -192,25 +207,25 @@ public abstract class AbstractBlockWrapper {
|
||||
setCanUseFirstChildIndentAsBlockIndent(newValue);
|
||||
}
|
||||
|
||||
if (getStartOffset() == tokenBlockStartOffset) {
|
||||
if (getStartOffset() == targetBlockStartOffset) {
|
||||
if (myParent == null) {
|
||||
return childIndent;
|
||||
}
|
||||
else {
|
||||
return childIndent.add(myParent.getChildOffset(this, options, tokenBlockStartOffset));
|
||||
return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset));
|
||||
}
|
||||
} else if (!getWhiteSpace().containsLineFeeds()) {
|
||||
if (isIndentAffectedAlignment(child)) {
|
||||
return createAlignmentIndent(childIndent, child);
|
||||
}
|
||||
else {
|
||||
return childIndent.add(myParent.getChildOffset(this, options, tokenBlockStartOffset));
|
||||
return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset));
|
||||
}
|
||||
} else {
|
||||
if (myParent == null) return childIndent.add(getWhiteSpace());
|
||||
if (getIndent().isAbsolute()) {
|
||||
if (myParent.myParent != null) {
|
||||
return childIndent.add(myParent.myParent.getChildOffset(myParent, options, tokenBlockStartOffset));
|
||||
return childIndent.add(myParent.myParent.getChildOffset(myParent, options, targetBlockStartOffset));
|
||||
}
|
||||
else {
|
||||
return childIndent.add(getWhiteSpace());
|
||||
@@ -225,7 +240,7 @@ public abstract class AbstractBlockWrapper {
|
||||
}
|
||||
}
|
||||
else {
|
||||
return childIndent.add(myParent.getChildOffset(this, options, tokenBlockStartOffset));
|
||||
return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,7 +267,7 @@ public abstract class AbstractBlockWrapper {
|
||||
* @return previous block for the current block if any; <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
protected abstract AbstractBlockWrapper getPreviousBlock();
|
||||
protected abstract LeafBlockWrapper getPreviousBlock();
|
||||
|
||||
protected final void setCanUseFirstChildIndentAsBlockIndent(final boolean newValue) {
|
||||
if (newValue) myFlags |= CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
|
||||
@@ -287,10 +302,12 @@ public abstract class AbstractBlockWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer if indent for the given child block should be calculated
|
||||
* Allows to answer if indent for the given child block should be calculated taking into consideration alignment
|
||||
* of the text at current block start.
|
||||
*
|
||||
* @param child
|
||||
* @return
|
||||
* @param child child block to check
|
||||
* @return <code>true</code> if indent should be calculated taking into consideration alignment of the text at current
|
||||
* block start; <code>false</code> otherwise
|
||||
*/
|
||||
private boolean isIndentAffectedAlignment(AbstractBlockWrapper child) {
|
||||
if (!child.getWhiteSpace().containsLineFeeds()) {
|
||||
|
||||
@@ -75,7 +75,7 @@ public class CompositeBlockWrapper extends AbstractBlockWrapper{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractBlockWrapper getPreviousBlock() {
|
||||
protected LeafBlockWrapper getPreviousBlock() {
|
||||
if (myChildren == null || myChildren.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -151,8 +151,6 @@ class LeafBlockWrapper extends AbstractBlockWrapper {
|
||||
return new IndentData(indentSpaces, spaces);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
myPreviousBlock = null;
|
||||
@@ -230,9 +228,4 @@ class LeafBlockWrapper extends AbstractBlockWrapper {
|
||||
public TextRange getTextRange() {
|
||||
return new TextRange(myStart, myEnd);
|
||||
}
|
||||
|
||||
private void calculateNumberOfSymbolsAtLastLine() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -340,6 +340,7 @@ editbox.indent.continuation.indent=Continuation indent
|
||||
editbox.indent.label.indent=Label indent
|
||||
checkbox.indent.absolute.label.indent=Absolute label indent
|
||||
checkbox.do.not.indent.top.level.class.members=Do not indent top level class members
|
||||
checkbox.use.relative.indents=Use indents relative to expression start
|
||||
tooltip.indent.must.be.multiple.of.tab.size.for.smart.tabs.to.operate=Indent must be multiple of tab size for smart tabs to operate
|
||||
combobox.crlf.system.dependent=System Dependent
|
||||
combobox.crlf.unix=Unix \n
|
||||
|
||||
+12
-11
@@ -60,19 +60,20 @@ public class SMTestRunnerConnectionUtil {
|
||||
* consistency of test events communication protocol and throw assertion errors. To enable debug mode
|
||||
* please set system property idea.smrunner.debug=true
|
||||
*
|
||||
* @param processHandler Process handler
|
||||
* @param consoleProperties Console properties for test console actions
|
||||
* @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings
|
||||
* and also will be mentioned in debug diagnostics
|
||||
* @param processHandler Process handler
|
||||
* @param consoleProperties Console properties for test console actions
|
||||
* @return Console view
|
||||
* @throws ExecutionException If IDEA cannot execute process this Exception will
|
||||
* be caught and shown in error message box
|
||||
*/
|
||||
public static BaseTestsOutputConsoleView attachRunner(@NotNull final ProcessHandler processHandler,
|
||||
public static BaseTestsOutputConsoleView attachRunner(@NotNull final String testFrameworkName,
|
||||
@NotNull final ProcessHandler processHandler,
|
||||
@NotNull final TestConsoleProperties consoleProperties,
|
||||
final RunnerSettings runnerSettings,
|
||||
final ConfigurationPerRunnerSettings configurationSettings,
|
||||
@NotNull final String testFrameworkName) throws ExecutionException {
|
||||
final ConfigurationPerRunnerSettings configurationSettings
|
||||
) throws ExecutionException {
|
||||
|
||||
// Console
|
||||
final String splitterPropertyName = testFrameworkName + ".Splitter.Proportion";
|
||||
@@ -126,24 +127,24 @@ public class SMTestRunnerConnectionUtil {
|
||||
* consistency of test events communication protocol and throw assertion errors. To enable debug mode
|
||||
* please set system property idea.smrunner.debug=true
|
||||
*
|
||||
* @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings
|
||||
* @param processHandler Process handler
|
||||
* @param commandLineState Command line state
|
||||
* @param config User run configuration settings
|
||||
* @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings
|
||||
* @return Console view
|
||||
* @throws ExecutionException If IDEA cannot execute process this Exception will
|
||||
* be caught and shown in error message box
|
||||
*/
|
||||
public static ConsoleView attachRunner(@NotNull final ProcessHandler processHandler,
|
||||
public static ConsoleView attachRunner(@NotNull final String testFrameworkName, @NotNull final ProcessHandler processHandler,
|
||||
@NotNull final CommandLineState commandLineState,
|
||||
@NotNull final RuntimeConfiguration config,
|
||||
@NotNull final String testFrameworkName) throws ExecutionException {
|
||||
@NotNull final RuntimeConfiguration config
|
||||
) throws ExecutionException {
|
||||
// final String testFrameworkName
|
||||
final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(config, testFrameworkName);
|
||||
|
||||
return attachRunner(processHandler, consoleProperties,
|
||||
return attachRunner(testFrameworkName, processHandler, consoleProperties,
|
||||
commandLineState.getRunnerSettings(),
|
||||
commandLineState.getConfigurationSettings(), testFrameworkName);
|
||||
commandLineState.getConfigurationSettings());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -642,7 +642,7 @@ public class ContainerUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T, V> List<V> mapNotNull(T[] array, Function<T, V> mapping) {
|
||||
public static <T, V> List<V> mapNotNull(@NotNull T[] array, Function<T, V> mapping) {
|
||||
return mapNotNull(Arrays.asList(array), mapping);
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -98,6 +98,7 @@ public class GrDocCommentImpl extends LazyParseablePsiElement implements GroovyD
|
||||
return list.toArray(new GrDocTag[list.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getDescriptionElements() {
|
||||
ArrayList<PsiElement> array = new ArrayList<PsiElement>();
|
||||
for (PsiElement child = getFirstChild(); child != null; child = child.getNextSibling()) {
|
||||
|
||||
@@ -46,6 +46,7 @@ class HgIncomingStatusUpdater implements HgUpdater {
|
||||
public void run() {
|
||||
new Task.Backgroundable(project, "Checking Incoming Changesets", true) {
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
if (project.isDisposed()) return;
|
||||
HgIncomingCommand command = new HgIncomingCommand(project);
|
||||
VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots();
|
||||
List<HgFileRevision> changesets = new LinkedList<HgFileRevision>();
|
||||
@@ -57,7 +58,7 @@ class HgIncomingStatusUpdater implements HgUpdater {
|
||||
}
|
||||
}.queue();
|
||||
}
|
||||
});
|
||||
}, project.getDisposed());
|
||||
}
|
||||
|
||||
private final class IncomingChangesetFormatter implements HgChangesetStatus.ChangesetWriter {
|
||||
|
||||
@@ -46,6 +46,7 @@ class HgOutgoingStatusUpdater implements HgUpdater {
|
||||
public void run() {
|
||||
new Task.Backgroundable(project, "Checking Outgoing Changesets", true) {
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
if (project.isDisposed()) return;
|
||||
HgOutgoingCommand command = new HgOutgoingCommand(project);
|
||||
VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots();
|
||||
List<HgFileRevision> outgoing = new LinkedList<HgFileRevision>();
|
||||
@@ -57,7 +58,7 @@ class HgOutgoingStatusUpdater implements HgUpdater {
|
||||
}
|
||||
}.queue();
|
||||
}
|
||||
});
|
||||
}, project.getDisposed());
|
||||
}
|
||||
|
||||
private final class OutgoingChangesetFormatter implements HgChangesetStatus.ChangesetWriter {
|
||||
|
||||
@@ -189,16 +189,21 @@ public class HgVcs extends AbstractVcs {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start() throws VcsException {
|
||||
protected void activate() {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
HgExecutableValidator validator = new HgExecutableValidator(myProject);
|
||||
started = validator.check(globalSettings);
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
started = true;
|
||||
}
|
||||
else {
|
||||
HgExecutableValidator validator = new HgExecutableValidator(myProject);
|
||||
started = validator.check(globalSettings);
|
||||
}
|
||||
if (isStarted()) {
|
||||
addListeners();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, myProject.getDisposed());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+30
-18
@@ -29,6 +29,7 @@ import com.intellij.psi.xml.XmlTokenType;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.containers.IntArrayList;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
@@ -310,27 +311,38 @@ class XmlZenCodingInterpreter {
|
||||
if (token instanceof XmlTemplateToken && token.getTemplate() != null) {
|
||||
XmlTemplateToken xmlTemplateToken = (XmlTemplateToken)token;
|
||||
List<Pair<String, String>> attr2value = new ArrayList<Pair<String, String>>(xmlTemplateToken.getAttribute2Value());
|
||||
if (attr2value.size() > 0 || XmlZenCodingTemplate.isTrueXml(callback)) {
|
||||
TemplateImpl modifiedTemplate = token.getTemplate().copy();
|
||||
XmlTag tag = xmlTemplateToken.getTag();
|
||||
if (tag != null) {
|
||||
for (Iterator<Pair<String, String>> iterator = attr2value.iterator(); iterator.hasNext();) {
|
||||
Pair<String, String> pair = iterator.next();
|
||||
if (tag.getAttribute(pair.first) != null) {
|
||||
tag.setAttribute(pair.first, ZenCodingUtil.getValue(pair, numberInIteration));
|
||||
iterator.remove();
|
||||
}
|
||||
TemplateImpl modifiedTemplate = token.getTemplate().copy();
|
||||
XmlTag tag = xmlTemplateToken.getTag();
|
||||
if (tag != null) {
|
||||
for (Iterator<Pair<String, String>> iterator = attr2value.iterator(); iterator.hasNext();) {
|
||||
Pair<String, String> pair = iterator.next();
|
||||
if (tag.getAttribute(pair.first) != null) {
|
||||
tag.setAttribute(pair.first, ZenCodingUtil.getValue(pair, numberInIteration));
|
||||
iterator.remove();
|
||||
}
|
||||
String s = filterXml(tag, callback, filter);
|
||||
assert s != null;
|
||||
modifiedTemplate.setString(s);
|
||||
removeVariablesWhichHasNoSegment(modifiedTemplate);
|
||||
Map<String, String> predefinedValues = buildPredefinedValues(attr2value, numberInIteration, callback);
|
||||
callback.expandTemplate(modifiedTemplate, predefinedValues);
|
||||
return;
|
||||
}
|
||||
String s = filterXml(tag, callback, filter);
|
||||
assert s != null;
|
||||
if (HtmlUtil.isHtmlBlockTagL(tag.getName())) {
|
||||
boolean newLineBefore = callback.newLineBefore();
|
||||
boolean newLineAfter = callback.newLineAfter();
|
||||
if (!newLineBefore || !newLineAfter) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (!newLineBefore) {
|
||||
builder.append('\n');
|
||||
}
|
||||
builder.append(s);
|
||||
if (!newLineAfter) {
|
||||
builder.append('\n');
|
||||
}
|
||||
s = builder.toString();
|
||||
}
|
||||
}
|
||||
modifiedTemplate.setString(s);
|
||||
removeVariablesWhichHasNoSegment(modifiedTemplate);
|
||||
Map<String, String> predefinedValues = buildPredefinedValues(attr2value, numberInIteration, callback);
|
||||
callback.expandTemplate(modifiedTemplate, predefinedValues);
|
||||
}
|
||||
callback.expandTemplate(token.getTemplate(), null);
|
||||
}
|
||||
else {
|
||||
// for CSS
|
||||
|
||||
Reference in New Issue
Block a user