mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
Merge branch 'master' into changeSignature
Conflicts: plugins/groovy/testdata/highlighting/MethodDuplicates.groovy
This commit is contained in:
+1
-1
@@ -51,7 +51,7 @@ public class JavaCompletionStatistician extends CompletionStatistician{
|
||||
}
|
||||
}
|
||||
|
||||
LookupItem item = element.as(LookupItem.class);
|
||||
LookupItem item = LookupItem.from(element);
|
||||
if (item == null) return null;
|
||||
|
||||
PsiType qualifierType = JavaCompletionUtil.getQualifierType(item);
|
||||
|
||||
@@ -789,9 +789,8 @@ public class JavaCompletionUtil {
|
||||
return typed.getType();
|
||||
}
|
||||
|
||||
|
||||
final PsiType qualifierType = getPsiType(element.getObject());
|
||||
final LookupItem lookupItem = element.as(LookupItem.class);
|
||||
final LookupItem lookupItem = LookupItem.from(element);
|
||||
if (lookupItem != null) {
|
||||
final Object o = lookupItem.getAttribute(LookupItem.TYPE);
|
||||
if (o instanceof PsiType) {
|
||||
|
||||
@@ -31,6 +31,10 @@ public class StaticMembersWeigher extends CompletionWeigher {
|
||||
final PsiElement position = loc.getCompletionParameters().getPosition();
|
||||
if (!position.isValid()) return 0;
|
||||
|
||||
// cheap weigher applicability goes first
|
||||
final Object o = element.getObject();
|
||||
if (!(o instanceof PsiMember)) return 0;
|
||||
|
||||
if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) return 0;
|
||||
if (position.getParent() instanceof PsiReferenceExpression) {
|
||||
final PsiReferenceExpression refExpr = (PsiReferenceExpression)position.getParent();
|
||||
@@ -43,9 +47,6 @@ public class StaticMembersWeigher extends CompletionWeigher {
|
||||
}
|
||||
}
|
||||
|
||||
final Object o = element.getObject();
|
||||
if (!(o instanceof PsiMember)) return 0;
|
||||
|
||||
if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC)) {
|
||||
if (o instanceof PsiMethod) return 5;
|
||||
if (o instanceof PsiField) return 4;
|
||||
|
||||
-9
@@ -16,14 +16,11 @@
|
||||
package com.intellij.openapi.options.colors.pages;
|
||||
|
||||
import com.intellij.application.options.colors.InspectionColorSettingsPage;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.daemon.impl.SeveritiesProvider;
|
||||
import com.intellij.ide.highlighter.JavaFileHighlighter;
|
||||
import com.intellij.openapi.editor.HighlighterColors;
|
||||
import com.intellij.openapi.editor.SyntaxHighlighterColors;
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.options.OptionsBundle;
|
||||
@@ -136,12 +133,6 @@ public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColor
|
||||
descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.full.coverage"), CodeInsightColors.LINE_FULL_COVERAGE));
|
||||
descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.partial.coverage"), CodeInsightColors.LINE_PARTIAL_COVERAGE));
|
||||
descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.none.coverage"), CodeInsightColors.LINE_NONE_COVERAGE));
|
||||
for (SeveritiesProvider provider : Extensions.getExtensions(SeveritiesProvider.EP_NAME)) {
|
||||
for (HighlightInfoType highlightInfoType : provider.getSeveritiesHighlightInfoTypes()) {
|
||||
final TextAttributesKey attributesKey = highlightInfoType.getAttributesKey();
|
||||
descriptors.add(new AttributesDescriptor(attributesKey.myExternalName, attributesKey));
|
||||
}
|
||||
}
|
||||
return descriptors.toArray(new AttributesDescriptor[descriptors.size()]);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.FormatterUtil;
|
||||
import com.intellij.psi.formatter.common.AbstractBlock;
|
||||
import com.intellij.psi.formatter.common.JavaBlockUtil;
|
||||
import com.intellij.psi.formatter.java.wrap.JavaWrapManager;
|
||||
import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.impl.source.tree.java.ClassElement;
|
||||
@@ -37,7 +39,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlock {
|
||||
public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlock, ReservedWrapsProvider {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.java.AbstractJavaBlock");
|
||||
|
||||
protected final CodeStyleSettings mySettings;
|
||||
@@ -51,16 +53,21 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
protected Alignment myReservedAlignment;
|
||||
protected Alignment myReservedAlignment2;
|
||||
|
||||
|
||||
private final JavaWrapManager myWrapManager;
|
||||
|
||||
protected AbstractJavaBlock(final ASTNode node,
|
||||
final Wrap wrap,
|
||||
final Alignment alignment,
|
||||
final Indent indent,
|
||||
final CodeStyleSettings settings) {
|
||||
protected AbstractJavaBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent,
|
||||
final CodeStyleSettings settings)
|
||||
{
|
||||
this(node, wrap, alignment, indent, settings, JavaWrapManager.INSTANCE);
|
||||
}
|
||||
|
||||
protected AbstractJavaBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent,
|
||||
final CodeStyleSettings settings, JavaWrapManager wrapManager)
|
||||
{
|
||||
super(node, wrap, alignment);
|
||||
mySettings = settings;
|
||||
myIndent = indent;
|
||||
myWrapManager = wrapManager;
|
||||
}
|
||||
|
||||
public static Block createJavaBlock(final ASTNode child,
|
||||
@@ -159,7 +166,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
}
|
||||
|
||||
final ASTNode prevElement = getPrevElement(child);
|
||||
final ASTNode prevElement = FormattingAstUtil.getPrevElement(child);
|
||||
if (prevElement != null && prevElement.getElementType() == JavaElementType.MODIFIER_LIST) {
|
||||
return Indent.getNoneIndent();
|
||||
}
|
||||
@@ -234,51 +241,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
|
||||
@Nullable
|
||||
protected Wrap createChildWrap() {
|
||||
final IElementType nodeType = myNode.getElementType();
|
||||
if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.EXTENDS_LIST_WRAP), false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.BINARY_EXPRESSION) {
|
||||
Wrap actualWrap = myWrap != null ? myWrap : getReservedWrap(JavaElementType.BINARY_EXPRESSION);
|
||||
if (actualWrap == null) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.BINARY_OPERATION_WRAP), false);
|
||||
}
|
||||
else {
|
||||
if (!hasTheSamePriority(myNode.getTreeParent())) {
|
||||
return Wrap.createChildWrap(actualWrap, getWrapType(mySettings.BINARY_OPERATION_WRAP), false);
|
||||
}
|
||||
else {
|
||||
return actualWrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.TERNARY_OPERATION_WRAP), false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.ASSERT_STATEMENT) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.ASSERT_STATEMENT_WRAP), false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.FOR_STATEMENT) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.FOR_STATEMENT_WRAP), false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.THROWS_LIST) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.THROWS_LIST_WRAP), true);
|
||||
}
|
||||
else if (nodeType == JavaElementType.CODE_BLOCK) {
|
||||
return Wrap.createWrap(Wrap.NORMAL, false);
|
||||
}
|
||||
else if (isAssignment()) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.ASSIGNMENT_WRAP), true);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAssignment() {
|
||||
final IElementType nodeType = myNode.getElementType();
|
||||
return nodeType == JavaElementType.ASSIGNMENT_EXPRESSION || nodeType == JavaElementType.LOCAL_VARIABLE
|
||||
|| nodeType == JavaElementType.FIELD;
|
||||
return myWrapManager.createChildBlockWrap(this, getSettings(), this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -375,14 +338,14 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
if (myNode.getElementType() == JavaElementType.BINARY_EXPRESSION) {
|
||||
final ASTNode treeParent = myNode.getTreeParent();
|
||||
if (treeParent != null && treeParent.getElementType() == JavaElementType.BINARY_EXPRESSION) {
|
||||
return hasTheSamePriority(treeParent);
|
||||
return FormattingAstUtil.binaryExpressionHasTheSamePriority(myNode, treeParent);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ASTNode processChild(final ArrayList<Block> result,
|
||||
protected ASTNode processChild(final List<Block> result,
|
||||
ASTNode child,
|
||||
Alignment defaultAlignment,
|
||||
final Wrap defaultWrap,
|
||||
@@ -391,7 +354,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ASTNode processChild(final ArrayList<Block> result,
|
||||
protected ASTNode processChild(final List<Block> result,
|
||||
ASTNode child,
|
||||
Alignment defaultAlignment,
|
||||
final Wrap defaultWrap,
|
||||
@@ -411,7 +374,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
|
||||
if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ARRAY_INITIALIZER_EXPRESSION) {
|
||||
final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false);
|
||||
child = processParenBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE,
|
||||
child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE,
|
||||
result,
|
||||
child,
|
||||
WrappingStrategy.createDoNotWrapCommaStrategy(wrap),
|
||||
@@ -419,7 +382,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
else if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) {
|
||||
final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false);
|
||||
child = processParenBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE,
|
||||
child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE,
|
||||
result,
|
||||
child,
|
||||
WrappingStrategy.createDoNotWrapCommaStrategy(wrap),
|
||||
@@ -430,7 +393,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
if (mySettings.PREFER_PARAMETERS_WRAP) {
|
||||
wrap.ignoreParentWraps();
|
||||
}
|
||||
child = processParenBlock(result,
|
||||
child = processParenthesisBlock(result,
|
||||
child,
|
||||
WrappingStrategy.createDoNotWrapCommaStrategy(wrap),
|
||||
mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS);
|
||||
@@ -438,18 +401,18 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
|
||||
else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.PARAMETER_LIST) {
|
||||
final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), false);
|
||||
child = processParenBlock(result, child,
|
||||
child = processParenthesisBlock(result, child,
|
||||
WrappingStrategy.createDoNotWrapCommaStrategy(wrap),
|
||||
mySettings.ALIGN_MULTILINE_PARAMETERS);
|
||||
}
|
||||
else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.ANNOTATION_PARAMETER_LIST) {
|
||||
final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), false);
|
||||
child = processParenBlock(result, child,
|
||||
child = processParenthesisBlock(result, child,
|
||||
WrappingStrategy.createDoNotWrapCommaStrategy(wrap),
|
||||
mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS);
|
||||
}
|
||||
else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.PARENTH_EXPRESSION) {
|
||||
child = processParenBlock(result, child,
|
||||
child = processParenthesisBlock(result, child,
|
||||
WrappingStrategy.DO_NOT_WRAP,
|
||||
mySettings.ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION);
|
||||
}
|
||||
@@ -501,7 +464,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
return child;
|
||||
}
|
||||
|
||||
private ASTNode processField(final ArrayList<Block> result, ASTNode child, final Alignment defaultAlignment, final Wrap defaultWrap,
|
||||
private ASTNode processField(final List<Block> result, ASTNode child, final Alignment defaultAlignment, final Wrap defaultWrap,
|
||||
final Indent childIndent) {
|
||||
ASTNode lastFieldInGroup = findLastFieldInGroup(child);
|
||||
if (lastFieldInGroup == child) {
|
||||
@@ -563,7 +526,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ASTNode processTernaryOperationRange(final ArrayList<Block> result,
|
||||
private ASTNode processTernaryOperationRange(final List<Block> result,
|
||||
final ASTNode child, final Wrap defaultWrap, final Indent childIndent) {
|
||||
final ArrayList<Block> localResult = new ArrayList<Block>();
|
||||
final Wrap wrap = arrangeChildWrap(child, defaultWrap);
|
||||
@@ -825,186 +788,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
myAnnotationWrap = null;
|
||||
}
|
||||
}
|
||||
final ASTNode parent = child.getTreeParent();
|
||||
int role = ((CompositeElement)parent).getChildRole(child);
|
||||
final IElementType nodeType = myNode.getElementType();
|
||||
if (nodeType == JavaElementType.BINARY_EXPRESSION) {
|
||||
if (role == ChildRole.OPERATION_SIGN && !mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.ROPERAND && mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null;
|
||||
return defaultWrap;
|
||||
}
|
||||
final IElementType childType = child.getElementType();
|
||||
if (childType == JavaElementType.EXTENDS_LIST || childType == JavaElementType.IMPLEMENTS_LIST) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.EXTENDS_KEYWORD_WRAP), true);
|
||||
}
|
||||
else if (childType == JavaElementType.THROWS_LIST) {
|
||||
return Wrap.createWrap(getWrapType(mySettings.THROWS_KEYWORD_WRAP), true);
|
||||
}
|
||||
else if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) {
|
||||
if (role == ChildRole.REFERENCE_IN_LIST) {
|
||||
return defaultWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.THROWS_LIST) {
|
||||
if (role == ChildRole.REFERENCE_IN_LIST) {
|
||||
return defaultWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) {
|
||||
if (role == ChildRole.COLON && !mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.QUEST && !mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.THEN_EXPRESSION && mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.ELSE_EXPRESSION && mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
return defaultWrap;
|
||||
|
||||
}
|
||||
|
||||
else if (isAssignment()) {
|
||||
if (role == ChildRole.INITIALIZER_EQ && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap;
|
||||
if (role == ChildRole.INITIALIZER_EQ && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.OPERATION_SIGN && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap;
|
||||
if (role == ChildRole.OPERATION_SIGN && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.INITIALIZER && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap;
|
||||
if (role == ChildRole.INITIALIZER && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.ROPERAND && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap;
|
||||
if (role == ChildRole.ROPERAND && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.CLOSING_SEMICOLON) return null;
|
||||
//if (role == ChildRole.TYPE) return defaultWrap;
|
||||
return defaultWrap;
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (role == ChildRole.DOT) {
|
||||
return getReservedWrap(JavaElementType.REFERENCE_EXPRESSION);
|
||||
}
|
||||
else {
|
||||
return defaultWrap;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.FOR_STATEMENT) {
|
||||
if (role == ChildRole.FOR_INITIALIZATION || role == ChildRole.CONDITION || role == ChildRole.FOR_UPDATE) {
|
||||
return defaultWrap;
|
||||
}
|
||||
if (role == ChildRole.LOOP_BODY) {
|
||||
final boolean dontWrap = (childType == JavaElementType.CODE_BLOCK || childType == JavaElementType.BLOCK_STATEMENT) &&
|
||||
mySettings.BRACE_STYLE == CodeStyleSettings.END_OF_LINE;
|
||||
return Wrap.createWrap(dontWrap ? WrapType.NONE : WrapType.NORMAL, true);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.METHOD) {
|
||||
if (role == ChildRole.THROWS_LIST) {
|
||||
return defaultWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.MODIFIER_LIST) {
|
||||
if (childType == JavaElementType.ANNOTATION) {
|
||||
return getReservedWrap(JavaElementType.MODIFIER_LIST);
|
||||
}
|
||||
ASTNode prevElement = getPrevElement(child);
|
||||
if (prevElement != null && prevElement.getElementType() == JavaElementType.ANNOTATION) {
|
||||
return getReservedWrap(JavaElementType.MODIFIER_LIST);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.ASSERT_STATEMENT) {
|
||||
if (role == ChildRole.CONDITION) {
|
||||
return defaultWrap;
|
||||
}
|
||||
if (role == ChildRole.ASSERT_DESCRIPTION && !mySettings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) {
|
||||
return defaultWrap;
|
||||
}
|
||||
if (role == ChildRole.COLON && mySettings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) {
|
||||
return defaultWrap;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (nodeType == JavaElementType.CODE_BLOCK) {
|
||||
if (role == ChildRole.STATEMENT_IN_BLOCK) {
|
||||
return defaultWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.IF_STATEMENT) {
|
||||
if (childType == JavaElementType.IF_STATEMENT && role == ChildRole.ELSE_BRANCH && getSettings().SPECIAL_ELSE_IF_TREATMENT) {
|
||||
return Wrap.createWrap(WrapType.NONE, false);
|
||||
}
|
||||
if (role == ChildRole.THEN_BRANCH || role == ChildRole.ELSE_BRANCH) {
|
||||
if (childType == JavaElementType.BLOCK_STATEMENT) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.FOREACH_STATEMENT || nodeType == JavaElementType.WHILE_STATEMENT) {
|
||||
if (role == ChildRole.LOOP_BODY) {
|
||||
if (childType == JavaElementType.BLOCK_STATEMENT) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.DO_WHILE_STATEMENT) {
|
||||
if (role == ChildRole.LOOP_BODY) {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
} else if (role == ChildRole.WHILE_KEYWORD) {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
} else if (nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) {
|
||||
if (role == ChildRole.ANNOTATION_VALUE) {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
}
|
||||
|
||||
return defaultWrap;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ASTNode getPrevElement(final ASTNode child) {
|
||||
ASTNode result = child.getTreePrev();
|
||||
while (result != null && result.getElementType() == TokenType.WHITE_SPACE) {
|
||||
result = result.getTreePrev();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean hasTheSamePriority(final ASTNode node) {
|
||||
if (node == null) return false;
|
||||
if (node.getElementType() != JavaElementType.BINARY_EXPRESSION) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
final PsiBinaryExpression expr1 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(myNode);
|
||||
final PsiBinaryExpression expr2 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(node);
|
||||
final PsiJavaToken op1 = expr1.getOperationSign();
|
||||
final PsiJavaToken op2 = expr2.getOperationSign();
|
||||
return op1.getTokenType() == op2.getTokenType();
|
||||
}
|
||||
return myWrapManager.arrangeChildWrap(child, myNode, getSettings(), defaultWrap, this);
|
||||
}
|
||||
|
||||
private static WrapType getWrapType(final int wrap) {
|
||||
@@ -1020,23 +804,19 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
}
|
||||
|
||||
private ASTNode processParenBlock(List<Block> result,
|
||||
ASTNode child,
|
||||
WrappingStrategy wrappingStrategy,
|
||||
final boolean doAlign) {
|
||||
private ASTNode processParenthesisBlock(List<Block> result, ASTNode child,WrappingStrategy wrappingStrategy, final boolean doAlign) {
|
||||
|
||||
myUseChildAttributes = true;
|
||||
|
||||
final IElementType from = JavaTokenType.LPARENTH;
|
||||
final IElementType to = JavaTokenType.RPARENTH;
|
||||
|
||||
return processParenBlock(from, to, result, child, wrappingStrategy, doAlign);
|
||||
|
||||
return processParenthesisBlock(from, to, result, child, wrappingStrategy, doAlign);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ASTNode processParenBlock(final IElementType from,
|
||||
private ASTNode processParenthesisBlock(final IElementType from,
|
||||
final IElementType to, final List<Block> result, ASTNode child,
|
||||
final WrappingStrategy wrappingStrategy, final boolean doAlign
|
||||
) {
|
||||
@@ -1049,7 +829,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
boolean isAfterIncomplete = false;
|
||||
|
||||
ASTNode prev = child;
|
||||
int startOffset = child.getTextRange().getStartOffset();
|
||||
while (child != null) {
|
||||
isAfterIncomplete = isAfterIncomplete || child.getElementType() == TokenType.ERROR_ELEMENT ||
|
||||
child.getElementType() == JavaElementType.EMPTY_EXPRESSION;
|
||||
@@ -1066,10 +845,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
else {
|
||||
final IElementType elementType = child.getElementType();
|
||||
result.add(createJavaBlock(child, mySettings, internalIndent,
|
||||
wrappingStrategy.getWrap(elementType),
|
||||
alignmentStrategy.getAlignment(elementType),
|
||||
startOffset));
|
||||
processChild(result, child, alignmentStrategy.getAlignment(elementType), wrappingStrategy.getWrap(elementType), internalIndent);
|
||||
if (to == null) {//process only one statement
|
||||
return child;
|
||||
}
|
||||
@@ -1077,7 +853,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
isAfterIncomplete = false;
|
||||
}
|
||||
prev = child;
|
||||
startOffset += child.getTextLength();
|
||||
child = child.getTreeNext();
|
||||
}
|
||||
|
||||
@@ -1202,9 +977,31 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract Wrap getReservedWrap(final IElementType elementType);
|
||||
/**
|
||||
* <b>Note:</b> this method is considered to be a legacy heritage and is assumed to be removed as soon as formatting processing
|
||||
* is refactored
|
||||
*
|
||||
* @param elementType target element type
|
||||
* @return <code>null</code> all the time
|
||||
*/
|
||||
public Wrap getReservedWrap(IElementType elementType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract void setReservedWrap(final Wrap reservedWrap, final IElementType operationType);
|
||||
/**
|
||||
* Defines contract for associating operation type and particular wrap instance. I.e. given wrap object <b>may</b> be returned
|
||||
* from subsequent {@link #getReservedWrap(IElementType)} call if given operation type is used as an argument there.
|
||||
* <p/>
|
||||
* Default implementation ({@link AbstractJavaBlock#setReservedWrap(Wrap, IElementType)}) does nothing.
|
||||
* <p/>
|
||||
* <b>Note:</b> this method is considered to be a legacy heritage and is assumed to be removed as soon as formatting processing
|
||||
* is refactored
|
||||
*
|
||||
* @param reservedWrap reserved wrap instance
|
||||
* @param operationType target operation type to associate with the given wrap instance
|
||||
*/
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static ASTNode getTreeNode(final Block child2) {
|
||||
|
||||
@@ -71,7 +71,7 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{
|
||||
}
|
||||
}
|
||||
|
||||
private int calcNewState(final ASTNode child, final int state) {
|
||||
private static int calcNewState(final ASTNode child, final int state) {
|
||||
if (state == BEFORE_FIRST) {
|
||||
if (child.getElementType() == ElementType.ELSE_KEYWORD) {
|
||||
return AFTER_ELSE;
|
||||
@@ -152,13 +152,13 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{
|
||||
return Indent.getContinuationIndent();
|
||||
}
|
||||
|
||||
private boolean isSimpleStatement(final ASTNode child) {
|
||||
private static boolean isSimpleStatement(final ASTNode child) {
|
||||
if (child.getElementType() == ElementType.BLOCK_STATEMENT) return false;
|
||||
if (!ElementType.STATEMENT_BIT_SET.contains(child.getElementType())) return false;
|
||||
return isStatement(child, child.getTreeParent());
|
||||
}
|
||||
|
||||
private boolean isPartOfCodeBlock(final ASTNode child) {
|
||||
private static boolean isPartOfCodeBlock(final ASTNode child) {
|
||||
if (child == null) return false;
|
||||
if (child.getElementType() == ElementType.BLOCK_STATEMENT) return true;
|
||||
if (child.getElementType() == ElementType.CODE_BLOCK) return true;
|
||||
@@ -168,12 +168,7 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{
|
||||
return child.getElementType() == JavaDocElementType.DOC_COMMENT;
|
||||
}
|
||||
|
||||
protected Wrap getReservedWrap(final IElementType elementType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ChildAttributes getChildAttributes(final int newChildIndex) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.StdTokenSets;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -97,6 +98,7 @@ 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());
|
||||
@@ -125,6 +127,7 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ASTNode processCaseAndStatementAfter(final ArrayList<Block> result,
|
||||
ASTNode child,
|
||||
final Alignment childAlignment,
|
||||
@@ -159,7 +162,7 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isBreakOrReturn(final ASTNode child) {
|
||||
private static boolean isBreakOrReturn(final ASTNode child) {
|
||||
IElementType elementType = child.getElementType();
|
||||
return JavaElementType.BREAK_STATEMENT == elementType || JavaElementType.RETURN_STATEMENT == elementType;
|
||||
}
|
||||
@@ -193,7 +196,7 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
return result;
|
||||
}
|
||||
|
||||
private int calcNewState(final ASTNode child, int state) {
|
||||
private static int calcNewState(final ASTNode child, int state) {
|
||||
switch (state) {
|
||||
case BEFORE_FIRST: {
|
||||
if (StdTokenSets.COMMENT_BIT_SET.contains(child.getElementType())) {
|
||||
@@ -218,7 +221,7 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
return INSIDE_BODY;
|
||||
}
|
||||
|
||||
private boolean isLBrace(final ASTNode child) {
|
||||
private static boolean isLBrace(final ASTNode child) {
|
||||
return child.getElementType() == ElementType.LBRACE;
|
||||
}
|
||||
|
||||
@@ -250,7 +253,7 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRBrace(final ASTNode child) {
|
||||
private static boolean isRBrace(final ASTNode child) {
|
||||
return child.getElementType() == ElementType.RBRACE;
|
||||
}
|
||||
|
||||
@@ -269,11 +272,4 @@ public class CodeBlockBlock extends AbstractJavaBlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Wrap getReservedWrap(final IElementType elementType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.FormatterUtil;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -48,13 +47,6 @@ public class DocCommentBlock extends AbstractJavaBlock{
|
||||
|
||||
}
|
||||
|
||||
protected Wrap getReservedWrap(final IElementType elementType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ChildAttributes getChildAttributes(final int newChildIndex) {
|
||||
return new ChildAttributes(Indent.getSpaceIndent(1), null);
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.FormatterUtil;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -77,11 +76,4 @@ public class ExtendsListBlock extends AbstractJavaBlock{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Wrap getReservedWrap(final IElementType elementType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.formatter.java;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiBinaryExpression;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* Contains various utility methods for <code>AST</code> processing during code formatting.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since Apr 21, 2010 4:02:17 PM
|
||||
*/
|
||||
public class FormattingAstUtil {
|
||||
|
||||
/** Holds type of AST elements that are considered to be assignments. */
|
||||
private static final Set<IElementType> ASSIGNMENT_ELEMENT_TYPES = new HashSet<IElementType>(asList(
|
||||
JavaElementType.ASSIGNMENT_EXPRESSION, JavaElementType.LOCAL_VARIABLE, JavaElementType.FIELD
|
||||
));
|
||||
|
||||
private FormattingAstUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to get previous non-white space <code>AST</code> node for the given one.
|
||||
*
|
||||
* @param node base node which left non-white space sibling is to be found
|
||||
* @return left non-white space sibling of the given node if any; <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
public static ASTNode getPrevElement(final ASTNode node) {
|
||||
ASTNode result = node.getTreePrev();
|
||||
while (result != null && result.getElementType() == TokenType.WHITE_SPACE) {
|
||||
result = result.getTreePrev();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer if given node wraps assignement operation.
|
||||
*
|
||||
* @param node node to check
|
||||
* @return <code>true</code> if given node wraps assignement operation; <code>false</code> otherwise
|
||||
*/
|
||||
public static boolean isAssignment(ASTNode node) {
|
||||
return ASSIGNMENT_ELEMENT_TYPES.contains(node.getElementType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to check if given <code>AST</code> nodes refer to binary expressions and have the same priority.
|
||||
*
|
||||
* @param node1 node to check
|
||||
* @param node2 node to check
|
||||
* @return <code>true</code> if given nodes are binary expressions and have the same priority;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public static boolean binaryExpressionHasTheSamePriority(ASTNode node1, ASTNode node2) {
|
||||
if (node1 == null || node2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node1.getElementType() != JavaElementType.BINARY_EXPRESSION || node2.getElementType() != JavaElementType.BINARY_EXPRESSION) {
|
||||
return false;
|
||||
}
|
||||
PsiBinaryExpression expression1 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(node1);
|
||||
PsiBinaryExpression expression2 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(node2);
|
||||
return expression1.getOperationSign().getTokenType() == expression2.getOperationSign().getTokenType();
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.FormatterUtil;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -46,7 +45,7 @@ public class LabeledJavaBlock extends AbstractJavaBlock{
|
||||
result.add(createJavaBlock(child, mySettings, currentIndent, currentWrap, null));
|
||||
if (child.getElementType() == ElementType.COLON) {
|
||||
currentIndent = Indent.getNoneIndent();
|
||||
currentWrap =Wrap.createWrap(Wrap.ALWAYS, true);
|
||||
currentWrap =Wrap.createWrap(WrapType.ALWAYS, true);
|
||||
}
|
||||
}
|
||||
child = child.getTreeNext();
|
||||
@@ -62,13 +61,6 @@ public class LabeledJavaBlock extends AbstractJavaBlock{
|
||||
}
|
||||
}
|
||||
|
||||
protected Wrap getReservedWrap(final IElementType elementType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ChildAttributes getChildAttributes(final int newChildIndex) {
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.intellij.formatting.Alignment;
|
||||
import com.intellij.formatting.Indent;
|
||||
import com.intellij.formatting.Block;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -33,11 +32,4 @@ public class MethodCallExpressionBlock extends AbstractJavaBlock{
|
||||
protected List<Block> buildChildren() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Wrap getReservedWrap(final IElementType elementType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class SimpleJavaBlock extends AbstractJavaBlock {
|
||||
if (astNode != child && child != null) {
|
||||
offset = child.getTextRange().getStartOffset();
|
||||
}
|
||||
if (indent != null && !(myNode.getPsi() instanceof PsiFile) && child.getElementType() != ElementType.MODIFIER_LIST) {
|
||||
if (indent != null && !(myNode.getPsi() instanceof PsiFile) && child != null && child.getElementType() != ElementType.MODIFIER_LIST) {
|
||||
indent = Indent.getContinuationIndent();
|
||||
}
|
||||
//indent = FormatterEx.getInstance().getContinuationIndent();
|
||||
@@ -107,10 +107,12 @@ public class SimpleJavaBlock extends AbstractJavaBlock {
|
||||
}
|
||||
}
|
||||
|
||||
protected Wrap getReservedWrap(final IElementType elementType) {
|
||||
@Override
|
||||
public Wrap getReservedWrap(final IElementType elementType) {
|
||||
return myReservedWrap.get(elementType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
|
||||
myReservedWrap.put(operationType, reservedWrap);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.formatter.java.wrap;
|
||||
|
||||
import com.intellij.formatting.ASTBlock;
|
||||
import com.intellij.formatting.Block;
|
||||
import com.intellij.formatting.Wrap;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.java.wrap.impl.JavaChildBlockWrapFactory;
|
||||
import com.intellij.psi.formatter.java.wrap.impl.JavaChildWrapArranger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Defines common contract for {@link Wrap wraps} manipulation during java {@link Block blockes} processing
|
||||
* <p/>
|
||||
* This class is intended to serve as a facade for various fine-grained wrap processing classes.
|
||||
* <p/>
|
||||
* This class is not singleton but it's thread-safe and provides single-point-of-usage field {@link #INSTANCE}.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since Apr 21, 2010 2:19:17 PM
|
||||
*/
|
||||
public class JavaWrapManager {
|
||||
|
||||
/** Single-point-of-usage field. */
|
||||
public static final JavaWrapManager INSTANCE = new JavaWrapManager();
|
||||
|
||||
private final JavaChildWrapArranger myChildArranger;
|
||||
private final JavaChildBlockWrapFactory myChildBlockFactory;
|
||||
|
||||
/**
|
||||
* Creates new <code>JavaWrapManager</code> object with default wrapping services.
|
||||
*/
|
||||
public JavaWrapManager() {
|
||||
this(new JavaChildWrapArranger(), new JavaChildBlockWrapFactory());
|
||||
}
|
||||
|
||||
public JavaWrapManager(JavaChildWrapArranger childWrapArranger, JavaChildBlockWrapFactory childBlockWrapFactory) {
|
||||
myChildArranger = childWrapArranger;
|
||||
myChildBlockFactory = childBlockWrapFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to define the wrap to use for the {@link Block block} for the given <code>'child'</code> node. It's assumed that
|
||||
* given <code>'child'</code> node is descendant (direct or indirect) of the given <code>'parent'</code> node.
|
||||
* I.e. <code>'parent'</code> node defines usage context for the <code>'child'</code> node.
|
||||
*
|
||||
* @param child child node which {@link Wrap wrap} is to be defined
|
||||
* @param parent direct or indirect parent of the given <code>'child'</code> node. Defines usage context
|
||||
* of <code>'child'</code> node processing
|
||||
* @param settings code style settings to use during wrap definition
|
||||
* @param suggestedWrap wrap suggested to use by clients of current class. I.e. those clients offer wrap to
|
||||
* use based on their information about current processing state. However, it's possible
|
||||
* that they don't know details of fine-grained wrap definition algorithm encapsulated
|
||||
* at the current class. Hence, this method takes suggested wrap into consideration but
|
||||
* is not required to use it all the time node based on the given parameters
|
||||
* @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. <b>Note:</b> this
|
||||
* argument is considered to be a part of legacy heritage and is intended to be removed as
|
||||
* soon as formatting code refactoring is done
|
||||
* @return wrap to use for the given <code>'child'</code> node if it's possible to define the one;
|
||||
* <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
public Wrap arrangeChildWrap(ASTNode child, ASTNode parent, CodeStyleSettings settings, Wrap suggestedWrap,
|
||||
ReservedWrapsProvider reservedWrapsProvider)
|
||||
{
|
||||
return myChildArranger.arrange(child, parent, settings, suggestedWrap, reservedWrapsProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link Wrap wrap} to be used with the children blocks of the the given block.
|
||||
*
|
||||
* @param block target block which sub-blocks should use wrap created by the current method
|
||||
* @param settings code formatting settings to consider during wrap construction
|
||||
* @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. <b>Note:</b> this
|
||||
* argument is considered to be a part of legacy heritage and is intended to be removed as
|
||||
* soon as formatting code refactoring is done
|
||||
* @return wrap to use for the sub-blocks of the given block
|
||||
*/
|
||||
@Nullable
|
||||
public Wrap createChildBlockWrap(ASTBlock block, CodeStyleSettings settings, ReservedWrapsProvider reservedWrapsProvider) {
|
||||
return myChildBlockFactory.create(block, settings, reservedWrapsProvider);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.formatter.java.wrap;
|
||||
|
||||
import com.intellij.formatting.Wrap;
|
||||
import com.intellij.psi.formatter.java.AbstractJavaBlock;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Defines contract for using predefined reserved wraps.
|
||||
* <p/>
|
||||
* <b>Note:</b> this interface is introduced for encapsulating legacy {@link AbstractJavaBlock#getReservedWrap(IElementType)}
|
||||
* method and most probably will be removed as soon as formatting stuff is refactored.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since Apr 21, 2010 3:43:17 PM
|
||||
*/
|
||||
public interface ReservedWrapsProvider {
|
||||
|
||||
/**
|
||||
* Allows to retrieve predefined {@link Wrap} object for the given element type if any.
|
||||
*
|
||||
* @param elementType target element type
|
||||
* @return predefined wrap for the given element type if any; <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
Wrap getReservedWrap(IElementType elementType);
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.formatter.java.wrap.impl;
|
||||
|
||||
import com.intellij.formatting.ASTBlock;
|
||||
import com.intellij.formatting.Wrap;
|
||||
import com.intellij.formatting.WrapType;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.java.FormattingAstUtil;
|
||||
import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Encapsulates algorithm of construction {@link Wrap wraps} for sub-blocks of particular {@link ASTBlock block} taking into
|
||||
* consideration current formatting settings.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since Apr 21, 2010 4:49:49 PM
|
||||
*/
|
||||
public class JavaChildBlockWrapFactory {
|
||||
|
||||
/**
|
||||
* Creates {@link Wrap wrap} to be used with the children blocks of the the given block.
|
||||
*
|
||||
* @param block target block which sub-blocks should use wrap created by the current method
|
||||
* @param settings code formatting settings to consider during wrap construction
|
||||
* @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. <b>Note:</b> this
|
||||
* argument is considered to be a part of legacy heritage and is intended to be removed as
|
||||
* soon as formatting code refactoring is done
|
||||
* @return wrap to use for the sub-blocks of the given block
|
||||
*/
|
||||
@Nullable
|
||||
public Wrap create(ASTBlock block, CodeStyleSettings settings, ReservedWrapsProvider reservedWrapsProvider) {
|
||||
ASTNode node = block.getNode();
|
||||
Wrap wrap = block.getWrap();
|
||||
final IElementType nodeType = node.getElementType();
|
||||
if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) {
|
||||
return Wrap.createWrap(settings.EXTENDS_LIST_WRAP, false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.BINARY_EXPRESSION) {
|
||||
Wrap actualWrap = wrap != null ? wrap : reservedWrapsProvider.getReservedWrap(JavaElementType.BINARY_EXPRESSION);
|
||||
if (actualWrap == null) {
|
||||
return Wrap.createWrap(settings.BINARY_OPERATION_WRAP, false);
|
||||
}
|
||||
else {
|
||||
if (!FormattingAstUtil.binaryExpressionHasTheSamePriority(node, node.getTreeParent())) {
|
||||
return Wrap.createChildWrap(actualWrap, WrapType.byLegacyRepresentation(settings.BINARY_OPERATION_WRAP), false);
|
||||
}
|
||||
else {
|
||||
return actualWrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) {
|
||||
return Wrap.createWrap(settings.TERNARY_OPERATION_WRAP, false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.ASSERT_STATEMENT) {
|
||||
return Wrap.createWrap(settings.ASSERT_STATEMENT_WRAP, false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.FOR_STATEMENT) {
|
||||
return Wrap.createWrap(settings.FOR_STATEMENT_WRAP, false);
|
||||
}
|
||||
else if (nodeType == JavaElementType.THROWS_LIST) {
|
||||
return Wrap.createWrap(settings.THROWS_LIST_WRAP, true);
|
||||
}
|
||||
else if (nodeType == JavaElementType.CODE_BLOCK) {
|
||||
return Wrap.createWrap(Wrap.NORMAL, false);
|
||||
}
|
||||
else if (FormattingAstUtil.isAssignment(node)) {
|
||||
return Wrap.createWrap(settings.ASSIGNMENT_WRAP, true);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.formatter.java.wrap.impl;
|
||||
|
||||
import com.intellij.formatting.Wrap;
|
||||
import com.intellij.formatting.WrapType;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.java.FormattingAstUtil;
|
||||
import com.intellij.psi.formatter.java.wrap.JavaWrapManager;
|
||||
import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider;
|
||||
import com.intellij.psi.impl.source.tree.ChildRole;
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Encapsulates implementation of
|
||||
* {@link JavaWrapManager#arrangeChildWrap(ASTNode, ASTNode, CodeStyleSettings, Wrap, ReservedWrapsProvider)}.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since Apr 21, 2010 2:30:29 PM
|
||||
*/
|
||||
public class JavaChildWrapArranger {
|
||||
|
||||
/**
|
||||
* Provides implementation of {@link JavaWrapManager#arrangeChildWrap(ASTNode, ASTNode, CodeStyleSettings, Wrap, ReservedWrapsProvider)}
|
||||
* method.
|
||||
*
|
||||
* @param child child node which {@link Wrap wrap} is to be defined
|
||||
* @param parent direct or indirect parent of the given <code>'child'</code> node. Defines usage context
|
||||
* of <code>'child'</code> node processing
|
||||
* @param settings code style settings to use during wrap definition
|
||||
* @param suggestedWrap wrap suggested to use by clients of current class. I.e. those clients offer wrap to
|
||||
* use based on their information about current processing state. However, it's possible
|
||||
* that they don't know details of fine-grained wrap definition algorithm encapsulated
|
||||
* at the current class. Hence, this method takes suggested wrap into consideration but
|
||||
* is not required to use it all the time node based on the given parameters
|
||||
* @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. <b>Note:</b> this
|
||||
* argument is considered to be a part of legacy heritage and is intended to be removed as
|
||||
* soon as formatting code refactoring is done
|
||||
* @return wrap to use for the given <code>'child'</code> node if it's possible to define the one;
|
||||
* <code>null</code> otherwise
|
||||
*/
|
||||
@SuppressWarnings({"MethodMayBeStatic"})
|
||||
@Nullable
|
||||
public Wrap arrange(ASTNode child, ASTNode parent, CodeStyleSettings settings, Wrap suggestedWrap,
|
||||
ReservedWrapsProvider reservedWrapsProvider)
|
||||
{
|
||||
final ASTNode directParent = child.getTreeParent();
|
||||
int role = ((CompositeElement)directParent).getChildRole(child);
|
||||
final IElementType nodeType = parent.getElementType();
|
||||
if (nodeType == JavaElementType.BINARY_EXPRESSION) {
|
||||
if (role == ChildRole.OPERATION_SIGN && !settings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.ROPERAND && settings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null;
|
||||
return suggestedWrap;
|
||||
}
|
||||
final IElementType childType = child.getElementType();
|
||||
if (childType == JavaElementType.EXTENDS_LIST || childType == JavaElementType.IMPLEMENTS_LIST) {
|
||||
return Wrap.createWrap(settings.EXTENDS_KEYWORD_WRAP, true);
|
||||
}
|
||||
else if (childType == JavaElementType.THROWS_LIST) {
|
||||
return Wrap.createWrap(settings.THROWS_KEYWORD_WRAP, true);
|
||||
}
|
||||
else if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) {
|
||||
if (role == ChildRole.REFERENCE_IN_LIST) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.THROWS_LIST) {
|
||||
if (role == ChildRole.REFERENCE_IN_LIST) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) {
|
||||
if (role == ChildRole.COLON && !settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.QUEST && !settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.THEN_EXPRESSION && settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.ELSE_EXPRESSION && settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null;
|
||||
return suggestedWrap;
|
||||
|
||||
}
|
||||
|
||||
else if (FormattingAstUtil.isAssignment(parent)) {
|
||||
if (role == ChildRole.INITIALIZER_EQ && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap;
|
||||
if (role == ChildRole.INITIALIZER_EQ && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.OPERATION_SIGN && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap;
|
||||
if (role == ChildRole.OPERATION_SIGN && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.INITIALIZER && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap;
|
||||
if (role == ChildRole.INITIALIZER && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.ROPERAND && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap;
|
||||
if (role == ChildRole.ROPERAND && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null;
|
||||
if (role == ChildRole.CLOSING_SEMICOLON) return null;
|
||||
//if (role == ChildRole.TYPE) return suggestedWrap;
|
||||
return suggestedWrap;
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (role == ChildRole.DOT) {
|
||||
return reservedWrapsProvider.getReservedWrap(JavaElementType.REFERENCE_EXPRESSION);
|
||||
}
|
||||
else {
|
||||
return suggestedWrap;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.FOR_STATEMENT) {
|
||||
if (role == ChildRole.FOR_INITIALIZATION || role == ChildRole.CONDITION || role == ChildRole.FOR_UPDATE) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
if (role == ChildRole.LOOP_BODY) {
|
||||
final boolean dontWrap = (childType == JavaElementType.CODE_BLOCK || childType == JavaElementType.BLOCK_STATEMENT) &&
|
||||
settings.BRACE_STYLE == CodeStyleSettings.END_OF_LINE;
|
||||
return Wrap.createWrap(dontWrap ? WrapType.NONE : WrapType.NORMAL, true);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.METHOD) {
|
||||
if (role == ChildRole.THROWS_LIST) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.MODIFIER_LIST) {
|
||||
if (childType == JavaElementType.ANNOTATION) {
|
||||
return reservedWrapsProvider.getReservedWrap(JavaElementType.MODIFIER_LIST);
|
||||
}
|
||||
ASTNode prevElement = FormattingAstUtil.getPrevElement(child);
|
||||
if (prevElement != null && prevElement.getElementType() == JavaElementType.ANNOTATION) {
|
||||
return reservedWrapsProvider.getReservedWrap(JavaElementType.MODIFIER_LIST);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (nodeType == JavaElementType.ASSERT_STATEMENT) {
|
||||
if (role == ChildRole.CONDITION) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
if (role == ChildRole.ASSERT_DESCRIPTION && !settings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
if (role == ChildRole.COLON && settings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (nodeType == JavaElementType.CODE_BLOCK) {
|
||||
if (role == ChildRole.STATEMENT_IN_BLOCK) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.IF_STATEMENT) {
|
||||
if (childType == JavaElementType.IF_STATEMENT && role == ChildRole.ELSE_BRANCH && settings.SPECIAL_ELSE_IF_TREATMENT) {
|
||||
return Wrap.createWrap(WrapType.NONE, false);
|
||||
}
|
||||
if (role == ChildRole.THEN_BRANCH || role == ChildRole.ELSE_BRANCH) {
|
||||
if (childType == JavaElementType.BLOCK_STATEMENT) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.FOREACH_STATEMENT || nodeType == JavaElementType.WHILE_STATEMENT) {
|
||||
if (role == ChildRole.LOOP_BODY) {
|
||||
if (childType == JavaElementType.BLOCK_STATEMENT) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeType == JavaElementType.DO_WHILE_STATEMENT) {
|
||||
if (role == ChildRole.LOOP_BODY) {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
} else if (role == ChildRole.WHILE_KEYWORD) {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
} else if (nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) {
|
||||
if (suggestedWrap != null) {
|
||||
return suggestedWrap;
|
||||
}
|
||||
if (role == ChildRole.ANNOTATION_VALUE) {
|
||||
return Wrap.createWrap(WrapType.NORMAL, true);
|
||||
}
|
||||
}
|
||||
|
||||
return suggestedWrap;
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -30,6 +30,7 @@ import com.intellij.psi.scope.ElementClassFilter;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.scope.processor.FilterScopeProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.CharTable;
|
||||
@@ -112,7 +113,17 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo
|
||||
PsiParameter parameter = parameters[j];
|
||||
PsiType type1 = TypeConversionUtil.erasure(parameter.getType());
|
||||
String type2 = signature[j];
|
||||
if (!Comparing.strEqual(type1.getPresentableText(), type2) && !Comparing.strEqual(type1.getCanonicalText(), type2)) continue nextMethod;
|
||||
if (!Comparing.strEqual(type1.getPresentableText(), type2) && !Comparing.strEqual(type1.getCanonicalText(), type2)) {
|
||||
String shortName = "";
|
||||
PsiClass psiClass = PsiUtil.resolveClassInType(type1);
|
||||
while (psiClass != null) {
|
||||
shortName = psiClass.getName() + (shortName.length() > 0 ? "." + shortName : "");
|
||||
psiClass = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class);
|
||||
}
|
||||
if (!Comparing.strEqual(shortName, type2)) {
|
||||
continue nextMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new MyReference(method) {
|
||||
|
||||
@@ -91,6 +91,7 @@ public class CreateClassUtil {
|
||||
else {
|
||||
final FileTemplateManager fileTemplateManager = FileTemplateManager.getInstance();
|
||||
FileTemplate fileTemplate = fileTemplateManager.getJ2eeTemplate(templateName);
|
||||
LOG.assertTrue(fileTemplate != null, templateName + " not found");
|
||||
final String text = fileTemplate.getText(attributes);
|
||||
aClass = JavaCreateFromTemplateHandler.createClassOrInterface(project, directory, text, true, fileTemplate.getExtension());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class JavaInheritanceWeigher extends ProximityWeigher {
|
||||
|
||||
public Comparable weigh(@NotNull final PsiElement element, final ProximityLocation location) {
|
||||
if (element instanceof PsiClass && isTooGeneral((PsiClass)element)) return false;
|
||||
if (element instanceof PsiMethod && isTooGeneral(((PsiMethod)element).getContainingClass())) return false;
|
||||
|
||||
final PsiElement position = location.getPosition();
|
||||
PsiClass placeClass = PsiTreeUtil.getContextOfType(element, PsiClass.class, false);
|
||||
if (position.getParent() instanceof PsiReferenceExpression) {
|
||||
@@ -43,9 +46,8 @@ public class JavaInheritanceWeigher extends ProximityWeigher {
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof PsiClass && isTooGeneral((PsiClass)element)) return false;
|
||||
if (element instanceof PsiMethod && isTooGeneral(((PsiMethod)element).getContainingClass())) return false;
|
||||
|
||||
if (placeClass == null) return false;
|
||||
|
||||
PsiClass contextClass = PsiTreeUtil.getContextOfType(position, PsiClass.class, false);
|
||||
while (contextClass != null) {
|
||||
PsiClass elementClass = placeClass;
|
||||
|
||||
+14
@@ -84,5 +84,19 @@ public class MoveJavaFileHandler extends MoveFileHandler {
|
||||
@Override
|
||||
public void updateMovedFile(PsiFile file) throws IncorrectOperationException {
|
||||
ChangeContextUtil.decodeContextInfo(file, null, null);
|
||||
final PsiDirectory containingDirectory = file.getContainingDirectory();
|
||||
if (containingDirectory != null) {
|
||||
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(containingDirectory);
|
||||
if (aPackage != null) {
|
||||
final PsiPackageStatement packageStatement =
|
||||
JavaPsiFacade.getElementFactory(file.getProject()).createPackageStatement(aPackage.getQualifiedName());
|
||||
if (file instanceof PsiJavaFile) {
|
||||
final PsiPackageStatement filePackageStatement = ((PsiJavaFile)file).getPackageStatement();
|
||||
if (filePackageStatement != null) {
|
||||
filePackageStatement.getPackageReference().replace(packageStatement.getPackageReference());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -33,7 +33,8 @@ public class JavaMoveFilesOrDirectoriesHandler extends MoveFilesOrDirectoriesHan
|
||||
allJava &= JavaCopyFilesOrDirectoriesHandler.hasPackages((PsiDirectory)element);
|
||||
}
|
||||
else if (element instanceof PsiFile) {
|
||||
allJava &= element instanceof PsiJavaFile && !JspPsiUtil.isInJspFile(element) && !CollectHighlightsUtil.isOutsideSourceRootJavaFile((PsiJavaFile) element);
|
||||
allJava &= element instanceof PsiJavaFile && !JspPsiUtil.isInJspFile(element) &&
|
||||
((PsiJavaFile)element).getClasses().length > 0 && !CollectHighlightsUtil.isOutsideSourceRootJavaFile((PsiJavaFile) element);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
@@ -55,6 +56,6 @@ public class JavaMoveFilesOrDirectoriesHandler extends MoveFilesOrDirectoriesHan
|
||||
|
||||
@Override
|
||||
public void doMove(Project project, PsiElement[] elements, PsiElement targetContainer, MoveCallback callback) {
|
||||
super.doMove(project, elements, targetContainer, callback); //To change body of overridden methods use File | Settings | File Templates.
|
||||
super.doMove(project, elements, targetContainer, callback);
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class CSS {
|
||||
static class IO{}
|
||||
}
|
||||
|
||||
class TD {
|
||||
void calculateSmth(CSS.IO io){}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TD#calculateSmth(CSS.IO)
|
||||
*/
|
||||
class Test {
|
||||
}
|
||||
@@ -90,6 +90,8 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
|
||||
public void testVararg() throws Exception {doTest();}
|
||||
|
||||
public void testInnerClassReferenceInSignature() throws Exception {doTest();}
|
||||
|
||||
public void testBadReference() throws Exception{
|
||||
doTest();
|
||||
}
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.intellij.codeInsight.javadoc;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.CodeInsightTestCase;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
|
||||
public void testSimpleField() throws Exception {
|
||||
doTestField();
|
||||
}
|
||||
|
||||
public void testFieldValue() throws Exception {
|
||||
doTestField();
|
||||
}
|
||||
|
||||
public void testValueInMethod() throws Exception {
|
||||
doTestMethod();
|
||||
}
|
||||
|
||||
public void testIdeadev2326() throws Exception {
|
||||
doTestMethod();
|
||||
}
|
||||
|
||||
public void testMethodTypeParameter() throws Exception {
|
||||
doTestMethod();
|
||||
}
|
||||
|
||||
public void testClassTypeParameter() throws Exception {
|
||||
verifyJavaDoc(getTestClass());
|
||||
}
|
||||
|
||||
private void doTestField() throws Exception {
|
||||
PsiClass psiClass = getTestClass();
|
||||
PsiField field = psiClass.getFields() [0];
|
||||
verifyJavaDoc(field);
|
||||
}
|
||||
|
||||
private void doTestMethod() throws Exception {
|
||||
PsiClass psiClass = getTestClass();
|
||||
PsiMethod method = psiClass.getMethods() [0];
|
||||
verifyJavaDoc(method);
|
||||
}
|
||||
|
||||
private PsiClass getTestClass() throws Exception{
|
||||
configureByFile("/codeInsight/javadocIG/" + getTestName(true) + ".java");
|
||||
return ((PsiJavaFile)myFile).getClasses() [0];
|
||||
}
|
||||
|
||||
private void verifyJavaDoc(final PsiElement field) throws IOException {
|
||||
final File htmlPath = new File(JavaTestUtil.getJavaTestDataPath() + "/codeInsight/javadocIG/" + getTestName(true) + ".html");
|
||||
String htmlText = new String(FileUtil.loadFileText(htmlPath));
|
||||
String docInfo = new JavaDocInfoGenerator(getProject(), field).generateDocInfo(null);
|
||||
assertEquals(StringUtil.convertLineSeparators(htmlText.trim()), StringUtil.convertLineSeparators(docInfo.trim()));
|
||||
}
|
||||
|
||||
public void testPackageInfo() throws Exception {
|
||||
final String path = JavaTestUtil.getJavaTestDataPath() + "/codeInsight/javadocIG/";
|
||||
final String packageInfo = path + getTestName(true);
|
||||
PsiTestUtil.createTestProjectStructure(myProject, myModule, path, myFilesToDelete);
|
||||
final String info =
|
||||
new JavaDocInfoGenerator(getProject(), JavaPsiFacade.getInstance(getProject()).findPackage(getTestName(true))).generateDocInfo(null);
|
||||
String htmlText = new String(FileUtil.loadFileText(new File(packageInfo + File.separator + "packageInfo.html")));
|
||||
assertEquals(StringUtil.convertLineSeparators(htmlText.trim()), StringUtil.convertLineSeparators(info.trim()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ public class JavaFormatterTest extends LightIdeaTestCase {
|
||||
doTest("SCR915.java", "SCR915_after.java");
|
||||
}
|
||||
|
||||
|
||||
public void testForEach() throws Exception {
|
||||
doTest("ForEach.java", "ForEach_after.java");
|
||||
}
|
||||
@@ -207,6 +206,35 @@ public class JavaFormatterTest extends LightIdeaTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNestedMethodsIndentation() throws Exception {
|
||||
// Inspired by IDEA-43962
|
||||
|
||||
getSettings().getIndentOptions(StdFileTypes.JAVA).CONTINUATION_INDENT_SIZE = 4;
|
||||
|
||||
doMethodTest(
|
||||
"BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
".add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE)))))))));",
|
||||
"BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE\n" +
|
||||
" .add(BigDecimal.ONE)))))))));"
|
||||
);
|
||||
}
|
||||
|
||||
public void testSwitch() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
@@ -2892,22 +2920,26 @@ public class JavaFormatterTest extends LightIdeaTestCase {
|
||||
getSettings().ARRAY_INITIALIZER_WRAP = CodeStyleSettings.WRAP_ALWAYS;
|
||||
getSettings().ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE = true;
|
||||
getSettings().ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE = true;
|
||||
doTextTest("public @interface Ann\n" +
|
||||
doTextTest(
|
||||
"public @interface Ann\n" +
|
||||
"{\n" +
|
||||
"int[] x = { 1, 2 };\n" +
|
||||
"\n" +
|
||||
"Mode[] modes () default { @Mode(value = 1), @Mode(value = 2) };\n" +
|
||||
"}", "public @interface Ann {\n" +
|
||||
" int[] x = {\n" +
|
||||
" 1,\n" +
|
||||
" 2\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" Mode[] modes() default {\n" +
|
||||
" @Mode(value = 1),\n" +
|
||||
" @Mode(value = 2)\n" +
|
||||
" };\n" +
|
||||
"}");
|
||||
"}",
|
||||
|
||||
"public @interface Ann {\n" +
|
||||
" int[] x = {\n" +
|
||||
" 1,\n" +
|
||||
" 2\n" +
|
||||
" };\n" +
|
||||
"\n" +
|
||||
" Mode[] modes() default {\n" +
|
||||
" @Mode(value = 1),\n" +
|
||||
" @Mode(value = 2)\n" +
|
||||
" };\n" +
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
private void doMethodTest(final String before, final String after) throws Exception {
|
||||
|
||||
@@ -78,4 +78,8 @@ public abstract class LookupElement extends UserDataHolderBase {
|
||||
//noinspection unchecked
|
||||
return aClass.isInstance(this) ? (T) this : null;
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,10 @@ public abstract class LookupElementDecorator<T extends LookupElement> extends Lo
|
||||
final T t = super.as(aClass);
|
||||
return t == null ? myDelegate.as(aClass) : t;
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive() {
|
||||
return myDelegate.isCaseSensitive();
|
||||
}
|
||||
|
||||
private static class InsertingDecorator<T extends LookupElement> extends LookupElementDecorator<T> {
|
||||
private final InsertHandler<? super LookupElementDecorator<T>> myInsertHandler;
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.intellij.formatting;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
|
||||
/**
|
||||
* The wrap setting for a formatting model block. Indicates the conditions under which a line break
|
||||
* is inserted before the block when formatting, if the block extends beyond the
|
||||
@@ -34,15 +32,46 @@ public abstract class Wrap {
|
||||
|
||||
private static WrapFactory myFactory;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link WrapType#ALWAYS} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static WrapType ALWAYS = WrapType.ALWAYS;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link WrapType#NORMAL} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static WrapType NORMAL = WrapType.NORMAL;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link WrapType#NONE} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static WrapType NONE = WrapType.NONE;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link WrapType#CHOP_DOWN_IF_LONG} instead
|
||||
*/
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
@Deprecated
|
||||
public static WrapType CHOP_DOWN_IF_LONG = WrapType.CHOP_DOWN_IF_LONG;
|
||||
|
||||
static void setFactory(WrapFactory factory) {
|
||||
myFactory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block wrap setting of the legacy representation of specified wrap type (see {@link WrapType#getLegacyRepresentation()}).
|
||||
*
|
||||
* @param type the type of the wrap setting.
|
||||
* @param wrapFirstElement if <code>true</code>, the first element in a sequence of elements of the same type is also wrapped.
|
||||
* @return the wrap setting instance.
|
||||
*/
|
||||
public static Wrap createWrap(final int type, final boolean wrapFirstElement) {
|
||||
return myFactory.createWrap(WrapType.byLegacyRepresentation(type), wrapFirstElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block wrap setting of the specified type.
|
||||
*
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
*/
|
||||
package com.intellij.formatting;
|
||||
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines possible types of a wrap.
|
||||
*
|
||||
@@ -23,29 +28,69 @@ package com.intellij.formatting;
|
||||
*/
|
||||
|
||||
public enum WrapType {
|
||||
|
||||
/**
|
||||
* A line break is always inserted before the start of the element.
|
||||
* This corresponds to the "Wrap always" setting in Global Code Style | Wrapping.
|
||||
*/
|
||||
ALWAYS,
|
||||
ALWAYS(CodeStyleSettings.WRAP_ALWAYS),
|
||||
|
||||
/**
|
||||
* A line break is inserted before the start of the element if the right edge
|
||||
* of the element goes beyond the specified wrap margin.
|
||||
* This corresponds to the "Wrap if long" setting in Global Code Style | Wrapping.
|
||||
*/
|
||||
NORMAL,
|
||||
NORMAL(CodeStyleSettings.WRAP_AS_NEEDED),
|
||||
|
||||
/**
|
||||
* A line break is never inserted before the start of the element.
|
||||
* This corresponds to the "Do not wrap" setting in Global Code Style | Wrapping.
|
||||
*/
|
||||
NONE,
|
||||
NONE(CodeStyleSettings.DO_NOT_WRAP),
|
||||
|
||||
/**
|
||||
* A line break is inserted before the start of the element if it is a part
|
||||
* of list of elements of the same type and at least one of the elements was wrapped.
|
||||
* This corresponds to the "Chop down if long" setting in Global Code Style | Wrapping.
|
||||
*/
|
||||
CHOP_DOWN_IF_LONG
|
||||
CHOP_DOWN_IF_LONG(CodeStyleSettings.WRAP_ON_EVERY_ITEM);
|
||||
|
||||
private static final Map<Integer, WrapType> LEGACY_MAPPINGS = new HashMap<Integer, WrapType>();
|
||||
|
||||
static {
|
||||
for (WrapType wrapType : values()) {
|
||||
LEGACY_MAPPINGS.put(wrapType.getLegacyRepresentation(), wrapType);
|
||||
}
|
||||
}
|
||||
|
||||
private final int myLegacyRepresentation;
|
||||
|
||||
WrapType(int legacyRepresentation) {
|
||||
myLegacyRepresentation = legacyRepresentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to retrieve wrap type by it's legacy non-type-safe representation (see {@link #getLegacyRepresentation()}).
|
||||
*
|
||||
* @param value legacy representation of the target wrap type
|
||||
* @return wrap type which {@link #getLegacyRepresentation() legacyRepresentation} is equal to the given value if any;
|
||||
* {@link #CHOP_DOWN_IF_LONG} otherwise
|
||||
*/
|
||||
public static WrapType byLegacyRepresentation(int value) {
|
||||
WrapType result = LEGACY_MAPPINGS.get(value);
|
||||
return result == null ? CHOP_DOWN_IF_LONG : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapping types were used as a primitive constants during this enum introduction (e.g. {@link CodeStyleSettings#DO_NOT_WRAP} etc).
|
||||
* <p/>
|
||||
* It's possible to map that legacy representation to the object-level enum member via {@link #byLegacyRepresentation(int)}.
|
||||
* <p/>
|
||||
* Current getter exposes legacy value associated with the current object-level wrap type representation.
|
||||
*
|
||||
* @return legacy representation of the current wrap type
|
||||
*/
|
||||
public int getLegacyRepresentation() {
|
||||
return myLegacyRepresentation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.psi;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.KeyedExtensionCollector;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -37,7 +38,7 @@ public class WeighingService {
|
||||
@NotNull
|
||||
public static <T,Loc> WeighingComparable<T,Loc> weigh(Key<? extends Weigher<T,Loc>> key, T element, Loc location) {
|
||||
final List<Weigher> weighers = COLLECTOR.forKey(key);
|
||||
return new WeighingComparable<T,Loc>(element, location, weighers.toArray(new Weigher[weighers.size()]));
|
||||
return new WeighingComparable<T,Loc>(element, location, ContainerUtil.toArray(weighers, new Weigher[weighers.size()]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -42,7 +43,7 @@ import java.util.Set;
|
||||
* @author peter
|
||||
*/
|
||||
public class FileContentUtil {
|
||||
public static final String FORCE_RELOAD_REQUESTOR = "FileContentUtil.saveOrReload";
|
||||
@NonNls public static final String FORCE_RELOAD_REQUESTOR = "FileContentUtil.saveOrReload";
|
||||
|
||||
private FileContentUtil() {
|
||||
}
|
||||
@@ -67,23 +68,23 @@ public class FileContentUtil {
|
||||
}
|
||||
|
||||
public static void reparseFiles(@NotNull final Project project, @NotNull final Collection<VirtualFile> files, boolean includeOpenFiles) {
|
||||
final Set<VFilePropertyChangeEvent> list = new THashSet<VFilePropertyChangeEvent>();
|
||||
final Set<VFilePropertyChangeEvent> events = new THashSet<VFilePropertyChangeEvent>();
|
||||
for (VirtualFile file : files) {
|
||||
saveOrReload(file, list);
|
||||
saveOrReload(file, events);
|
||||
}
|
||||
if (includeOpenFiles) {
|
||||
for (VirtualFile open : FileEditorManager.getInstance(project).getOpenFiles()) {
|
||||
if (!files.contains(open)) {
|
||||
saveOrReload(open, list);
|
||||
saveOrReload(open, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES)
|
||||
.before(new ArrayList<VFileEvent>(list));
|
||||
.before(new ArrayList<VFileEvent>(events));
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES)
|
||||
.after(new ArrayList<VFileEvent>(list));
|
||||
.after(new ArrayList<VFileEvent>(events));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.intellij.application.options.colors;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.daemon.impl.SeveritiesProvider;
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
@@ -82,5 +84,12 @@ public class ColorSettingsUtil {
|
||||
descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.info"), CodeInsightColors.INFO_ATTRIBUTES));
|
||||
descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.server.problems"), CodeInsightColors.GENERIC_SERVER_ERROR_OR_WARNING));
|
||||
descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.server.duplicate"), CodeInsightColors.DUPLICATE_FROM_SERVER));
|
||||
|
||||
for (SeveritiesProvider provider : Extensions.getExtensions(SeveritiesProvider.EP_NAME)) {
|
||||
for (HighlightInfoType highlightInfoType : provider.getSeveritiesHighlightInfoTypes()) {
|
||||
final TextAttributesKey attributesKey = highlightInfoType.getAttributesKey();
|
||||
descriptors.add(new AttributesDescriptor(attributesKey.myExternalName, attributesKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-8
@@ -7,8 +7,6 @@ package com.intellij.codeInsight.completion.impl;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.PrefixMatcher;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.codeStyle.NameUtil;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
@@ -62,12 +60,7 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
|
||||
|
||||
public boolean prefixMatches(@NotNull final LookupElement element) {
|
||||
final LookupItem item = element.as(LookupItem.class); //must die, use LookupElementBuilder or CompletionResultSet.caseInsensitive
|
||||
final LookupElementBuilder builder = element.as(LookupElementBuilder.class);
|
||||
boolean itemCaseInsensitive = item != null && Boolean.TRUE.equals(item.getAttribute(LookupItem.CASE_INSENSITIVE)) ||
|
||||
builder != null && !builder.isCaseSensitive();
|
||||
|
||||
return prefixMatchersInternal(element, itemCaseInsensitive);
|
||||
return prefixMatchersInternal(element, !element.isCaseSensitive());
|
||||
}
|
||||
|
||||
private boolean prefixMatchersInternal(final LookupElement element, final boolean itemCaseInsensitive) {
|
||||
|
||||
+6
@@ -316,6 +316,12 @@ public class DocumentationManager {
|
||||
|
||||
component.setHint(hint);
|
||||
|
||||
if (myEditor == null) {
|
||||
// subsequent invocation of javadoc popup from completion will have myEditor == null because of cancel invoked,
|
||||
// so reevaluate the editor for proper popup placement
|
||||
Lookup lookup = LookupManager.getInstance(myProject).getActiveLookup();
|
||||
myEditor = lookup != null ? lookup.getEditor() : null;
|
||||
}
|
||||
fetchDocInfo(getDefaultCollector(element, originalElement), component);
|
||||
|
||||
myDocInfoHintRef = new WeakReference<JBPopup>(hint);
|
||||
|
||||
@@ -359,4 +359,16 @@ public class LookupItem<T> extends MutableLookupElement<T> implements Comparable
|
||||
myAttributes.putAll(item.myAttributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCaseSensitive() {
|
||||
return !Boolean.TRUE.equals(getAttribute(CASE_INSENSITIVE));
|
||||
}
|
||||
|
||||
public static @Nullable LookupItem from(LookupElement lookupElement) {
|
||||
if (lookupElement instanceof LookupElementDecorator) {
|
||||
lookupElement = ((LookupElementDecorator)lookupElement).getDelegate();
|
||||
}
|
||||
if (lookupElement instanceof LookupItem) return (LookupItem)lookupElement;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ public interface CustomLiveTemplate {
|
||||
@Nullable
|
||||
String computeTemplateKey(@NotNull CustomTemplateCallback callback);
|
||||
|
||||
boolean isApplicable(PsiFile file, int offset, boolean selection);
|
||||
boolean isApplicable(PsiFile file, int offset);
|
||||
|
||||
boolean supportsWrapping();
|
||||
|
||||
void expand(String key, @NotNull CustomTemplateCallback callback);
|
||||
|
||||
|
||||
+17
-2
@@ -18,12 +18,14 @@ package com.intellij.codeInsight.template;
|
||||
import com.intellij.codeInsight.template.impl.TemplateImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateSettings;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -61,8 +63,7 @@ public class CustomTemplateCallback {
|
||||
|
||||
@Nullable
|
||||
public PsiElement getContext() {
|
||||
int offset = myStartOffset;
|
||||
return myFile.findElementAt(offset > 0 ? offset - 1 : offset);
|
||||
return getContext(myFile, myStartOffset > 0 ? myStartOffset - 1 : myStartOffset);
|
||||
}
|
||||
|
||||
public void fixInitialState() {
|
||||
@@ -229,4 +230,18 @@ public class CustomTemplateCallback {
|
||||
int caretAt = myEditor.getCaretModel().getOffset();
|
||||
myEditor.getDocument().deleteString(caretAt - key.length(), caretAt);
|
||||
}
|
||||
|
||||
public static PsiElement getContext(PsiFile file, int offset) {
|
||||
PsiElement element = null;
|
||||
if (!InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) {
|
||||
element = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset);
|
||||
}
|
||||
if (element == null) {
|
||||
element = file.findElementAt(offset > 0 ? offset - 1 : offset);
|
||||
if (element == null) {
|
||||
element = file;
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class SurroundWithTemplateHandler implements CodeInsightActionHandler {
|
||||
List<CustomLiveTemplate> result = new ArrayList<CustomLiveTemplate>();
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
for (CustomLiveTemplate template : CustomLiveTemplate.EP_NAME.getExtensions()) {
|
||||
if (template.isApplicable(file, offset, true)) {
|
||||
if (template.supportsWrapping() && template.isApplicable(file, offset)) {
|
||||
result.add(template);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -244,7 +244,7 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
|
||||
for (final CustomLiveTemplate customLiveTemplate : CustomLiveTemplate.EP_NAME.getExtensions()) {
|
||||
if (shortcutChar == customLiveTemplate.getShortcut()) {
|
||||
int caretOffset = editor.getCaretModel().getOffset();
|
||||
if (customLiveTemplate.isApplicable(file, caretOffset, false)) {
|
||||
if (customLiveTemplate.isApplicable(file, caretOffset)) {
|
||||
final CustomTemplateCallback callback = new CustomTemplateCallback(editor, file);
|
||||
String key = customLiveTemplate.computeTemplateKey(callback);
|
||||
if (key != null) {
|
||||
|
||||
@@ -125,7 +125,7 @@ public abstract class AbstractBlockWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates indent for the given block and target start offset according to the given idnent options.
|
||||
* Calculates indent for the given block and target start offset according to the given indent options.
|
||||
*
|
||||
* @param options indent options to use
|
||||
* @param block target wrapped block
|
||||
@@ -255,18 +255,13 @@ public abstract class AbstractBlockWrapper {
|
||||
return indent.add(getWhiteSpace());
|
||||
}
|
||||
else {
|
||||
ArrayList<IndentData> ignored = new ArrayList<IndentData>();
|
||||
IndentData offsetFromParent = myParent.getChildOffset(this, indentOption, -1);
|
||||
IndentData result = indent.add(offsetFromParent);
|
||||
if (!ignored.isEmpty()) {
|
||||
result = result.add(ignored.get(ignored.size() - 1));
|
||||
}
|
||||
return result;
|
||||
return indent.add(offsetFromParent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private IndentData getIndent(final CodeStyleSettings.IndentOptions options, final int index, IndentImpl indent) {
|
||||
private static IndentData getIndent(final CodeStyleSettings.IndentOptions options, final int index, IndentImpl indent) {
|
||||
if (indent.getType() == IndentImpl.Type.CONTINUATION) {
|
||||
return new IndentData(options.CONTINUATION_INDENT_SIZE);
|
||||
}
|
||||
@@ -292,7 +287,7 @@ public abstract class AbstractBlockWrapper {
|
||||
* value is defined (not <code>null</code>).
|
||||
* <p/>
|
||||
* This property is used later during
|
||||
* {@link LeafBlockWrapper#calculateOffset(CodeStyleSettings.IndentOptions) leaf block offset calculation}.
|
||||
* {@link LeafBlockWrapper#calculateOffset(CodeStyleSettings.IndentOptions)} leaf block offset calculation}.
|
||||
*
|
||||
* @param indentFromParent indent value to apply
|
||||
*/
|
||||
@@ -340,4 +335,9 @@ public abstract class AbstractBlockWrapper {
|
||||
myParent = null;
|
||||
myWhiteSpace = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "(" + myStart + "-" + myEnd + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,9 +629,9 @@ class FormatProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to get align-implied indent of the line that contains current block.
|
||||
* Tries to get align-implied indent of the current block.
|
||||
*
|
||||
* @return indent of the line that contains current block if any; <code>null</code> otherwise
|
||||
* @return indent of the current block if any; <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
private IndentData getAlignOffset() {
|
||||
|
||||
@@ -279,8 +279,7 @@ public class FormatterImpl extends FormatterEx
|
||||
{
|
||||
boolean wsContainsCaret = whiteSpace.getStartOffset() <= offset && offset < whiteSpace.getEndOffset();
|
||||
|
||||
final CharSequence text = getCharSequence(documentModel);
|
||||
int lineStartOffset = getLineStartOffset(offset, whiteSpace, text, documentModel);
|
||||
int lineStartOffset = getLineStartOffset(offset, whiteSpace, documentModel);
|
||||
|
||||
final IndentInfo indent = calcIndent(offset, documentModel, processor, whiteSpace);
|
||||
|
||||
@@ -325,7 +324,7 @@ public class FormatterImpl extends FormatterEx
|
||||
final WhiteSpace whiteSpace = blockAfterOffset.getWhiteSpace();
|
||||
final IndentInfo indent = calcIndent(offset, documentModel, processor, whiteSpace);
|
||||
|
||||
return indent.generateNewWhiteSpace(indentOptions).toString();
|
||||
return indent.generateNewWhiteSpace(indentOptions);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -355,10 +354,10 @@ public class FormatterImpl extends FormatterEx
|
||||
|
||||
private static int getLineStartOffset(final int offset,
|
||||
final WhiteSpace whiteSpace,
|
||||
final CharSequence text,
|
||||
final FormattingDocumentModel documentModel) {
|
||||
int lineStartOffset = offset;
|
||||
|
||||
CharSequence text = getCharSequence(documentModel);
|
||||
lineStartOffset = CharArrayUtil.shiftBackwardUntil(text, lineStartOffset, " \t\n");
|
||||
if (lineStartOffset > whiteSpace.getStartOffset()) {
|
||||
if (lineStartOffset >= text.length()) lineStartOffset = text.length() - 1;
|
||||
@@ -572,10 +571,6 @@ public class FormatterImpl extends FormatterEx
|
||||
return myContinutationWithoutFirstIndent;
|
||||
}
|
||||
|
||||
public static int getLineFeedsToModified(final FormattingDocumentModel model, final int offset, final int startOffset) {
|
||||
return model.getLineNumber(offset) - model.getLineNumber(startOffset);
|
||||
}
|
||||
|
||||
private final Object DISABLING_LOCK = new Object();
|
||||
|
||||
public boolean isDisabled() {
|
||||
|
||||
@@ -20,8 +20,6 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
class LeafBlockWrapper extends AbstractBlockWrapper {
|
||||
private static final int CONTAIN_LINE_FEEDS = 4;
|
||||
private static final int READ_ONLY = 8;
|
||||
@@ -149,12 +147,7 @@ class LeafBlockWrapper extends AbstractBlockWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<IndentData> ignored = new ArrayList<IndentData>();
|
||||
IndentData result = myParent.getChildOffset(this, options, this.getStartOffset());
|
||||
if (!ignored.isEmpty()) {
|
||||
result = result.add(ignored.get(ignored.size() - 1));
|
||||
}
|
||||
return result;
|
||||
return myParent.getChildOffset(this, options, this.getStartOffset());
|
||||
}
|
||||
|
||||
public void setSpaceProperty(final SpacingImpl currentSpaceProperty) {
|
||||
@@ -191,8 +184,4 @@ class LeafBlockWrapper extends AbstractBlockWrapper {
|
||||
return new TextRange(myStart, myEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LeafBlockWrapper(" + myStart + "-" + myEnd + ")";
|
||||
}
|
||||
}
|
||||
|
||||
+25
-1
@@ -33,8 +33,10 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
@@ -352,6 +354,7 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
group.add(actionManager.createExpandAllAction(treeExpander, tree));
|
||||
}
|
||||
group.add(actionManager.createCollapseAllAction(treeExpander, tree));
|
||||
group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE));
|
||||
group.add(ActionManager.getInstance().getAction(IdeActions.MODULE_SETTINGS));
|
||||
appendDependenciesAction(group);
|
||||
return group;
|
||||
@@ -406,7 +409,7 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
TreeUtil.selectFirstNode(myLeftTree);
|
||||
}
|
||||
|
||||
private static class MyUserObject{
|
||||
private static class MyUserObject implements Navigatable{
|
||||
private boolean myInCycle;
|
||||
private final Module myModule;
|
||||
|
||||
@@ -438,6 +441,18 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
public String toString() {
|
||||
return myModule.getName();
|
||||
}
|
||||
|
||||
public void navigate(boolean requestFocus) {
|
||||
ProjectSettingsService.getInstance(myModule.getProject()).openModuleSettings(myModule);
|
||||
}
|
||||
|
||||
public boolean canNavigate() {
|
||||
return myModule != null && !myModule.isDisposed();
|
||||
}
|
||||
|
||||
public boolean canNavigateToSource() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyTreePanel extends JPanel implements DataProvider{
|
||||
@@ -466,6 +481,15 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
|
||||
if (PlatformDataKeys.HELP_ID.is(dataId)) {
|
||||
return ourHelpID;
|
||||
}
|
||||
if (PlatformDataKeys.NAVIGATABLE.is(dataId)) {
|
||||
final TreePath selectionPath = myTree.getLeadSelectionPath();
|
||||
if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode){
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
|
||||
if (node.getUserObject() instanceof MyUserObject){
|
||||
return node.getUserObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.packageDependencies.ui;
|
||||
|
||||
import com.intellij.analysis.AnalysisScopeBundle;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.PsiFile;
|
||||
|
||||
@@ -40,6 +41,21 @@ public class ModuleNode extends PackageDependenciesNode {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigate() {
|
||||
return myModule != null && !myModule.isDisposed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigateToSource() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigate(boolean focus) {
|
||||
ProjectSettingsService.getInstance(myModule.getProject()).openModuleSettings(myModule);
|
||||
}
|
||||
|
||||
public Icon getOpenIcon() {
|
||||
return myModule == null ? null : myModule.getModuleType().getNodeIcon(true);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@ import com.intellij.lang.ASTFactory;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.CharTable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -248,4 +250,22 @@ public class FormatterUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isPrecededBy(ASTNode node, IElementType eType) {
|
||||
ASTNode prevNode = node.getTreePrev();
|
||||
while (prevNode != null && prevNode.getPsi() instanceof PsiWhiteSpace) {
|
||||
prevNode = prevNode.getTreePrev();
|
||||
}
|
||||
if (prevNode == null) return false;
|
||||
return prevNode.getElementType() == eType;
|
||||
}
|
||||
|
||||
public static boolean isPrecededBy(ASTNode node, TokenSet tokens) {
|
||||
ASTNode prevNode = node.getTreePrev();
|
||||
while (prevNode != null && prevNode.getPsi() instanceof PsiWhiteSpace) {
|
||||
prevNode = prevNode.getTreePrev();
|
||||
}
|
||||
if (prevNode == null) return false;
|
||||
return tokens.contains(prevNode.getElementType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.formatter;
|
||||
|
||||
import com.intellij.formatting.Wrap;
|
||||
import com.intellij.formatting.WrapType;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
|
||||
/**
|
||||
* Misc. code wrapping functions
|
||||
* @author rvishnyakov
|
||||
*/
|
||||
public class WrappingUtil {
|
||||
|
||||
private WrappingUtil() {
|
||||
}
|
||||
|
||||
public static boolean shouldWrap(int setting) {
|
||||
return setting != CodeStyleSettings.DO_NOT_WRAP;
|
||||
}
|
||||
|
||||
public static Wrap createWrap(int setting) {
|
||||
return Wrap.createWrap(getWrapType(setting), true);
|
||||
}
|
||||
|
||||
public static WrapType getWrapType(int setting) {
|
||||
switch (setting) {
|
||||
case CodeStyleSettings.WRAP_ALWAYS:
|
||||
return WrapType.ALWAYS;
|
||||
case CodeStyleSettings.WRAP_AS_NEEDED:
|
||||
return WrapType.NORMAL;
|
||||
case CodeStyleSettings.DO_NOT_WRAP:
|
||||
return WrapType.NONE;
|
||||
default:
|
||||
return WrapType.CHOP_DOWN_IF_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
public static WrapType getArrayInitializerWrapType(CodeStyleSettings settings,
|
||||
ASTNode node,
|
||||
IElementType lBraceType,
|
||||
IElementType rBraceType) {
|
||||
WrapType wrapType = WrapType.NONE;
|
||||
if (shouldWrap(settings.ARRAY_INITIALIZER_WRAP)) {
|
||||
if (node.getElementType() == rBraceType) {
|
||||
wrapType = settings.ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE ? Wrap.ALWAYS : Wrap.NONE;
|
||||
}
|
||||
else if (FormatterUtil.isPrecededBy(node, lBraceType)) {
|
||||
wrapType = settings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE ? Wrap.ALWAYS : Wrap.NONE;
|
||||
}
|
||||
else {
|
||||
wrapType = WrappingUtil.getWrapType(settings.ARRAY_INITIALIZER_WRAP);
|
||||
}
|
||||
}
|
||||
return wrapType;
|
||||
}
|
||||
}
|
||||
@@ -67,16 +67,33 @@ public class ChangeList {
|
||||
myChangeSetDepth++;
|
||||
if (myChangeSetDepth > 1) return;
|
||||
|
||||
doBeginChangeSet();
|
||||
}
|
||||
|
||||
private void doBeginChangeSet() {
|
||||
myCurrentChangeSet = new ChangeSet(myStorage.nextId(), Clock.getCurrentTimestamp());
|
||||
myCurrentBlock.add(myCurrentChangeSet);
|
||||
}
|
||||
|
||||
public synchronized boolean forceBeginChangeSet() {
|
||||
boolean split = myChangeSetDepth > 0;
|
||||
if (split) doEndChangeSet(null);
|
||||
|
||||
myChangeSetDepth++;
|
||||
doBeginChangeSet();
|
||||
return split;
|
||||
}
|
||||
|
||||
public synchronized boolean endChangeSet(String name) {
|
||||
assert myChangeSetDepth > 0;
|
||||
|
||||
myChangeSetDepth--;
|
||||
if (myChangeSetDepth > 0) return false;
|
||||
|
||||
return doEndChangeSet(name);
|
||||
}
|
||||
|
||||
private boolean doEndChangeSet(String name) {
|
||||
if (myCurrentChangeSet.getChanges().isEmpty()) {
|
||||
myCurrentBlock.removeLast();
|
||||
return false;
|
||||
@@ -144,7 +161,7 @@ public class ChangeList {
|
||||
}
|
||||
|
||||
private void flushChanges(boolean force) {
|
||||
if (myChangeSetDepth > 0) return;
|
||||
if (myChangeSetDepth > 0) return;
|
||||
if (myCurrentBlock.shouldFlush(force) || flushEveryChangeSetInTests()) {
|
||||
myStorage.writeNextBlock(myCurrentBlock);
|
||||
myCurrentBlock = myStorage.createNewBlock();
|
||||
|
||||
@@ -140,7 +140,7 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
}
|
||||
|
||||
public synchronized List<ChangeSetBlock> purge(long period, int intervalBetweenActivities) {
|
||||
List<ChangeSetBlock> result = new ArrayList<ChangeSetBlock>();
|
||||
List<ChangeSetBlock> result = new ArrayList<ChangeSetBlock>(); // todo : do not collect changesets
|
||||
int each = findFirstObsoleteBlock(period, intervalBetweenActivities);
|
||||
try {
|
||||
while(each != 0) {
|
||||
@@ -155,7 +155,6 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private int findFirstObsoleteBlock(long period, int intervalBetweenActivities) {
|
||||
long prevTimestamp = 0;
|
||||
long length = 0;
|
||||
@@ -178,8 +177,7 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public void flush() {
|
||||
public synchronized void flush() {
|
||||
myStorage.flushSome();
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
private static final int VERSION = 3;
|
||||
private static final int VERSION = 4;
|
||||
|
||||
private static final int ID_COUNTER_OFFSET = DEFAULT_HEADER_SIZE;
|
||||
private static final int FIRST_RECORD_OFFSET = ID_COUNTER_OFFSET + 8;
|
||||
@@ -62,6 +62,13 @@ public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
return ZEROS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDeletedRecord(int record) {
|
||||
setTimestamp(record, 0);
|
||||
setNextRecord(record, 0);
|
||||
setPrevRecord(record, 0);
|
||||
}
|
||||
|
||||
public void setFSTimestamp(long timestamp) {
|
||||
markDirty();
|
||||
myStorage.putLong(FS_TIMESTAMP_OFFSET, timestamp);
|
||||
@@ -77,7 +84,6 @@ public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
}
|
||||
|
||||
public int getFirstRecord() {
|
||||
markDirty();
|
||||
return myStorage.getInt(FIRST_RECORD_OFFSET);
|
||||
}
|
||||
|
||||
@@ -87,7 +93,6 @@ public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
}
|
||||
|
||||
public int getLastRecord() {
|
||||
markDirty();
|
||||
return myStorage.getInt(LAST_RECORD_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@ public class LinkedStorage extends AbstractStorage {
|
||||
}
|
||||
}
|
||||
|
||||
public int getFirstRecord() {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getFirstRecord();
|
||||
}
|
||||
}
|
||||
|
||||
public int getLastRecord() {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getLastRecord();
|
||||
@@ -67,6 +73,12 @@ public class LinkedStorage extends AbstractStorage {
|
||||
}
|
||||
}
|
||||
|
||||
public int getNextRecord(int record) {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getNextRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
public long getTimestamp(int record) {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getTimestamp(record);
|
||||
|
||||
@@ -46,6 +46,12 @@ public class LocalHistoryFacade {
|
||||
myChangeList.beginChangeSet();
|
||||
}
|
||||
|
||||
public void forceBeginChangeSet() {
|
||||
if (myChangeList.forceBeginChangeSet()) {
|
||||
fireChangeSetFinished();
|
||||
}
|
||||
}
|
||||
|
||||
public void endChangeSet(String name) {
|
||||
if (myChangeList.endChangeSet(name)) {
|
||||
fireChangeSetFinished();
|
||||
|
||||
@@ -51,8 +51,8 @@ public class StreamUtil {
|
||||
}
|
||||
|
||||
public static Change readChange(DataInput in) throws IOException {
|
||||
switch (in.readInt()) {
|
||||
case 0:
|
||||
int type = in.readInt();
|
||||
switch (type) {
|
||||
case 1:
|
||||
return new CreateFileChange(in);
|
||||
case 2:
|
||||
@@ -72,14 +72,13 @@ public class StreamUtil {
|
||||
case 9:
|
||||
return new PutSystemLabelChange(in);
|
||||
}
|
||||
throw new IOException();
|
||||
throw new IOException("unexpected change type: " + type);
|
||||
}
|
||||
|
||||
public static void writeChange(DataOutput out, Change change) throws IOException {
|
||||
int id = -1;
|
||||
|
||||
Class c = change.getClass();
|
||||
if (c.equals(ChangeSet.class)) id = 0;
|
||||
if (c.equals(CreateFileChange.class)) id = 1;
|
||||
if (c.equals(CreateDirectoryChange.class)) id = 2;
|
||||
if (c.equals(ContentChange.class)) id = 3;
|
||||
@@ -90,7 +89,7 @@ public class StreamUtil {
|
||||
if (c.equals(PutLabelChange.class)) id = 8;
|
||||
if (c.equals(PutSystemLabelChange.class)) id = 9;
|
||||
|
||||
assert id != -1;
|
||||
if (id == -1) throw new IOException("unexpected change type: " + c);
|
||||
|
||||
out.writeInt(id);
|
||||
change.write(out);
|
||||
|
||||
+8
-29
@@ -30,9 +30,7 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V
|
||||
private static final Key<Boolean> WAS_VERSIONED_KEY = Key.create(LocalHistoryEventDispatcher.class.getSimpleName() + ".WAS_VERSIONED_KEY");
|
||||
|
||||
private final LocalHistoryFacade myVcs;
|
||||
|
||||
private final IdeaGateway myGateway;
|
||||
private int myChangeSetDepth = 0;
|
||||
|
||||
public LocalHistoryEventDispatcher(LocalHistoryFacade vcs, IdeaGateway gw) {
|
||||
myVcs = vcs;
|
||||
@@ -64,41 +62,22 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V
|
||||
public void undoTransparentActionFinished() {
|
||||
}
|
||||
|
||||
public synchronized void startAction() {
|
||||
// save document in current or new changeset and close it
|
||||
if (myChangeSetDepth == 0) {
|
||||
myVcs.beginChangeSet();
|
||||
}
|
||||
public void startAction() {
|
||||
myGateway.registerUnsavedDocuments(myVcs);
|
||||
myVcs.endChangeSet(null);
|
||||
|
||||
// restore changeset if there were before saving the documents
|
||||
if (myChangeSetDepth > 0) {
|
||||
myVcs.beginChangeSet();
|
||||
}
|
||||
|
||||
beginChangeSet();
|
||||
myVcs.forceBeginChangeSet();
|
||||
}
|
||||
|
||||
public synchronized void finishAction(String name) {
|
||||
public void finishAction(String name) {
|
||||
myGateway.registerUnsavedDocuments(myVcs);
|
||||
endChangeSet(name);
|
||||
}
|
||||
|
||||
private synchronized void beginChangeSet() {
|
||||
myChangeSetDepth++;
|
||||
if (myChangeSetDepth == 1) {
|
||||
myVcs.beginChangeSet();
|
||||
}
|
||||
private void beginChangeSet() {
|
||||
myVcs.beginChangeSet();
|
||||
}
|
||||
|
||||
private synchronized void endChangeSet(String name) {
|
||||
LocalHistoryLog.LOG.assertTrue(myChangeSetDepth > 0, "changeset depth is invalid");
|
||||
|
||||
myChangeSetDepth--;
|
||||
if (myChangeSetDepth == 0) {
|
||||
myVcs.endChangeSet(name);
|
||||
}
|
||||
private void endChangeSet(String name) {
|
||||
myVcs.endChangeSet(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,7 +92,7 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V
|
||||
myVcs.created(f.getPath(), f.isDirectory());
|
||||
}
|
||||
if (f.isDirectory()) {
|
||||
for (VirtualFile each : ((NewVirtualFile)f).getChildren()) {
|
||||
for (VirtualFile each : ((NewVirtualFile)f).iterInDbChildren()) {
|
||||
createRecursively(each);
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -81,7 +81,6 @@ public class DirectoryHistoryDialog extends HistoryDialog<DirectoryHistoryDialog
|
||||
p.add(myToolBar.getComponent(), BorderLayout.NORTH);
|
||||
|
||||
p.add(myChangesTree, BorderLayout.CENTER);
|
||||
p.add(new DiffStatusBar(DiffStatusBar.DEFAULT_TYPES), BorderLayout.SOUTH);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -115,6 +115,28 @@ public class ChangeListTest extends ChangeListTestCase {
|
||||
assertEquals(array(c1, c2), cc.get(0).getChanges());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForcesBegin() throws Exception {
|
||||
facade.beginChangeSet();
|
||||
add(facade, createFile(r, "f1"));
|
||||
facade.beginChangeSet();
|
||||
add(facade, createFile(r, "f2"));
|
||||
facade.forceBeginChangeSet();
|
||||
add(facade, createFile(r, "f3"));
|
||||
facade.endChangeSet("a");
|
||||
add(facade, createFile(r, "f4"));
|
||||
facade.endChangeSet("b");
|
||||
add(facade, createFile(r, "f5"));
|
||||
facade.endChangeSet("c");
|
||||
|
||||
List<ChangeSet> cc = facade.getChangeListInTests().getChangesInTests();
|
||||
assertEquals(2, cc.size());
|
||||
assertEquals("c", cc.get(0).getName());
|
||||
assertEquals(3, cc.get(0).getChanges().size());
|
||||
assertEquals(null, cc.get(1).getName());
|
||||
assertEquals(2, cc.get(1).getChanges().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeSetTimestamp() {
|
||||
setCurrentTimestamp(123);
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.historyIntegrTests;
|
||||
|
||||
import com.intellij.history.core.LinkedStorage;
|
||||
import com.intellij.util.io.storage.AbstractStorage;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LinkedStorageTest extends IntegrationTestCase {
|
||||
private LinkedStorage myStorage;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myStorage.dispose();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testBasic() throws Exception {
|
||||
assertFirstAndLast(0, 0);
|
||||
|
||||
int r1 = createRecord();
|
||||
int r2 = createRecord();
|
||||
|
||||
assertFirstAndLast(r1, r2);
|
||||
assertRecord(r2, r1, 0);
|
||||
assertRecord(r1, 0, r2);
|
||||
}
|
||||
|
||||
public void testDeletion() throws Exception {
|
||||
int r1 = createRecord();
|
||||
int r2 = createRecord();
|
||||
int r3 = createRecord();
|
||||
|
||||
assertFirstAndLast(r1, r3);
|
||||
assertRecord(r3, r2, 0);
|
||||
assertRecord(r2, r1, r3);
|
||||
assertRecord(r1, 0, r2);
|
||||
|
||||
myStorage.deleteRecord(r2);
|
||||
|
||||
assertFirstAndLast(r1, r3);
|
||||
assertRecord(r3, r1, 0);
|
||||
assertRecord(r1, 0, r3);
|
||||
|
||||
myStorage.deleteRecord(r3);
|
||||
|
||||
assertFirstAndLast(r1, r1);
|
||||
assertRecord(r1, 0, 0);
|
||||
|
||||
int r4 = createRecord();
|
||||
|
||||
assertFirstAndLast(r1, r4);
|
||||
assertRecord(r4, r1, 0);
|
||||
assertRecord(r1, 0, r4);
|
||||
|
||||
myStorage.deleteRecord(r1);
|
||||
|
||||
assertFirstAndLast(r4, r4);
|
||||
assertRecord(r4, 0, 0);
|
||||
|
||||
myStorage.deleteRecord(r4);
|
||||
|
||||
assertFirstAndLast(0, 0);
|
||||
}
|
||||
|
||||
public void testReopening() throws Exception {
|
||||
int r1 = createRecord();
|
||||
int r2 = createRecord();
|
||||
int r3 = createRecord();
|
||||
|
||||
myStorage.deleteRecord(r2);
|
||||
|
||||
myStorage.dispose();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
|
||||
assertFirstAndLast(r1, r3);
|
||||
assertRecord(r3, r1, 0);
|
||||
assertRecord(r1, 0, r3);
|
||||
|
||||
myStorage.deleteRecord(r1);
|
||||
|
||||
myStorage.dispose();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
|
||||
assertFirstAndLast(r3, r3);
|
||||
assertRecord(r3, 0, 0);
|
||||
|
||||
int r4 = createRecord();
|
||||
|
||||
myStorage.dispose();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
|
||||
assertFirstAndLast(r3, r4);
|
||||
assertRecord(r4, r3, 0);
|
||||
assertRecord(r3, 0, r4);
|
||||
}
|
||||
|
||||
private int createRecord() throws IOException {
|
||||
int r = myStorage.createNextRecord();
|
||||
AbstractStorage.StorageDataOutput s = myStorage.writeStream(r);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
s.writeInt(r);
|
||||
}
|
||||
s.close();
|
||||
return r;
|
||||
}
|
||||
|
||||
private void assertFirstAndLast(int first, int last) {
|
||||
assertEquals(first, myStorage.getFirstRecord());
|
||||
assertEquals(last, myStorage.getLastRecord());
|
||||
}
|
||||
|
||||
private void assertRecord(int id, int prev, int next) throws IOException {
|
||||
assertEquals(prev, myStorage.getPrevRecord(id));
|
||||
assertEquals(next, myStorage.getNextRecord(id));
|
||||
DataInputStream s = myStorage.readStream(id);
|
||||
try {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
assertEquals(id, s.readInt());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
* @author Roman.Chernyatchik, oleg
|
||||
*/
|
||||
public interface CommandLineArgumentsProvider {
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingManager;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
|
||||
import com.intellij.util.Icons;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -36,6 +37,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a file in <code>{@link VirtualFileSystem}</code>. A particular file is represented by the same
|
||||
@@ -451,7 +453,10 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica
|
||||
if (isValid() && !application.isDisposed()) {
|
||||
application.runWriteAction(new Runnable(){
|
||||
public void run() {
|
||||
application.getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES).after(Collections.singletonList(new VFilePropertyChangeEvent(this, VirtualFile.this, PROP_ENCODING, old, charset, false)));
|
||||
List<VFilePropertyChangeEvent> events = Collections.singletonList(new VFilePropertyChangeEvent(this, VirtualFile.this, PROP_ENCODING, old, charset, false));
|
||||
BulkFileListener listener = application.getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES);
|
||||
listener.before(events);
|
||||
listener.after(events);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.ui.FixedSizeButton;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.CharFilter;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -50,6 +51,11 @@ public class GuiUtils {
|
||||
private static final Insets paddingInsideDialog = new Insets(5, 5, 5, 5);
|
||||
|
||||
public static final int lengthForFileField = 25;
|
||||
private static final CharFilter NOT_MNEMONIC_CHAR_FILTER = new CharFilter() {
|
||||
public boolean accept(char ch) {
|
||||
return ch != '&' && ch != UIUtil.MNEMONIC;
|
||||
}
|
||||
};
|
||||
|
||||
public static JPanel constructFieldWithBrowseButton(JComponent aComponent, ActionListener aActionListener) {
|
||||
return constructFieldWithBrowseButton(aComponent, aActionListener, 0);
|
||||
@@ -187,7 +193,7 @@ public class GuiUtils {
|
||||
}
|
||||
|
||||
public static String getTextWithoutMnemonicEscaping(String text) {
|
||||
return text.replaceAll("&", "");
|
||||
return StringUtil.strip(text, NOT_MNEMONIC_CHAR_FILTER);
|
||||
}
|
||||
|
||||
public static char getDisplayedMnemonic(String text) {
|
||||
|
||||
@@ -17,14 +17,15 @@ package com.intellij.ide.impl.dataRules;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
|
||||
public class CopyProviderRule implements GetDataRule {
|
||||
public Object getData(DataProvider dataProvider) {
|
||||
final EditorEx editor = (EditorEx)dataProvider.getData(PlatformDataKeys.EDITOR.getName());
|
||||
if (editor == null) {
|
||||
return null;
|
||||
final Editor editor = PlatformDataKeys.EDITOR.getData(dataProvider);
|
||||
if (editor instanceof EditorEx) {
|
||||
return ((EditorEx) editor).getCopyProvider();
|
||||
}
|
||||
return editor.getCopyProvider();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,15 @@ package com.intellij.ide.impl.dataRules;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
|
||||
public class CutProviderRule implements GetDataRule {
|
||||
public Object getData(DataProvider dataProvider) {
|
||||
final EditorEx editor = (EditorEx)dataProvider.getData(PlatformDataKeys.EDITOR.getName());
|
||||
if (editor == null) {
|
||||
return null;
|
||||
final Editor editor = PlatformDataKeys.EDITOR.getData(dataProvider);
|
||||
if (editor instanceof EditorEx) {
|
||||
return ((EditorEx) editor).getCutProvider();
|
||||
}
|
||||
return editor.getCutProvider();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@ package com.intellij.ide.impl.dataRules;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
|
||||
public class PasteProviderRule implements GetDataRule {
|
||||
public Object getData(DataProvider dataProvider) {
|
||||
final EditorEx editor = (EditorEx)dataProvider.getData(PlatformDataKeys.EDITOR.getName());
|
||||
if (editor == null) {
|
||||
return null;
|
||||
final Editor editor = PlatformDataKeys.EDITOR.getData(dataProvider);
|
||||
if (editor instanceof EditorEx) {
|
||||
return ((EditorEx) editor).getPasteProvider();
|
||||
}
|
||||
|
||||
return editor.getPasteProvider();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -16,7 +16,7 @@
|
||||
package com.intellij.openapi.editor.colors.impl;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Roman Chernyatchik
|
||||
@@ -29,6 +29,9 @@ public interface BundledColorSchemesProvider {
|
||||
* @return Array of relative paths without extensions for schemes.
|
||||
* E.g. : ["/colorSchemes/colbalt", "myscheme"] for colorSchemes/colbalt.xml, myscheme.xml
|
||||
*/
|
||||
@NotNull
|
||||
@Nullable
|
||||
String[] getBundledSchemesRelativePaths();
|
||||
|
||||
@Nullable
|
||||
String getDefaultSchemaExtensionPath();
|
||||
}
|
||||
|
||||
+78
-24
@@ -25,10 +25,9 @@ import com.intellij.openapi.application.ex.DecodeDefaultsUtil;
|
||||
import com.intellij.openapi.components.ExportableApplicationComponent;
|
||||
import com.intellij.openapi.components.RoamingType;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsListener;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.*;
|
||||
import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.options.*;
|
||||
import com.intellij.openapi.util.*;
|
||||
import org.jdom.Document;
|
||||
@@ -37,13 +36,11 @@ import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.*;
|
||||
|
||||
public class EditorColorsManagerImpl extends EditorColorsManager
|
||||
implements NamedJDOMExternalizable, ExportableApplicationComponent {
|
||||
@@ -113,38 +110,73 @@ public class EditorColorsManagerImpl extends EditorColorsManager
|
||||
|
||||
|
||||
addDefaultSchemes();
|
||||
|
||||
// Change some attributes of default schema using special extension
|
||||
extendDefaultScheme();
|
||||
|
||||
// Load default schemes from providers
|
||||
loadAdditionalDefaultSchemes();
|
||||
|
||||
loadAllSchemes();
|
||||
|
||||
setGlobalScheme(myDefaultColorSchemesManager.getAllSchemes()[0]);
|
||||
}
|
||||
|
||||
private void extendDefaultScheme() {
|
||||
final EditorColorsScheme defaultColorsScheme = mySchemesManager.findSchemeByName("Default");
|
||||
|
||||
//Get color scheme from EPs
|
||||
for (BundledColorSchemesProvider provider : BundledColorSchemesProvider.EP_NAME.getExtensions()) {
|
||||
final String extensionPath = provider.getDefaultSchemaExtensionPath();
|
||||
if (extensionPath == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
final EditorColorsSchemeImpl extScheme = loadScheme(extensionPath, provider);
|
||||
if (extScheme != null) {
|
||||
// copy text attrs from extension to default scheme
|
||||
for (Map.Entry<TextAttributesKey, TextAttributes> keyTextAttributesEntry : extScheme.myAttributesMap.entrySet()) {
|
||||
final TextAttributesKey key = keyTextAttributesEntry.getKey();
|
||||
final TextAttributes attrs = keyTextAttributesEntry.getValue();
|
||||
((AbstractColorsScheme)defaultColorsScheme).myAttributesMap.put(key, attrs);
|
||||
}
|
||||
|
||||
// copy colors
|
||||
for (Map.Entry<ColorKey, Color> keyColorEntry : extScheme.myColorsMap.entrySet()) {
|
||||
final ColorKey key = keyColorEntry.getKey();
|
||||
final Color color = keyColorEntry.getValue();
|
||||
((AbstractColorsScheme)defaultColorsScheme).myColorsMap.put(key, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
ApplicationManager.getApplication().invokeLater(
|
||||
new Runnable(){
|
||||
public void run() {
|
||||
// Error shouldn't occur during this operation
|
||||
// thus we report error instead of info
|
||||
LOG.error("Cannot read scheme from " + extensionPath + ": " + e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadAdditionalDefaultSchemes() {
|
||||
//Get color schemes from EPs
|
||||
for (BundledColorSchemesProvider provider : BundledColorSchemesProvider.EP_NAME.getExtensions()) {
|
||||
final String[] schemesPaths = provider.getBundledSchemesRelativePaths();
|
||||
if (schemesPaths == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (final String schemePath : schemesPaths) {
|
||||
try {
|
||||
final InputStream inputStream = DecodeDefaultsUtil.getDefaultsInputStream(provider, schemePath);
|
||||
if (inputStream == null) {
|
||||
// Error shouldn't occur during this operation
|
||||
// thus we report error instead of info
|
||||
LOG.error("Cannot read scheme from " + schemePath);
|
||||
continue;
|
||||
final EditorColorsSchemeImpl scheme = loadScheme(schemePath, provider);
|
||||
if (scheme != null) {
|
||||
mySchemesManager.addNewScheme(scheme, false);
|
||||
}
|
||||
|
||||
final Document document;
|
||||
try {
|
||||
document = JDOMUtil.loadDocument(inputStream);
|
||||
}
|
||||
catch (JDOMException e) {
|
||||
LOG.info("Error reading scheme from " + schemePath + ": " + e.getLocalizedMessage());
|
||||
throw e;
|
||||
}
|
||||
final EditorColorsSchemeImpl scheme = loadSchemeFromDocument(document, false);
|
||||
mySchemesManager.addNewScheme(scheme, false);
|
||||
}
|
||||
catch (final Exception e) {
|
||||
ApplicationManager.getApplication().invokeLater(
|
||||
@@ -161,6 +193,28 @@ public class EditorColorsManagerImpl extends EditorColorsManager
|
||||
}
|
||||
}
|
||||
|
||||
private EditorColorsSchemeImpl loadScheme(@NotNull final String schemePath,
|
||||
final BundledColorSchemesProvider provider)
|
||||
throws IOException, JDOMException, InvalidDataException {
|
||||
final InputStream inputStream = DecodeDefaultsUtil.getDefaultsInputStream(provider, schemePath);
|
||||
if (inputStream == null) {
|
||||
// Error shouldn't occur during this operation
|
||||
// thus we report error instead of info
|
||||
LOG.error("Cannot read scheme from " + schemePath);
|
||||
return null;
|
||||
}
|
||||
|
||||
final Document document;
|
||||
try {
|
||||
document = JDOMUtil.loadDocument(inputStream);
|
||||
}
|
||||
catch (JDOMException e) {
|
||||
LOG.info("Error reading scheme from " + schemePath + ": " + e.getLocalizedMessage());
|
||||
throw e;
|
||||
}
|
||||
return loadSchemeFromDocument(document, false);
|
||||
}
|
||||
|
||||
private EditorColorsSchemeImpl loadSchemeFromDocument(final Document document,
|
||||
final boolean isEditable)
|
||||
throws InvalidDataException {
|
||||
|
||||
@@ -108,7 +108,6 @@ public class ColorProgressBar extends JComponent {
|
||||
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
if (myFraction == 0) return;
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
Object oldAntialiasing = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
|
||||
|
||||
+6
-1
@@ -110,6 +110,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() {
|
||||
public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) {
|
||||
VirtualFile file = event.getFile();
|
||||
LOG.info("[RELOAD] Storage file changed: " + file.getPath());
|
||||
if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) {
|
||||
saveChangedProjectFile(file, null, storage);
|
||||
}
|
||||
@@ -535,6 +536,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
}
|
||||
|
||||
private void askToReloadProjectIfConfigFilesChangedExternally() {
|
||||
LOG.info("[RELOAD] myReloadBlockCount = " + myReloadBlockCount.get());
|
||||
if (myReloadBlockCount.get() == 0) {
|
||||
Set<Project> projects;
|
||||
|
||||
@@ -572,7 +574,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
reloadOk[0] = ((ApplicationImpl)app).getStateStore().reload(causes, components);
|
||||
}
|
||||
catch (StateStorage.StateStorageException e) {
|
||||
@@ -639,6 +640,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
LOG.info("[RELOAD] Reloading project/components...");
|
||||
reloadOk[0] = ((ProjectEx)project).getStateStore().reload(causes);
|
||||
}
|
||||
catch (StateStorage.StateStorageException e) {
|
||||
@@ -725,6 +727,8 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
}
|
||||
|
||||
private void registerProjectToReload(final Project project, final VirtualFile cause, final StateStorage storage) {
|
||||
LOG.info("[RELOAD] Registering project to reload.");
|
||||
|
||||
if (project != null) {
|
||||
synchronized (myChangedProjectFiles) {
|
||||
List<Pair<VirtualFile, StateStorage>> changedProjectFiles = myChangedProjectFiles.get(project);
|
||||
@@ -743,6 +747,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
myChangedFilesAlarm.cancelAllRequests();
|
||||
myChangedFilesAlarm.addRequest(new Runnable() {
|
||||
public void run() {
|
||||
LOG.info("[RELOAD] Scheduling reload application & project, myReloadBlockCount = " + myReloadBlockCount);
|
||||
if (myReloadBlockCount.get() == 0) {
|
||||
scheduleReloadApplicationAndProject();
|
||||
}
|
||||
|
||||
@@ -22,19 +22,13 @@
|
||||
<keyboard-shortcut first-keystroke="shift alt C" />
|
||||
</action>
|
||||
<action id="CheckinProject" />
|
||||
<action id="CloseActiveTab">
|
||||
<keyboard-shortcut first-keystroke="control F4" />
|
||||
<keyboard-shortcut first-keystroke="control W" />
|
||||
</action>
|
||||
<action id="CloseActiveTab" />
|
||||
<action id="CloseAllEditors">
|
||||
<keyboard-shortcut first-keystroke="shift control F4" />
|
||||
<keyboard-shortcut first-keystroke="shift control W" />
|
||||
</action>
|
||||
<action id="CloseEditor" />
|
||||
<action id="CloseWindow">
|
||||
<keyboard-shortcut first-keystroke="control F4" />
|
||||
<keyboard-shortcut first-keystroke="control W" />
|
||||
</action>
|
||||
<action id="CloseWindow" />
|
||||
<action id="CodeInspection.OnEditor" />
|
||||
<action id="CollapseAllRegions">
|
||||
<keyboard-shortcut first-keystroke="shift control DIVIDE" />
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
<keyboard-shortcut first-keystroke="UP"/>
|
||||
<keyboard-shortcut first-keystroke="control P"/>
|
||||
</action>
|
||||
<action id="CloseEditor">
|
||||
<action id="CloseContent">
|
||||
<keyboard-shortcut first-keystroke="control F4"/>
|
||||
<keyboard-shortcut first-keystroke="control X" second-keystroke="K"/>
|
||||
</action>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<action id="CloseActiveTab">
|
||||
<keyboard-shortcut first-keystroke="shift control 4" />
|
||||
</action>
|
||||
<action id="CloseEditor">
|
||||
<action id="CloseContent">
|
||||
<keyboard-shortcut first-keystroke="control 4" />
|
||||
</action>
|
||||
<action id="CompileDirty">
|
||||
|
||||
@@ -42,20 +42,16 @@
|
||||
<keyboard-shortcut first-keystroke="control alt BACK_SLASH" />
|
||||
</action>
|
||||
<action id="CloneElement" />
|
||||
<action id="CloseActiveTab">
|
||||
<keyboard-shortcut first-keystroke="control W" />
|
||||
</action>
|
||||
<action id="CloseActiveTab" />
|
||||
<action id="CloseAllEditors">
|
||||
<keyboard-shortcut first-keystroke="shift control W" />
|
||||
<keyboard-shortcut first-keystroke="shift control F4" />
|
||||
</action>
|
||||
<action id="CloseEditor">
|
||||
<action id="CloseContent">
|
||||
<keyboard-shortcut first-keystroke="control F4" />
|
||||
<keyboard-shortcut first-keystroke="control W" />
|
||||
</action>
|
||||
<action id="CloseWindow">
|
||||
<keyboard-shortcut first-keystroke="control W" />
|
||||
</action>
|
||||
<action id="CloseWindow" />
|
||||
<action id="CodeCompletion">
|
||||
<keyboard-shortcut first-keystroke="control SPACE" />
|
||||
<keyboard-shortcut first-keystroke="control BACK_SLASH" />
|
||||
|
||||
@@ -173,9 +173,12 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable {
|
||||
public void deleteRecord(final int record) {
|
||||
ensureFreeRecordsScanned();
|
||||
setSize(record, -1);
|
||||
clearDeletedRecord(record);
|
||||
myFreeRecordsList.add(record);
|
||||
}
|
||||
|
||||
protected abstract void clearDeletedRecord(int record);
|
||||
|
||||
public int getVersion() {
|
||||
return myStorage.getInt(HEADER_VERSION_OFFSET);
|
||||
}
|
||||
|
||||
@@ -47,4 +47,8 @@ class RecordsTable extends AbstractRecordsTable {
|
||||
protected byte[] getZeros() {
|
||||
return ZEROES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDeletedRecord(int record) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,11 @@ class RefCountingRecordsTable extends AbstractRecordsTable {
|
||||
return ZEROES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDeletedRecord(int record) {
|
||||
myStorage.putInt(getOffset(record, REF_COUNT_OFFSET), 0);
|
||||
}
|
||||
|
||||
public void incRefCount(int record) {
|
||||
markDirty();
|
||||
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.xdebugger.frame;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ImmediateFullValueEvaluator extends XFullValueEvaluator {
|
||||
private String myFullValue;
|
||||
|
||||
public ImmediateFullValueEvaluator(@NotNull String linkText, @NotNull String fullValue) {
|
||||
super(linkText);
|
||||
myFullValue = fullValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEvaluation(@NotNull XFullValueEvaluationCallback callback) {
|
||||
callback.evaluated(myFullValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.xdebugger.frame;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Supports asynchronous fetching full text of a value. If full text is already computed use {@link ImmediateFullValueEvaluator}
|
||||
* @see XValueNode#setFullValueEvaluator
|
||||
* @see ImmediateFullValueEvaluator
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class XFullValueEvaluator {
|
||||
private String myLinkText;
|
||||
|
||||
/**
|
||||
* @param linkText text of the link what will be appended to a variables tree node text
|
||||
*/
|
||||
protected XFullValueEvaluator(@NotNull String linkText) {
|
||||
myLinkText = linkText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start fetching full text of the value. Note that this method is called from the Event Dispatch Thread so it should return quickly
|
||||
* @param callback used to notify that the full text has been successfully evaluated or an error occurs
|
||||
*/
|
||||
public abstract void startEvaluation(@NotNull XFullValueEvaluationCallback callback);
|
||||
|
||||
public String getLinkText() {
|
||||
return myLinkText;
|
||||
}
|
||||
|
||||
public interface XFullValueEvaluationCallback {
|
||||
void evaluated(@NotNull String fullValue);
|
||||
|
||||
void errorOccurred(@NotNull String errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public abstract class XValueModifier {
|
||||
|
||||
/**
|
||||
* Start modification of the value. Note that this methods is called from the Event Dispatch Thread so it should return quickly
|
||||
* Start modification of the value. Note that this method is called from the Event Dispatch Thread so it should return quickly
|
||||
* @param expression new value
|
||||
* @param callback used to notify that value has been successfully modified or an error occurs
|
||||
*/
|
||||
|
||||
@@ -38,9 +38,8 @@ public interface XValueNode extends Obsolescent {
|
||||
/**
|
||||
* If string representation of the value is too long to show in the tree pass truncated value to {@link #setPresentation(String, javax.swing.Icon, String, String, boolean)}
|
||||
* method and call this method to provide full value.
|
||||
* This will add a link to the node and show <code>fullValue</code> text if a user click on that link.
|
||||
* @param fullValue full text of the value. Will be shown in popup window
|
||||
* @param linkText text of the link. Will be appended to the node text
|
||||
* This will add a link to the node and show popup with full value if an user clicks on that link.
|
||||
* @param fullValueEvaluator will be used to obtain full text of the value
|
||||
*/
|
||||
void setFullValue(@NotNull String fullValue, @NotNull String linkText);
|
||||
void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator);
|
||||
}
|
||||
|
||||
+2
-1
@@ -30,6 +30,7 @@ import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerUtil;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.frame.XValueNode;
|
||||
import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint;
|
||||
@@ -90,7 +91,7 @@ public class XValueHint extends AbstractValueHint {
|
||||
});
|
||||
}
|
||||
|
||||
public void setFullValue(@NotNull String fullValue, @NotNull String linkText) {
|
||||
public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) {
|
||||
//todo[nik] implement?
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -90,26 +91,52 @@ public class DebuggerUIUtil {
|
||||
return new RelativePoint(editor.getContentComponent(), p);
|
||||
}
|
||||
|
||||
public static void showValuePopup(@NotNull String text, @NotNull MouseEvent event, @NotNull Project project) {
|
||||
JTextArea textArea = new JTextArea(text);
|
||||
public static void showValuePopup(@NotNull XFullValueEvaluator text, @NotNull MouseEvent event, @NotNull Project project) {
|
||||
final JTextArea textArea = new JTextArea("Evaluating...");
|
||||
text.startEvaluation(new FullValueEvaluationCallbackImpl(textArea));
|
||||
|
||||
textArea.setEditable(false);
|
||||
textArea.setBackground(HintUtil.INFORMATION_COLOR);
|
||||
textArea.setLineWrap(false);
|
||||
final JScrollPane component = ScrollPaneFactory.createScrollPane(textArea);
|
||||
final Dimension frameSize = WindowManager.getInstance().getFrame(project).getSize();
|
||||
final Dimension size = new Dimension(frameSize.width / 2, frameSize.height / 2);
|
||||
component.setPreferredSize(size);
|
||||
component.setBorder(null);
|
||||
final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(component, null)
|
||||
.setResizable(true)
|
||||
.setMovable(true)
|
||||
.setDimensionServiceKey(project, "XDebugger.FullValuePopup", false)
|
||||
.setRequestFocus(false)
|
||||
.createPopup();
|
||||
|
||||
final Dimension size = textArea.getPreferredSize();
|
||||
final Component parentComponent = event.getComponent();
|
||||
final Dimension frameSize = WindowManager.getInstance().getFrame(project).getSize();
|
||||
size.width = Math.min(size.width, frameSize.width / 2);
|
||||
size.height = Math.min(size.height, frameSize.height / 2);
|
||||
component.setPreferredSize(size);
|
||||
RelativePoint point = new RelativePoint(parentComponent, new Point(event.getX()-size.width, event.getY()-size.height));
|
||||
popup.show(point);
|
||||
}
|
||||
|
||||
private static class FullValueEvaluationCallbackImpl implements XFullValueEvaluator.XFullValueEvaluationCallback {
|
||||
private final JTextArea myTextArea;
|
||||
|
||||
public FullValueEvaluationCallbackImpl(JTextArea textArea) {
|
||||
myTextArea = textArea;
|
||||
}
|
||||
|
||||
public void evaluated(@NotNull final String fullValue) {
|
||||
invokeOnEventDispatch(new Runnable() {
|
||||
public void run() {
|
||||
myTextArea.setText(fullValue);
|
||||
myTextArea.setCaretPosition(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void errorOccurred(@NotNull final String errorMessage) {
|
||||
invokeOnEventDispatch(new Runnable() {
|
||||
public void run() {
|
||||
myTextArea.setForeground(XDebuggerUIConstants.ERROR_MESSAGE_ATTRIBUTES.getFgColor());
|
||||
myTextArea.setText(errorMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-11
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.xdebugger.frame.XCompositeNode;
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.frame.XValueNode;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
@@ -39,10 +40,9 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
private String myName;
|
||||
private String myType;
|
||||
private String myValue;
|
||||
private String myFullValue;
|
||||
private XFullValueEvaluator myFullValueEvaluator;
|
||||
private String mySeparator;
|
||||
private boolean myChanged;
|
||||
private String myLinkText;
|
||||
|
||||
public XValueNodeImpl(XDebuggerTree tree, final XDebuggerTreeNode parent, final XValue value) {
|
||||
super(tree, parent, value);
|
||||
@@ -74,11 +74,10 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
});
|
||||
}
|
||||
|
||||
public void setFullValue(@NotNull final String fullValue, @NotNull final String linkText) {
|
||||
public void setFullValueEvaluator(@NotNull final XFullValueEvaluator fullValueEvaluator) {
|
||||
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
|
||||
public void run() {
|
||||
myLinkText = linkText;
|
||||
myFullValue = fullValue;
|
||||
myFullValueEvaluator = fullValueEvaluator;
|
||||
fireNodeChanged();
|
||||
}
|
||||
});
|
||||
@@ -122,11 +121,11 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
|
||||
@Override
|
||||
public XDebuggerNodeLink getLink() {
|
||||
if (myFullValue != null) {
|
||||
return new XDebuggerNodeLink(myLinkText) {
|
||||
if (myFullValueEvaluator != null) {
|
||||
return new XDebuggerNodeLink(myFullValueEvaluator.getLinkText()) {
|
||||
@Override
|
||||
public void onClick(MouseEvent event) {
|
||||
DebuggerUIUtil.showValuePopup(myFullValue, event, myTree.getProject());
|
||||
DebuggerUIUtil.showValuePopup(myFullValueEvaluator, event, myTree.getProject());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -135,9 +134,6 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
|
||||
@Nullable
|
||||
public String getValue() {
|
||||
if (myFullValue != null) {
|
||||
return myFullValue;
|
||||
}
|
||||
return myValue;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -71,7 +71,7 @@ public class GenerateToStringUtils {
|
||||
List<PsiField> availableFields = new ArrayList<PsiField>();
|
||||
|
||||
// performs til filtering process
|
||||
PsiField[] fields = psi.getFields(clazz);
|
||||
PsiField[] fields = clazz.getFields();
|
||||
for (PsiField field : fields) {
|
||||
FieldElement fe = ElementFactory.newFieldElement(project, field, psi);
|
||||
if (log.isDebugEnabled()) log.debug("Field being filtered: " + fe);
|
||||
@@ -103,7 +103,7 @@ public class GenerateToStringUtils {
|
||||
List<PsiMethod> availableMethods = new ArrayList<PsiMethod>();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory();
|
||||
|
||||
PsiMethod[] methods = psi.getMethods(clazz);
|
||||
PsiMethod[] methods = clazz.getMethods();
|
||||
for (PsiMethod method : methods) {
|
||||
|
||||
MethodElement me = ElementFactory.newMethodElement(method, elementFactory, psi);
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ public class GenerateToStringWorker {
|
||||
this.psi = PsiAdapterFactory.getPsiAdapter();
|
||||
this.editor = editor;
|
||||
this.elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
this.codeStyleManager = psi.getCodeStyleManager(project);
|
||||
this.codeStyleManager = CodeStyleManager.getInstance(project);
|
||||
this.containingFile = clazz.getContainingFile();
|
||||
this.config = GenerateToStringContext.getConfig();
|
||||
this.hasOverrideAnnotation = insertAtOverride;
|
||||
|
||||
+14
-14
@@ -55,9 +55,9 @@ public class ElementFactory {
|
||||
ce.setImplementNames(psi.getImplementsClassnames(clazz));
|
||||
|
||||
// other
|
||||
ce.setEnum(psi.isEnumClass(clazz));
|
||||
ce.setDeprecated(psi.isDeprecatedClass(clazz));
|
||||
ce.setException(psi.isExceptionClass(clazz));
|
||||
ce.setEnum(clazz.isEnum());
|
||||
ce.setDeprecated(clazz.isDeprecated());
|
||||
ce.setException(PsiAdapter.isExceptionClass(clazz));
|
||||
ce.setAbstract(psi.isAbstractClass(clazz));
|
||||
|
||||
return ce;
|
||||
@@ -83,8 +83,8 @@ public class ElementFactory {
|
||||
if (psi.isEnumField(field)) fe.setEnum(true);
|
||||
PsiModifierList modifiers = field.getModifierList();
|
||||
if (modifiers != null) {
|
||||
if (psi.isModifierTransient(modifiers)) fe.setModifierTransient(true);
|
||||
if (psi.isModifierVolatile(modifiers)) fe.setModifierVolatile(true);
|
||||
if (modifiers.hasModifierProperty(PsiModifier.TRANSIENT)) fe.setModifierTransient(true);
|
||||
if (modifiers.hasModifierProperty(PsiModifier.VOLATILE)) fe.setModifierVolatile(true);
|
||||
}
|
||||
|
||||
setElementInfo(fe, factory, type, modifiers, psi);
|
||||
@@ -126,11 +126,11 @@ public class ElementFactory {
|
||||
|
||||
// misc
|
||||
me.setReturnTypeVoid(psi.isTypeOfVoid(method.getReturnType()));
|
||||
me.setDeprecated(psi.isDeprecatedMethod(method));
|
||||
me.setDeprecated(method.isDeprecated());
|
||||
|
||||
// modifiers
|
||||
if (psi.isModifierAbstract(modifiers)) me.setModifierAbstract(true);
|
||||
if (psi.isModifierSynchronized(modifiers)) me.setModifierSynchronzied(true);
|
||||
if (modifiers.hasModifierProperty(PsiModifier.ABSTRACT)) me.setModifierAbstract(true);
|
||||
if (modifiers.hasModifierProperty(PsiModifier.SYNCHRONIZED)) me.setModifierSynchronzied(true);
|
||||
|
||||
return me;
|
||||
}
|
||||
@@ -184,18 +184,18 @@ public class ElementFactory {
|
||||
|
||||
// modifiers
|
||||
if (modifiers != null) {
|
||||
if (psi.isModifierStatic(modifiers)) element.setModifierStatic(true);
|
||||
if (psi.isModifierFinal(modifiers)) element.setModifierFinal(true);
|
||||
if (psi.isModifierPublic(modifiers)) {
|
||||
if (modifiers.hasModifierProperty(PsiModifier.STATIC)) element.setModifierStatic(true);
|
||||
if (modifiers.hasModifierProperty(PsiModifier.FINAL)) element.setModifierFinal(true);
|
||||
if (modifiers.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
element.setModifierPublic(true);
|
||||
}
|
||||
else if (psi.isModifierProtected(modifiers)) {
|
||||
else if (modifiers.hasModifierProperty(PsiModifier.PROTECTED)) {
|
||||
element.setModifierProtected(true);
|
||||
}
|
||||
else if (psi.isModifierPackageLocal(modifiers)) {
|
||||
else if (modifiers.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
|
||||
element.setModifierPackageLocal(true);
|
||||
}
|
||||
else if (psi.isModifierPrivate(modifiers)) element.setModifierPrivate(true);
|
||||
else if (modifiers.hasModifierProperty(PsiModifier.PRIVATE)) element.setModifierPrivate(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -85,19 +85,19 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
|
||||
PsiAdapter psi = PsiAdapterFactory.getPsiAdapter();
|
||||
|
||||
// must not be an exception
|
||||
if (excludeException && psi.isExceptionClass(clazz)) {
|
||||
if (excludeException && PsiAdapter.isExceptionClass(clazz)) {
|
||||
log.debug("This class is an exception");
|
||||
return;
|
||||
}
|
||||
|
||||
// must not be deprecated
|
||||
if (excludeDeprecated && psi.isDeprecatedClass(clazz)) {
|
||||
if (excludeDeprecated && clazz.isDeprecated()) {
|
||||
log.debug("Class is deprecated");
|
||||
return;
|
||||
}
|
||||
|
||||
// must not be enum
|
||||
if (excludeEnum && psi.isEnumClass(clazz)) {
|
||||
if (excludeEnum && clazz.isEnum()) {
|
||||
log.debug("Class is an enum");
|
||||
return;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
|
||||
}
|
||||
|
||||
// must have fields
|
||||
PsiField[] fields = psi.getFields(clazz);
|
||||
PsiField[] fields = clazz.getFields();
|
||||
if (fields.length == 0) {
|
||||
log.debug("Class does not have any fields");
|
||||
return;
|
||||
|
||||
+2
-2
@@ -83,7 +83,7 @@ public class FieldNotUsedInToStringInspection extends AbstractToStringInspection
|
||||
|
||||
// must have fields
|
||||
PsiAdapter psi = PsiAdapterFactory.getPsiAdapter();
|
||||
PsiField[] fields = psi.getFields(clazz);
|
||||
PsiField[] fields = clazz.getFields();
|
||||
if (fields.length == 0) {
|
||||
log.debug("Class does not have any fields");
|
||||
return;
|
||||
@@ -181,7 +181,7 @@ public class FieldNotUsedInToStringInspection extends AbstractToStringInspection
|
||||
}
|
||||
|
||||
// must have methods
|
||||
PsiMethod[] methods = psi.getMethods(clazz);
|
||||
PsiMethod[] methods = clazz.getMethods();
|
||||
if (methods.length == 0) {
|
||||
log.debug("Class does not have any methods");
|
||||
return;
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -39,16 +40,6 @@ public abstract class PsiAdapter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's the fields for the class.
|
||||
*
|
||||
* @param clazz class.
|
||||
* @return the fields for the class. If the class doesn't have any fields the array's size is 0.
|
||||
*/
|
||||
public PsiField[] getFields(PsiClass clazz) {
|
||||
return clazz.getFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the class for the given element.
|
||||
* <p/>
|
||||
* Will look in the element's parent hieracy.
|
||||
@@ -271,116 +262,6 @@ public abstract class PsiAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>transient</code> modifier?
|
||||
* <p/>eg: <code>private transient String myField;</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierTransient(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.TRANSIENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>volatile</code> modifier?
|
||||
* <p/>eg: <code>private volatile Image screen;</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierVolatile(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.VOLATILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>public</code> modifier?
|
||||
* <p/>eg: <code>public String myField;</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierPublic(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.PUBLIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>protected</code> modifier?
|
||||
* <p/>eg: <code>public String myField;</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierProtected(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.PROTECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>package-local</code> modifier?
|
||||
* <p/>eg: <code>String myField;</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierPackageLocal(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.PACKAGE_LOCAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>private</code> modifier?
|
||||
* <p/>eg: <code>private static String myField;</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierPrivate(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>abstract</code> modifier?
|
||||
* <p/>eg: <code>public abstract String getConfiguration()</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierAbstract(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>final</code> modifier?
|
||||
* <p/>eg: <code>final static boolean DEBUG = false;</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierFinal(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.FINAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>static</code> modifier?
|
||||
* <p/>eg: <code>private static String getMyField()</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierStatic(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.STATIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a <code>synchronized</code> modifier?
|
||||
* <p/>eg: <code>public synchronized void putInCache()</code>.
|
||||
*
|
||||
* @param modifiers the modifiers
|
||||
*/
|
||||
public boolean isModifierSynchronized(PsiModifierList modifiers) {
|
||||
return modifiers.hasModifierProperty(PsiModifier.SYNCHRONIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's the CodeStyleManager for the project.
|
||||
*
|
||||
* @param project project.
|
||||
* @return the CodeStyleManager.
|
||||
*/
|
||||
public CodeStyleManager getCodeStyleManager(Project project) {
|
||||
return CodeStyleManager.getInstance(project);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the javafile have the import statement?
|
||||
*
|
||||
@@ -592,17 +473,7 @@ public abstract class PsiAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's the methods for the class.
|
||||
*
|
||||
* @param clazz class.
|
||||
* @return the methods for the class. If the class doesn't have any methods the array's size is 0.
|
||||
*/
|
||||
public PsiMethod[] getMethods(PsiClass clazz) {
|
||||
return clazz.getMethods();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Find's an existing field with the given name.
|
||||
* If there isn't a field with the name, null is returned.
|
||||
*
|
||||
@@ -725,38 +596,8 @@ public abstract class PsiAdapter {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isEnumClass(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the class is enum (JDK1.5).
|
||||
*
|
||||
* @param clazz class to check if it's a enum
|
||||
* @return true if enum.
|
||||
*/
|
||||
public boolean isEnumClass(PsiClass clazz) {
|
||||
return clazz.isEnum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the class is deprecated.
|
||||
*
|
||||
* @param clazz class to check if it's deprecated
|
||||
* @return true if deprecated.
|
||||
*/
|
||||
public boolean isDeprecatedClass(PsiClass clazz) {
|
||||
return clazz.isDeprecated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the method is deprecated.
|
||||
*
|
||||
* @param method method to check if it's deprecated
|
||||
* @return true if deprecated.
|
||||
*/
|
||||
public boolean isDeprecatedMethod(PsiMethod method) {
|
||||
return method.isDeprecated();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the class an exception - extends Throwable (will check super).
|
||||
@@ -764,17 +605,8 @@ public abstract class PsiAdapter {
|
||||
* @param clazz class to check.
|
||||
* @return true if class is an exception.
|
||||
*/
|
||||
public boolean isExceptionClass(PsiClass clazz) {
|
||||
PsiClass[] supers = clazz.getSupers();
|
||||
for (PsiClass sup : supers) {
|
||||
if ("java.lang.Throwable".equals(sup.getQualifiedName())) {
|
||||
return true;
|
||||
} else if (isExceptionClass(sup)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
public static boolean isExceptionClass(PsiClass clazz) {
|
||||
return InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -788,7 +620,7 @@ public abstract class PsiAdapter {
|
||||
if (list == null) {
|
||||
return false;
|
||||
}
|
||||
return isModifierAbstract(clazz.getModifierList());
|
||||
return clazz.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
def <error descr="foo(String, int) already defined">foo</error>(String s = "a", int i, double y = 4) {
|
||||
def <error descr="foo(String, int) is already defined">foo</error>(String s = "a", int i, double y = 4) {
|
||||
|
||||
}
|
||||
|
||||
def foo(int i, double y) {}
|
||||
|
||||
def <error descr="foo(String, int) already defined">foo</error>(String s, int i) {}
|
||||
def <error descr="foo(String, int) is already defined">foo</error>(String s, int i) {}
|
||||
|
||||
def foo(String s, double y){}
|
||||
+16
-6
@@ -88,7 +88,7 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
|
||||
private static final Map<Language, SpellcheckingStrategy> factories = new HashMap<Language, SpellcheckingStrategy>();
|
||||
|
||||
private static void ensureFactoriesAreLoaded() {
|
||||
public static void ensureFactoriesAreLoaded() {
|
||||
synchronized (factories) {
|
||||
if (!factories.isEmpty()) return;
|
||||
final SpellcheckingStrategy[] spellcheckingStrategies = Extensions.getExtensions(SpellcheckingStrategy.EP_NAME);
|
||||
@@ -146,11 +146,8 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
}
|
||||
}
|
||||
|
||||
final SpellcheckingStrategy factoryByLanguage = getFactoryByLanguage(language);
|
||||
final Tokenizer tokenizer = factoryByLanguage.getTokenizer(element);
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
final Token[] tokens = tokenizer.tokenize(element);
|
||||
final Token[] tokens = tokenize(element, language);
|
||||
if (tokens == null) return;
|
||||
|
||||
Set<String> alreadyChecked = new THashSet<String>();
|
||||
@@ -161,6 +158,19 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits element text in tokens according to spell checker strategy of given language
|
||||
* @param element Psi element
|
||||
* @param language Usually element.getLanguage()
|
||||
* @return tokens array
|
||||
*/
|
||||
@Nullable
|
||||
public static Token[] tokenize(@NotNull final PsiElement element, @NotNull final Language language) {
|
||||
final SpellcheckingStrategy factoryByLanguage = getFactoryByLanguage(language);
|
||||
final Tokenizer tokenizer = factoryByLanguage.getTokenizer(element);
|
||||
return tokenizer.tokenize(element);
|
||||
}
|
||||
|
||||
|
||||
private static void inspect(Token token, ProblemsHolder holder, boolean isOnTheFly,@NotNull Set<String> alreadyChecked, @NotNull SpellCheckerManager manager, NamesValidator... validators) {
|
||||
List<CheckArea> areaList = token.getAreas();
|
||||
@@ -253,7 +263,7 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
return validators;
|
||||
}
|
||||
|
||||
private static boolean isKeyword(NamesValidator[] validators, PsiElement element, String word) {
|
||||
public static boolean isKeyword(NamesValidator[] validators, PsiElement element, String word) {
|
||||
if (validators == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
rubymine
|
||||
noinspection
|
||||
noinspections
|
||||
impl
|
||||
@@ -106,4 +107,5 @@ utf
|
||||
stylesheet
|
||||
charset
|
||||
vertices
|
||||
|
||||
commandline
|
||||
cmdline
|
||||
|
||||
@@ -553,7 +553,7 @@ public class TestNGUtil implements TestFramework
|
||||
}
|
||||
|
||||
public static boolean isTestngXML(final VirtualFile virtualFile) {
|
||||
if (virtualFile.getName().endsWith("xml")) {
|
||||
if ("xml".equalsIgnoreCase(virtualFile.getExtension())) {
|
||||
final String result = NanoXmlUtil.parseHeader(virtualFile).getRootTagLocalName();
|
||||
if (result != null && result.equals(SUITE_TAG_NAME)) {
|
||||
return true;
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.intellij.uiDesigner.lw.IComponent;
|
||||
import com.intellij.uiDesigner.lw.IProperty;
|
||||
import com.intellij.uiDesigner.lw.LwRootContainer;
|
||||
import com.intellij.uiDesigner.palette.ComponentItem;
|
||||
import com.intellij.uiDesigner.propertyInspector.PropertyInspector;
|
||||
import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager;
|
||||
import com.intellij.uiDesigner.propertyInspector.properties.IntroStringProperty;
|
||||
import com.intellij.uiDesigner.radComponents.RadComponent;
|
||||
@@ -465,7 +466,8 @@ public final class GuiEditor extends JPanel implements DataProvider {
|
||||
|
||||
// Standard Swing cut/copy/paste actions should work if user is editing something inside property inspector
|
||||
final UIDesignerToolWindowManager manager = UIDesignerToolWindowManager.getInstance(getProject());
|
||||
if (manager.getPropertyInspector().isEditing()) {
|
||||
final PropertyInspector inspector = manager.getPropertyInspector();
|
||||
if (inspector != null && inspector.isEditing()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -16,19 +16,20 @@
|
||||
package com.intellij.uiDesigner.designSurface;
|
||||
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.uiDesigner.radComponents.RadRootContainer;
|
||||
import com.intellij.uiDesigner.FormEditingUtil;
|
||||
import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager;
|
||||
import com.intellij.uiDesigner.componentTree.ComponentTree;
|
||||
import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager;
|
||||
import com.intellij.uiDesigner.radComponents.RadButtonGroup;
|
||||
import com.intellij.uiDesigner.radComponents.RadComponent;
|
||||
import com.intellij.uiDesigner.radComponents.RadRootContainer;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Decoration layer is over COMPONENT_LAYER (layer where all components are located).
|
||||
@@ -56,7 +57,9 @@ class PassiveDecorationLayer extends JComponent{
|
||||
final Set<RadButtonGroup> paintedGroups = new HashSet<RadButtonGroup>();
|
||||
final RadRootContainer rootContainer = myEditor.getRootContainer();
|
||||
final ComponentTree componentTree = UIDesignerToolWindowManager.getInstance(component.getProject()).getComponentTree();
|
||||
final Collection<RadButtonGroup> selectedGroups = componentTree.getSelectedElements(RadButtonGroup.class);
|
||||
final Collection<RadButtonGroup> selectedGroups = componentTree != null
|
||||
? componentTree.getSelectedElements(RadButtonGroup.class)
|
||||
: Collections.<RadButtonGroup>emptyList();
|
||||
|
||||
// Paint selection and dragger
|
||||
FormEditingUtil.iterate(
|
||||
|
||||
+5
-5
@@ -121,8 +121,8 @@ class XmlZenCodingInterpreter {
|
||||
case OPERATION:
|
||||
if (templateToken != null) {
|
||||
if (token instanceof MarkerToken || token instanceof OperationToken) {
|
||||
final char sign = token instanceof OperationToken ? ((OperationToken)token).mySign : XmlZenCodingTemplate.MARKER;
|
||||
if (sign == '+' || (mySurroundedText == null && sign == XmlZenCodingTemplate.MARKER)) {
|
||||
final char sign = token instanceof OperationToken ? ((OperationToken)token).mySign : ZenCodingTemplate.MARKER;
|
||||
if (sign == '+' || (mySurroundedText == null && sign == ZenCodingTemplate.MARKER)) {
|
||||
final Object key = new Object();
|
||||
myCallback.fixStartOfTemplate(key);
|
||||
invokeTemplate(templateToken, myCallback, 0);
|
||||
@@ -135,7 +135,7 @@ class XmlZenCodingInterpreter {
|
||||
}
|
||||
templateToken = null;
|
||||
}
|
||||
else if (sign == '>' || (mySurroundedText != null && sign == XmlZenCodingTemplate.MARKER)) {
|
||||
else if (sign == '>' || (mySurroundedText != null && sign == ZenCodingTemplate.MARKER)) {
|
||||
startTemplateAndGotoChild(templateToken);
|
||||
templateToken = null;
|
||||
}
|
||||
@@ -168,8 +168,8 @@ class XmlZenCodingInterpreter {
|
||||
break;
|
||||
case AFTER_NUMBER:
|
||||
if (token instanceof MarkerToken || token instanceof OperationToken) {
|
||||
char sign = token instanceof OperationToken ? ((OperationToken)token).mySign : XmlZenCodingTemplate.MARKER;
|
||||
if (sign == '+' || (mySurroundedText == null && sign == XmlZenCodingTemplate.MARKER)) {
|
||||
char sign = token instanceof OperationToken ? ((OperationToken)token).mySign : ZenCodingTemplate.MARKER;
|
||||
if (sign == '+' || (mySurroundedText == null && sign == ZenCodingTemplate.MARKER)) {
|
||||
invokeTemplateSeveralTimes(templateToken, 0, number);
|
||||
templateToken = null;
|
||||
}
|
||||
|
||||
+75
-286
@@ -15,60 +15,38 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.template.zencoding;
|
||||
|
||||
import com.intellij.application.options.editor.WebEditorOptions;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.template.CustomLiveTemplate;
|
||||
import com.intellij.codeInsight.template.CustomTemplateCallback;
|
||||
import com.intellij.codeInsight.template.TemplateInvokationListener;
|
||||
import com.intellij.codeInsight.template.impl.TemplateImpl;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.lang.xml.XMLLanguage;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorModificationUtil;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.ui.InputValidatorEx;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.*;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.xml.XmlBundle;
|
||||
import org.apache.xerces.util.XML11Char;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class XmlZenCodingTemplate implements CustomLiveTemplate {
|
||||
static final char MARKER = '$';
|
||||
private static final String OPERATIONS = ">+*";
|
||||
public class XmlZenCodingTemplate extends ZenCodingTemplate {
|
||||
private static final String SELECTORS = ".#[";
|
||||
private static final String ID = "id";
|
||||
private static final String CLASS = "class";
|
||||
|
||||
private static int parseNonNegativeInt(@NotNull String s) {
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
catch (Throwable ignored) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private static final String DEFAULT_TAG = "div";
|
||||
|
||||
private static String getPrefix(@NotNull String templateKey) {
|
||||
for (int i = 0, n = templateKey.length(); i < n; i++) {
|
||||
@@ -183,187 +161,59 @@ public class XmlZenCodingTemplate implements CustomLiveTemplate {
|
||||
return type == StdFileTypes.XHTML || type == StdFileTypes.JSPX || type == StdFileTypes.XML;
|
||||
}
|
||||
|
||||
private static boolean isHtml(CustomTemplateCallback callback) {
|
||||
FileType type = callback.getFileType();
|
||||
return type == StdFileTypes.HTML || type == StdFileTypes.XHTML;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
private static List<Token> parse(@NotNull String text, @NotNull CustomTemplateCallback callback) {
|
||||
text += MARKER;
|
||||
StringBuilder templateKeyBuilder = new StringBuilder();
|
||||
List<Token> result = new ArrayList<Token>();
|
||||
for (int i = 0, n = text.length(); i < n; i++) {
|
||||
char c = text.charAt(i);
|
||||
if (i == n - 1 || (i < n - 2 && OPERATIONS.indexOf(c) >= 0)) {
|
||||
String key = templateKeyBuilder.toString();
|
||||
templateKeyBuilder = new StringBuilder();
|
||||
int num = parseNonNegativeInt(key);
|
||||
if (num > 0) {
|
||||
result.add(new NumberToken(num));
|
||||
}
|
||||
else {
|
||||
if (key.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
String prefix = getPrefix(key);
|
||||
TemplateImpl template = callback.findApplicableTemplate(prefix);
|
||||
if (template == null && !isXML11ValidQName(prefix)) {
|
||||
return null;
|
||||
}
|
||||
TemplateToken token = parseSelectors(key);
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
if (template != null && (token.myAttribute2Value.size() > 0 || isTrueXml(callback))) {
|
||||
assert prefix.equals(token.myKey);
|
||||
token.myTemplate = template;
|
||||
if (token.myAttribute2Value.size() > 0) {
|
||||
XmlTag tag = parseXmlTagInTemplate(template.getString(), callback, false);
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.add(token);
|
||||
}
|
||||
result.add(i < n - 1 ? new OperationToken(c) : new MarkerToken());
|
||||
}
|
||||
else if (!Character.isWhitespace(c)) {
|
||||
templateKeyBuilder.append(c);
|
||||
}
|
||||
else {
|
||||
protected TemplateToken parseTemplateKey(String key, CustomTemplateCallback callback) {
|
||||
String prefix = getPrefix(key);
|
||||
boolean useDefaultTag = false;
|
||||
if (prefix.length() == 0) {
|
||||
if (!isHtml(callback)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean check(@NotNull Collection<Token> tokens) {
|
||||
State state = State.WORD;
|
||||
for (Token token : tokens) {
|
||||
if (token instanceof MarkerToken) {
|
||||
break;
|
||||
}
|
||||
switch (state) {
|
||||
case OPERATION:
|
||||
if (token instanceof OperationToken) {
|
||||
state = ((OperationToken)token).mySign == '*' ? State.NUMBER : State.WORD;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case WORD:
|
||||
if (token instanceof TemplateToken) {
|
||||
state = State.OPERATION;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case NUMBER:
|
||||
if (token instanceof NumberToken) {
|
||||
state = State.AFTER_NUMBER;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case AFTER_NUMBER:
|
||||
if (token instanceof OperationToken && ((OperationToken)token).mySign != '*') {
|
||||
state = State.WORD;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
else {
|
||||
useDefaultTag = true;
|
||||
prefix = DEFAULT_TAG;
|
||||
key = prefix + key;
|
||||
}
|
||||
}
|
||||
return state == State.OPERATION || state == State.AFTER_NUMBER;
|
||||
}
|
||||
|
||||
private static String computeKey(Editor editor, int startOffset) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
String s = editor.getDocument().getCharsSequence().subSequence(startOffset, offset).toString();
|
||||
int index = 0;
|
||||
while (index < s.length() && Character.isWhitespace(s.charAt(index))) {
|
||||
index++;
|
||||
TemplateImpl template = callback.findApplicableTemplate(prefix);
|
||||
if (template == null && !isXML11ValidQName(prefix)) {
|
||||
return null;
|
||||
}
|
||||
String key = s.substring(index);
|
||||
int lastWhitespaceIndex = -1;
|
||||
for (int i = 0; i < key.length(); i++) {
|
||||
if (Character.isWhitespace(key.charAt(i))) {
|
||||
lastWhitespaceIndex = i;
|
||||
}
|
||||
TemplateToken token = parseSelectors(key);
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
if (lastWhitespaceIndex >= 0 && lastWhitespaceIndex < key.length() - 1) {
|
||||
return key.substring(lastWhitespaceIndex + 1);
|
||||
if (useDefaultTag && token.myAttribute2Value.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
|
||||
return computeKey(callback);
|
||||
}
|
||||
|
||||
static String computeKey(CustomTemplateCallback callback) {
|
||||
Editor editor = callback.getEditor();
|
||||
PsiElement element = callback.getContext();
|
||||
int line = editor.getCaretModel().getLogicalPosition().line;
|
||||
int lineStart = editor.getDocument().getLineStartOffset(line);
|
||||
int parentStart;
|
||||
do {
|
||||
parentStart = element != null ? element.getTextRange().getStartOffset() : 0;
|
||||
int startOffset = parentStart > lineStart ? parentStart : lineStart;
|
||||
String key = computeKey(editor, startOffset);
|
||||
if (checkTemplateKey(key, callback)) {
|
||||
return key;
|
||||
}
|
||||
if (element != null) {
|
||||
element = element.getParent();
|
||||
}
|
||||
}
|
||||
while (element != null && parentStart > lineStart);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean checkTemplateKey(String key, CustomTemplateCallback callback) {
|
||||
List<Token> tokens = parse(key, callback);
|
||||
if (tokens != null && check(tokens)) {
|
||||
// !! required if Zen Coding if invoked by TemplateManagerImpl action
|
||||
/*if (tokens.size() == 2) {
|
||||
Token token = tokens.get(0);
|
||||
if (token instanceof TemplateToken) {
|
||||
if (key.equals(((TemplateToken)token).myKey) && callback.isLiveTemplateApplicable(key)) {
|
||||
// do not activate only live template
|
||||
return null;
|
||||
}
|
||||
if (template != null && (token.myAttribute2Value.size() > 0 || isTrueXml(callback))) {
|
||||
assert prefix.equals(token.myKey);
|
||||
token.myTemplate = template;
|
||||
if (token.myAttribute2Value.size() > 0) {
|
||||
XmlTag tag = parseXmlTagInTemplate(template.getString(), callback, false);
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isApplicable(PsiFile file, int offset, boolean selection) {
|
||||
return isApplicable(file, offset);
|
||||
}
|
||||
|
||||
private static boolean isApplicable(PsiFile file, int offset) {
|
||||
WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
|
||||
if (!webEditorOptions.isZenCodingEnabled()) {
|
||||
return false;
|
||||
}
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
|
||||
PsiElement element = null;
|
||||
if (!InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) {
|
||||
element = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset);
|
||||
}
|
||||
if (element == null) {
|
||||
element = file.findElementAt(offset > 0 ? offset - 1 : offset);
|
||||
if (element == null) {
|
||||
element = file;
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static XmlTag parseXmlTagInTemplate(String templateString, CustomTemplateCallback callback, boolean createPhysicalFile) {
|
||||
XmlFile xmlFile = (XmlFile)PsiFileFactory.getInstance(callback.getProject())
|
||||
.createFileFromText("dummy.xml", StdFileTypes.XML, templateString, LocalTimeCounter.currentTime(), createPhysicalFile);
|
||||
XmlDocument document = xmlFile.getDocument();
|
||||
return document == null ? null : document.getRootTag();
|
||||
}
|
||||
|
||||
protected boolean isApplicable(@NotNull PsiElement element) {
|
||||
if (element.getLanguage() instanceof XMLLanguage) {
|
||||
if (PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class) != null) {
|
||||
return false;
|
||||
@@ -376,111 +226,25 @@ public class XmlZenCodingTemplate implements CustomLiveTemplate {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void expand(String key, @NotNull CustomTemplateCallback callback) {
|
||||
expand(key, callback, null);
|
||||
}
|
||||
|
||||
private static void expand(String key,
|
||||
@NotNull CustomTemplateCallback callback,
|
||||
String surroundedText) {
|
||||
List<Token> tokens = parse(key, callback);
|
||||
assert tokens != null;
|
||||
if (surroundedText == null) {
|
||||
if (tokens.size() == 2) {
|
||||
Token token = tokens.get(0);
|
||||
if (token instanceof TemplateToken) {
|
||||
if (key.equals(((TemplateToken)token).myKey) && callback.findApplicableTemplates(key).size() > 1) {
|
||||
callback.startTemplate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
callback.deleteTemplateKey(key);
|
||||
}
|
||||
XmlZenCodingInterpreter.interpret(tokens, 0, callback, State.WORD, surroundedText);
|
||||
}
|
||||
|
||||
public void wrap(final String selection,
|
||||
@NotNull final CustomTemplateCallback callback,
|
||||
@Nullable final TemplateInvokationListener listener) {
|
||||
InputValidatorEx validator = new InputValidatorEx() {
|
||||
public String getErrorText(String inputString) {
|
||||
if (!checkTemplateKey(inputString, callback)) {
|
||||
return XmlBundle.message("zen.coding.incorrect.abbreviation.error");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean checkInput(String inputString) {
|
||||
return getErrorText(inputString) == null;
|
||||
}
|
||||
|
||||
public boolean canClose(String inputString) {
|
||||
return checkInput(inputString);
|
||||
}
|
||||
};
|
||||
final String abbreviation = Messages
|
||||
.showInputDialog(callback.getProject(), XmlBundle.message("zen.coding.enter.abbreviation.dialog.label"),
|
||||
XmlBundle.message("zen.coding.title"), Messages.getQuestionIcon(), "", validator);
|
||||
if (abbreviation != null) {
|
||||
doWrap(selection, abbreviation, callback, listener);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doWrap(final String selection,
|
||||
final String abbreviation,
|
||||
final CustomTemplateCallback callback,
|
||||
final TemplateInvokationListener listener) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
CommandProcessor.getInstance().executeCommand(callback.getProject(), new Runnable() {
|
||||
public void run() {
|
||||
EditorModificationUtil.deleteSelectedText(callback.getEditor());
|
||||
PsiDocumentManager.getInstance(callback.getProject()).commitAllDocuments();
|
||||
callback.fixInitialState();
|
||||
expand(abbreviation, callback, selection);
|
||||
if (listener != null) {
|
||||
listener.finished();
|
||||
}
|
||||
}
|
||||
}, CodeInsightBundle.message("insert.code.template.command"), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getTitle() {
|
||||
return XmlBundle.message("zen.coding.title");
|
||||
}
|
||||
|
||||
public char getShortcut() {
|
||||
return (char)WebEditorOptions.getInstance().getZenCodingExpandShortcut();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static XmlTag parseXmlTagInTemplate(String templateString, CustomTemplateCallback callback, boolean createPhysicalFile) {
|
||||
XmlFile xmlFile = (XmlFile)PsiFileFactory.getInstance(callback.getProject())
|
||||
.createFileFromText("dummy.xml", StdFileTypes.XML, templateString, LocalTimeCounter.currentTime(), createPhysicalFile);
|
||||
XmlDocument document = xmlFile.getDocument();
|
||||
return document == null ? null : document.getRootTag();
|
||||
}
|
||||
|
||||
public static boolean startZenCoding(Editor editor, PsiFile file, String abbreviation) {
|
||||
int caretAt = editor.getCaretModel().getOffset();
|
||||
if (isApplicable(file, caretAt)) {
|
||||
XmlZenCodingTemplate template = CustomLiveTemplate.EP_NAME.findExtension(XmlZenCodingTemplate.class);
|
||||
if (abbreviation != null && !template.supportsWrapping()) {
|
||||
return false;
|
||||
}
|
||||
if (template.isApplicable(file, caretAt)) {
|
||||
final CustomTemplateCallback callback = new CustomTemplateCallback(editor, file);
|
||||
if (abbreviation != null) {
|
||||
String selection = callback.getEditor().getSelectionModel().getSelectedText();
|
||||
assert selection != null;
|
||||
selection = selection.trim();
|
||||
doWrap(selection, abbreviation, callback, new TemplateInvokationListener() {
|
||||
template.doWrap(selection, abbreviation, callback, new TemplateInvokationListener() {
|
||||
public void finished() {
|
||||
callback.startAllExpandedTemplates();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
XmlZenCodingTemplate template = new XmlZenCodingTemplate();
|
||||
String key = template.computeTemplateKey(callback);
|
||||
if (key != null) {
|
||||
template.expand(key, callback);
|
||||
@@ -494,4 +258,29 @@ public class XmlZenCodingTemplate implements CustomLiveTemplate {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
|
||||
Editor editor = callback.getEditor();
|
||||
PsiElement element = callback.getContext();
|
||||
int line = editor.getCaretModel().getLogicalPosition().line;
|
||||
int lineStart = editor.getDocument().getLineStartOffset(line);
|
||||
int elementStart;
|
||||
do {
|
||||
elementStart = element != null ? element.getTextRange().getStartOffset() : 0;
|
||||
int startOffset = elementStart > lineStart ? elementStart : lineStart;
|
||||
String key = computeKey(editor, startOffset);
|
||||
if (checkTemplateKey(key, callback)) {
|
||||
return key;
|
||||
}
|
||||
if (element != null) {
|
||||
element = element.getParent();
|
||||
}
|
||||
}
|
||||
while (element != null && elementStart > lineStart);
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean supportsWrapping() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.codeInsight.template.zencoding;
|
||||
|
||||
import com.intellij.application.options.editor.WebEditorOptions;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.template.CustomLiveTemplate;
|
||||
import com.intellij.codeInsight.template.CustomTemplateCallback;
|
||||
import com.intellij.codeInsight.template.TemplateInvokationListener;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorModificationUtil;
|
||||
import com.intellij.openapi.ui.InputValidatorEx;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.xml.XmlBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public abstract class ZenCodingTemplate implements CustomLiveTemplate {
|
||||
static final char MARKER = '$';
|
||||
private static final String OPERATIONS = ">+*";
|
||||
|
||||
private static int parseNonNegativeInt(@NotNull String s) {
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
catch (Throwable ignored) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<Token> parse(@NotNull String text, @NotNull CustomTemplateCallback callback) {
|
||||
text += MARKER;
|
||||
StringBuilder templateKeyBuilder = new StringBuilder();
|
||||
List<Token> result = new ArrayList<Token>();
|
||||
for (int i = 0, n = text.length(); i < n; i++) {
|
||||
char c = text.charAt(i);
|
||||
if (i == n - 1 || (i < n - 2 && OPERATIONS.indexOf(c) >= 0)) {
|
||||
String key = templateKeyBuilder.toString();
|
||||
templateKeyBuilder = new StringBuilder();
|
||||
int num = parseNonNegativeInt(key);
|
||||
if (num > 0) {
|
||||
result.add(new NumberToken(num));
|
||||
}
|
||||
else {
|
||||
TemplateToken token = parseTemplateKey(key, callback);
|
||||
if (token == null) return null;
|
||||
result.add(token);
|
||||
}
|
||||
result.add(i < n - 1 ? new OperationToken(c) : new MarkerToken());
|
||||
}
|
||||
else if (!Character.isWhitespace(c)) {
|
||||
templateKeyBuilder.append(c);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract TemplateToken parseTemplateKey(String key, CustomTemplateCallback callback);
|
||||
|
||||
private static boolean check(@NotNull Collection<Token> tokens) {
|
||||
State state = State.WORD;
|
||||
for (Token token : tokens) {
|
||||
if (token instanceof MarkerToken) {
|
||||
break;
|
||||
}
|
||||
switch (state) {
|
||||
case OPERATION:
|
||||
if (token instanceof OperationToken) {
|
||||
state = ((OperationToken)token).mySign == '*' ? State.NUMBER : State.WORD;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case WORD:
|
||||
if (token instanceof TemplateToken) {
|
||||
state = State.OPERATION;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case NUMBER:
|
||||
if (token instanceof NumberToken) {
|
||||
state = State.AFTER_NUMBER;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case AFTER_NUMBER:
|
||||
if (token instanceof OperationToken && ((OperationToken)token).mySign != '*') {
|
||||
state = State.WORD;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return state == State.OPERATION || state == State.AFTER_NUMBER;
|
||||
}
|
||||
|
||||
protected static String computeKey(Editor editor, int startOffset) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
String s = editor.getDocument().getCharsSequence().subSequence(startOffset, offset).toString();
|
||||
int index = 0;
|
||||
while (index < s.length() && Character.isWhitespace(s.charAt(index))) {
|
||||
index++;
|
||||
}
|
||||
String key = s.substring(index);
|
||||
int lastWhitespaceIndex = -1;
|
||||
for (int i = 0; i < key.length(); i++) {
|
||||
if (Character.isWhitespace(key.charAt(i))) {
|
||||
lastWhitespaceIndex = i;
|
||||
}
|
||||
}
|
||||
if (lastWhitespaceIndex >= 0 && lastWhitespaceIndex < key.length() - 1) {
|
||||
return key.substring(lastWhitespaceIndex + 1);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
protected boolean checkTemplateKey(String key, CustomTemplateCallback callback) {
|
||||
List<Token> tokens = parse(key, callback);
|
||||
if (tokens != null && check(tokens)) {
|
||||
// !! required if Zen Coding if invoked by TemplateManagerImpl action
|
||||
/*if (tokens.size() == 2) {
|
||||
Token token = tokens.get(0);
|
||||
if (token instanceof TemplateToken) {
|
||||
if (key.equals(((TemplateToken)token).myKey) && callback.isLiveTemplateApplicable(key)) {
|
||||
// do not activate only live template
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void expand(String key, @NotNull CustomTemplateCallback callback) {
|
||||
expand(key, callback, null);
|
||||
}
|
||||
|
||||
private void expand(String key,
|
||||
@NotNull CustomTemplateCallback callback,
|
||||
String surroundedText) {
|
||||
List<Token> tokens = parse(key, callback);
|
||||
assert tokens != null;
|
||||
if (surroundedText == null) {
|
||||
if (tokens.size() == 2) {
|
||||
Token token = tokens.get(0);
|
||||
if (token instanceof TemplateToken) {
|
||||
if (key.equals(((TemplateToken)token).myKey) && callback.findApplicableTemplates(key).size() > 1) {
|
||||
callback.startTemplate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
callback.deleteTemplateKey(key);
|
||||
}
|
||||
XmlZenCodingInterpreter.interpret(tokens, 0, callback, State.WORD, surroundedText);
|
||||
}
|
||||
|
||||
public void wrap(final String selection,
|
||||
@NotNull final CustomTemplateCallback callback,
|
||||
@Nullable final TemplateInvokationListener listener) {
|
||||
InputValidatorEx validator = new InputValidatorEx() {
|
||||
public String getErrorText(String inputString) {
|
||||
if (!checkTemplateKey(inputString, callback)) {
|
||||
return XmlBundle.message("zen.coding.incorrect.abbreviation.error");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean checkInput(String inputString) {
|
||||
return getErrorText(inputString) == null;
|
||||
}
|
||||
|
||||
public boolean canClose(String inputString) {
|
||||
return checkInput(inputString);
|
||||
}
|
||||
};
|
||||
final String abbreviation = Messages
|
||||
.showInputDialog(callback.getProject(), XmlBundle.message("zen.coding.enter.abbreviation.dialog.label"),
|
||||
XmlBundle.message("zen.coding.title"), Messages.getQuestionIcon(), "", validator);
|
||||
if (abbreviation != null) {
|
||||
doWrap(selection, abbreviation, callback, listener);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isApplicable(PsiFile file, int offset) {
|
||||
WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
|
||||
if (!webEditorOptions.isZenCodingEnabled()) {
|
||||
return false;
|
||||
}
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
|
||||
PsiElement element = CustomTemplateCallback.getContext(file, offset);
|
||||
return isApplicable(element);
|
||||
}
|
||||
|
||||
protected abstract boolean isApplicable(@NotNull PsiElement element);
|
||||
|
||||
protected void doWrap(final String selection,
|
||||
final String abbreviation,
|
||||
final CustomTemplateCallback callback,
|
||||
final TemplateInvokationListener listener) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
CommandProcessor.getInstance().executeCommand(callback.getProject(), new Runnable() {
|
||||
public void run() {
|
||||
EditorModificationUtil.deleteSelectedText(callback.getEditor());
|
||||
PsiDocumentManager.getInstance(callback.getProject()).commitAllDocuments();
|
||||
callback.fixInitialState();
|
||||
expand(abbreviation, callback, selection);
|
||||
if (listener != null) {
|
||||
listener.finished();
|
||||
}
|
||||
}
|
||||
}, CodeInsightBundle.message("insert.code.template.command"), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getTitle() {
|
||||
return XmlBundle.message("zen.coding.title");
|
||||
}
|
||||
|
||||
public char getShortcut() {
|
||||
return (char)WebEditorOptions.getInstance().getZenCodingExpandShortcut();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user