Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2012-06-02 17:12:26 +02:00
38 changed files with 946 additions and 436 deletions
@@ -857,12 +857,13 @@ public class AsmCodeGenerator {
}
pushBorderProperties(container, generator, borderTitle, componentLocal);
if (Boolean.valueOf(System.getProperty("idea.is.internal")).booleanValue()) {
container.getDelegeeClientProperties().put(ourBorderFactoryClientProperty, StringDescriptor.create("com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"));
}
Type borderFactoryType = ourBorderFactoryType;
StringDescriptor borderFactoryValue = (StringDescriptor)container.getDelegeeClientProperties().get(ourBorderFactoryClientProperty);
if (borderFactoryValue == null && Boolean.valueOf(System.getProperty("idea.is.internal")).booleanValue()) {
borderFactoryValue = StringDescriptor.create("com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent");
container.getDelegeeClientProperties().put(ourBorderFactoryClientProperty, borderFactoryValue);
}
if (borderFactoryValue != null && borderFactoryValue.getValue().length() != 0) {
borderFactoryType = typeFromClassName(borderFactoryValue.getValue());
}
@@ -0,0 +1,31 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi;
import org.jetbrains.annotations.Nullable;
/**
* Represents a method or constructor reference.
*/
public interface PsiMethodReferenceExpression extends PsiReferenceExpression {
/**
* Returns the type element used as the qualifier of the reference.
*
* @return the qualifier, or null if the reference is qualified by expression.
*/
@Nullable
PsiTypeElement getQualifierType();
}
@@ -321,6 +321,7 @@ public class ExpressionParser {
private enum BreakPoint {P1, P2, P3, P4}
// todo[r.sh] make 'this', 'super' and 'class' reference expressions
@Nullable
private PsiBuilder.Marker parsePrimary(final PsiBuilder builder, @Nullable final BreakPoint breakPoint, final int breakOffset) {
PsiBuilder.Marker startMarker = builder.mark();
@@ -350,7 +351,7 @@ public class ExpressionParser {
final int offset = builder.getCurrentOffset();
startMarker.rollbackTo();
final PsiBuilder.Marker classObjAccess = parseClassObjectAccess(builder);
final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
if (classObjAccess == null || builder.getCurrentOffset() < offset) {
copy.rollbackTo();
return parsePrimary(builder, BreakPoint.P1, offset);
@@ -466,7 +467,7 @@ public class ExpressionParser {
final PsiBuilder.Marker copy = startMarker.precede();
startMarker.rollbackTo();
final PsiBuilder.Marker classObjAccess = parseClassObjectAccess(builder);
final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
if (classObjAccess == null || builder.getCurrentOffset() <= pos) {
copy.rollbackTo();
return parsePrimary(builder, BreakPoint.P4, -1);
@@ -498,6 +499,9 @@ public class ExpressionParser {
expr = arrayAccess;
}
}
else if (tokenType == JavaTokenType.DOUBLE_COLON) {
return parseMethodReference(builder, startMarker);
}
else {
startMarker.drop();
return expr;
@@ -515,6 +519,7 @@ public class ExpressionParser {
literal.done(JavaElementType.LITERAL_EXPRESSION);
return literal;
}
if (tokenType == JavaTokenType.LPARENTH) {
final PsiBuilder.Marker parenth = builder.mark();
builder.advanceLexer();
@@ -533,12 +538,25 @@ public class ExpressionParser {
parenth.done(JavaElementType.PARENTH_EXPRESSION);
return parenth;
}
if (tokenType == JavaTokenType.LBRACE) {
return parseArrayInitializer(builder);
}
if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType) || tokenType == JavaTokenType.IDENTIFIER) {
final boolean primitive = tokenType != JavaTokenType.IDENTIFIER;
final PsiBuilder.Marker mark = builder.mark();
final ReferenceParser.TypeInfo typeInfo = myReferenceParser.parseTypeInfo(builder, 0);
if (typeInfo != null && (primitive || !typeInfo.hasErrors && typeInfo.isParameterized)) {
final PsiBuilder.Marker result = continueClassAccessOrMethodReference(builder, mark, primitive);
if (result != null) return result;
}
mark.rollbackTo();
}
PsiBuilder.Marker annotation = null;
final PsiBuilder.Marker beforeAnnotation = builder.mark();
if (tokenType == JavaTokenType.AT) {
annotation = myDeclarationParser.parseAnnotations(builder);
tokenType = builder.getTokenType();
@@ -558,17 +576,13 @@ public class ExpressionParser {
builder.advanceLexer();
refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
beforeAnnotation.drop();
return refExpr;
}
if (annotation != null) {
beforeAnnotation.rollbackTo();
annotation.rollbackTo();
tokenType = builder.getTokenType();
}
else {
beforeAnnotation.drop();
}
PsiBuilder.Marker expr = null;
if (tokenType == JavaTokenType.LT) {
@@ -599,12 +613,10 @@ public class ExpressionParser {
: JavaElementType.SUPER_EXPRESSION);
return expr;
}
if (tokenType == JavaTokenType.NEW_KEYWORD) {
return parseNew(builder, null);
}
if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
return parseClassObjectAccess(builder);
}
return null;
}
@@ -745,27 +757,47 @@ public class ExpressionParser {
}
@Nullable
private PsiBuilder.Marker parseClassObjectAccess(final PsiBuilder builder) {
private PsiBuilder.Marker parseClassAccessOrMethodReference(final PsiBuilder builder) {
final PsiBuilder.Marker expr = builder.mark();
final boolean primitive = ElementType.PRIMITIVE_TYPE_BIT_SET.contains(builder.getTokenType());
if (myReferenceParser.parseType(builder, 0) == null) {
expr.drop();
return null;
}
if (builder.getTokenType() != JavaTokenType.DOT) {
expr.rollbackTo();
return null;
final PsiBuilder.Marker result = continueClassAccessOrMethodReference(builder, expr, primitive);
if (result == null) expr.rollbackTo();
return result;
}
@Nullable
private PsiBuilder.Marker continueClassAccessOrMethodReference(final PsiBuilder builder,
final PsiBuilder.Marker expr,
final boolean primitive) {
final IElementType tokenType = builder.getTokenType();
if (tokenType == JavaTokenType.DOT) {
return parseClassObjectAccess(builder, expr, primitive);
}
PsiBuilder.Marker afterType = builder.mark();
else if (tokenType == JavaTokenType.DOUBLE_COLON) {
return parseMethodReference(builder, expr);
}
return null;
}
@Nullable
private static PsiBuilder.Marker parseClassObjectAccess(PsiBuilder builder, PsiBuilder.Marker expr, boolean primitive) {
final PsiBuilder.Marker mark = builder.mark();
builder.advanceLexer();
if (builder.getTokenType() == JavaTokenType.CLASS_KEYWORD) {
afterType.drop();
mark.drop();
builder.advanceLexer();
}
else {
afterType.rollbackTo();
if (!primitive) return null;
mark.rollbackTo();
builder.error(".class expected");
}
@@ -773,6 +805,20 @@ public class ExpressionParser {
return expr;
}
@NotNull
private PsiBuilder.Marker parseMethodReference(final PsiBuilder builder, final PsiBuilder.Marker start) {
builder.advanceLexer();
myReferenceParser.parseReferenceParameterList(builder, false, false);
if (!expect(builder, JavaTokenType.IDENTIFIER) && !expect(builder, JavaTokenType.NEW_KEYWORD)) {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
start.done(JavaElementType.METHOD_REF_EXPRESSION);
return start;
}
@NotNull
public PsiBuilder.Marker parseArgumentList(final PsiBuilder builder) {
final PsiBuilder.Marker list = builder.mark();
@@ -29,13 +29,12 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
TokenSet KEYWORD_BIT_SET = TokenSet.create(
ABSTRACT_KEYWORD, ASSERT_KEYWORD, BOOLEAN_KEYWORD, BREAK_KEYWORD, BYTE_KEYWORD, CASE_KEYWORD, CATCH_KEYWORD, CHAR_KEYWORD,
CLASS_KEYWORD,
CONST_KEYWORD, CONTINUE_KEYWORD, DEFAULT_KEYWORD, DO_KEYWORD, DOUBLE_KEYWORD, ELSE_KEYWORD, ENUM_KEYWORD, EXTENDS_KEYWORD,
FINAL_KEYWORD,
FINALLY_KEYWORD, FLOAT_KEYWORD, FOR_KEYWORD, GOTO_KEYWORD, IF_KEYWORD, IMPLEMENTS_KEYWORD, IMPORT_KEYWORD, INSTANCEOF_KEYWORD,
INT_KEYWORD, INTERFACE_KEYWORD, LONG_KEYWORD, NATIVE_KEYWORD, NEW_KEYWORD, PACKAGE_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD,
PUBLIC_KEYWORD, RETURN_KEYWORD, SHORT_KEYWORD, SUPER_KEYWORD, STATIC_KEYWORD, STRICTFP_KEYWORD, SWITCH_KEYWORD, SYNCHRONIZED_KEYWORD,
THIS_KEYWORD, THROW_KEYWORD, THROWS_KEYWORD, TRANSIENT_KEYWORD, TRY_KEYWORD, VOID_KEYWORD, VOLATILE_KEYWORD, WHILE_KEYWORD);
CLASS_KEYWORD, CONST_KEYWORD, CONTINUE_KEYWORD, DEFAULT_KEYWORD, DO_KEYWORD, DOUBLE_KEYWORD, ELSE_KEYWORD, ENUM_KEYWORD,
EXTENDS_KEYWORD, FINAL_KEYWORD, FINALLY_KEYWORD, FLOAT_KEYWORD, FOR_KEYWORD, GOTO_KEYWORD, IF_KEYWORD, IMPLEMENTS_KEYWORD,
IMPORT_KEYWORD, INSTANCEOF_KEYWORD, INT_KEYWORD, INTERFACE_KEYWORD, LONG_KEYWORD, NATIVE_KEYWORD, NEW_KEYWORD, PACKAGE_KEYWORD,
PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, RETURN_KEYWORD, SHORT_KEYWORD, SUPER_KEYWORD, STATIC_KEYWORD, STRICTFP_KEYWORD,
SWITCH_KEYWORD, SYNCHRONIZED_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, THROWS_KEYWORD, TRANSIENT_KEYWORD, TRY_KEYWORD, VOID_KEYWORD,
VOLATILE_KEYWORD, WHILE_KEYWORD);
TokenSet LITERAL_BIT_SET = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD, NULL_KEYWORD);
@@ -45,33 +44,31 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
PLUSEQ, MINUSEQ, ASTERISKEQ, DIVEQ, ANDEQ, OREQ, XOREQ, PERCEQ, LTLTEQ, GTGTEQ, GTGTGTEQ);
TokenSet MODIFIER_BIT_SET = TokenSet.create(
PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, STATIC_KEYWORD, ABSTRACT_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD, SYNCHRONIZED_KEYWORD,
STRICTFP_KEYWORD, TRANSIENT_KEYWORD, VOLATILE_KEYWORD);
PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, STATIC_KEYWORD, ABSTRACT_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD,
SYNCHRONIZED_KEYWORD, STRICTFP_KEYWORD, TRANSIENT_KEYWORD, VOLATILE_KEYWORD);
TokenSet PRIMITIVE_TYPE_BIT_SET = TokenSet.create(
BOOLEAN_KEYWORD, BYTE_KEYWORD, SHORT_KEYWORD, INT_KEYWORD, LONG_KEYWORD, CHAR_KEYWORD, FLOAT_KEYWORD, DOUBLE_KEYWORD, VOID_KEYWORD);
TokenSet EXPRESSION_BIT_SET = TokenSet.create(
REFERENCE_EXPRESSION, LITERAL_EXPRESSION, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTH_EXPRESSION, METHOD_CALL_EXPRESSION,
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, POLYADIC_EXPRESSION, CONDITIONAL_EXPRESSION, ASSIGNMENT_EXPRESSION,
NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, ARRAY_INITIALIZER_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION,
EMPTY_EXPRESSION);
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, POLYADIC_EXPRESSION, CONDITIONAL_EXPRESSION,
ASSIGNMENT_EXPRESSION, NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, ARRAY_INITIALIZER_EXPRESSION, INSTANCE_OF_EXPRESSION,
CLASS_OBJECT_ACCESS_EXPRESSION, METHOD_REF_EXPRESSION, EMPTY_EXPRESSION);
TokenSet ANNOTATION_MEMBER_VALUE_BIT_SET = TokenSet.orSet(EXPRESSION_BIT_SET,
TokenSet.create(ANNOTATION, ANNOTATION_ARRAY_INITIALIZER));
TokenSet ARRAY_DIMENSION_BIT_SET = TokenSet.create(
REFERENCE_EXPRESSION, LITERAL_EXPRESSION, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTH_EXPRESSION, METHOD_CALL_EXPRESSION,
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, POLYADIC_EXPRESSION, CONDITIONAL_EXPRESSION, ASSIGNMENT_EXPRESSION,
NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION, EMPTY_EXPRESSION);
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, POLYADIC_EXPRESSION, CONDITIONAL_EXPRESSION,
ASSIGNMENT_EXPRESSION, NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION,
EMPTY_EXPRESSION);
TokenSet JAVA_STATEMENT_BIT_SET = TokenSet.create(
EMPTY_STATEMENT, BLOCK_STATEMENT, EXPRESSION_STATEMENT, EXPRESSION_LIST_STATEMENT,
DECLARATION_STATEMENT, IF_STATEMENT, WHILE_STATEMENT, FOR_STATEMENT, FOREACH_STATEMENT,
DO_WHILE_STATEMENT, SWITCH_STATEMENT, SWITCH_LABEL_STATEMENT, BREAK_STATEMENT,
CONTINUE_STATEMENT, RETURN_STATEMENT, THROW_STATEMENT, SYNCHRONIZED_STATEMENT,
TRY_STATEMENT, LABELED_STATEMENT, ASSERT_STATEMENT
);
EMPTY_STATEMENT, BLOCK_STATEMENT, EXPRESSION_STATEMENT, EXPRESSION_LIST_STATEMENT, DECLARATION_STATEMENT, IF_STATEMENT,
WHILE_STATEMENT, FOR_STATEMENT, FOREACH_STATEMENT, DO_WHILE_STATEMENT, SWITCH_STATEMENT, SWITCH_LABEL_STATEMENT, BREAK_STATEMENT,
CONTINUE_STATEMENT, RETURN_STATEMENT, THROW_STATEMENT, SYNCHRONIZED_STATEMENT, TRY_STATEMENT, LABELED_STATEMENT, ASSERT_STATEMENT);
TokenSet TYPES_BIT_SET = TokenSet.create(TYPE);
TokenSet IMPORT_STATEMENT_BIT_SET = TokenSet.create(IMPORT_STATEMENT);
@@ -79,7 +76,6 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
TokenSet IMPORT_STATEMENT_BASE_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT);
TokenSet CLASS_KEYWORD_BIT_SET = TokenSet.create(CLASS_KEYWORD, INTERFACE_KEYWORD, ENUM_KEYWORD);
TokenSet MEMBER_BIT_SET = TokenSet.create(CLASS, FIELD, ENUM_CONSTANT, METHOD, ANNOTATION_METHOD);
TokenSet FULL_MEMBER_BIT_SET = TokenSet.orSet(MEMBER_BIT_SET,
TokenSet.create(CLASS_INITIALIZER));
TokenSet FULL_MEMBER_BIT_SET = TokenSet.orSet(MEMBER_BIT_SET, TokenSet.create(CLASS_INITIALIZER));
TokenSet ANNOTATIONS = TokenSet.create(ANNOTATION);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,6 +104,7 @@ public interface JavaElementType {
IElementType INSTANCE_OF_EXPRESSION = new JavaCompositeElementType("INSTANCE_OF_EXPRESSION", PsiInstanceOfExpressionImpl.class);
IElementType CLASS_OBJECT_ACCESS_EXPRESSION = new JavaCompositeElementType("CLASS_OBJECT_ACCESS_EXPRESSION", PsiClassObjectAccessExpressionImpl.class);
IElementType EMPTY_EXPRESSION = new JavaCompositeElementType("EMPTY_EXPRESSION", PsiEmptyExpressionImpl.class, true);
IElementType METHOD_REF_EXPRESSION = new JavaCompositeElementType("METHOD_REF_EXPRESSION", PsiMethodReferenceExpressionImpl.class);
IElementType EXPRESSION_LIST = new JavaCompositeElementType("EXPRESSION_LIST", PsiExpressionListImpl.class, true);
IElementType EMPTY_STATEMENT = new JavaCompositeElementType("EMPTY_STATEMENT", PsiEmptyStatementImpl.class);
IElementType BLOCK_STATEMENT = new JavaCompositeElementType("BLOCK_STATEMENT", PsiBlockStatementImpl.class);
@@ -0,0 +1,111 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase implements PsiMethodReferenceExpression {
private static Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl");
public PsiMethodReferenceExpressionImpl() {
super(JavaElementType.METHOD_REF_EXPRESSION);
}
@Override
public PsiTypeElement getQualifierType() {
final PsiElement qualifier = getQualifier();
return qualifier instanceof PsiTypeElement ? (PsiTypeElement)qualifier : null;
}
@Override
public PsiExpression getQualifierExpression() {
final PsiElement qualifier = getQualifier();
return qualifier instanceof PsiExpression ? (PsiExpression)qualifier : null;
}
@Override
public PsiType getType() {
// todo[r.sh]: implement
return null;
}
@Override
public PsiElement getReferenceNameElement() {
final PsiElement element = getLastChild();
return element instanceof PsiIdentifier || PsiUtil.isJavaToken(element, JavaTokenType.NEW_KEYWORD) ? element : null;
}
@Override
public void processVariants(final PsiScopeProcessor processor) {
// todo[r.sh]: implement
}
@NotNull
@Override
public JavaResolveResult[] multiResolve(final boolean incompleteCode) {
// todo[r.sh]: implement
return JavaResolveResult.EMPTY_ARRAY;
}
@Override
public PsiElement getQualifier() {
final PsiElement element = getFirstChild();
return element instanceof PsiExpression || element instanceof PsiTypeElement ? element : null;
}
@Override
public TextRange getRangeInElement() {
final PsiElement element = getReferenceNameElement();
if (element != null) return new TextRange(element.getStartOffsetInParent(), element.getTextLength());
final PsiElement colons = findPsiChildByType(JavaTokenType.DOUBLE_COLON);
if (colons != null) return new TextRange(colons.getStartOffsetInParent(), colons.getTextLength());
LOG.error(getText());
return null;
}
@NotNull
@Override
public String getCanonicalText() {
return getText();
}
@Override
public boolean isReferenceTo(final PsiElement element) {
if (!(element instanceof PsiMethod)) return false;
final PsiMethod method = (PsiMethod)element;
final PsiElement nameElement = getReferenceNameElement();
if (nameElement instanceof PsiIdentifier) {
if (!nameElement.getText().equals(method.getName())) return false;
}
else if (PsiUtil.isJavaToken(nameElement, JavaTokenType.NEW_KEYWORD)) {
if (!method.isConstructor()) return false;
}
return element.getManager().areElementsEquivalent(element, resolve());
}
@Override
public String toString() {
return "PsiMethodReferenceExpression:" + getText();
}
}
@@ -0,0 +1,117 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class PsiReferenceExpressionBase extends ExpressionPsiElement implements PsiReferenceExpression {
public PsiReferenceExpressionBase(@NotNull final IElementType type) {
super(type);
}
@Override
public PsiElement bindToElementViaStaticImport(@NotNull final PsiClass qualifierClass) throws IncorrectOperationException {
throw new IncorrectOperationException();
}
@Override
public void setQualifierExpression(@Nullable PsiExpression newQualifier) throws IncorrectOperationException {
throw new IncorrectOperationException();
}
@Override
public PsiElement getElement() {
return this;
}
@Override
public PsiElement resolve() {
return advancedResolve(false).getElement();
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
throw new IncorrectOperationException();
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
throw new IncorrectOperationException();
}
@Override
public boolean isReferenceTo(final PsiElement element) {
return element.getManager().areElementsEquivalent(element, resolve());
}
@NotNull
@Override
public Object[] getVariants() {
// this reference's variants are rather obtained with processVariants()
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
@Override
public boolean isSoft() {
return false;
}
@Override
public PsiReference getReference() {
return this;
}
@NotNull
@Override
public JavaResolveResult advancedResolve(boolean incompleteCode) {
final JavaResolveResult[] results = multiResolve(incompleteCode);
return results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
}
@Override
public String getReferenceName() {
final PsiElement element = getReferenceNameElement();
return element != null ? element.getText() : null;
}
@Override
public PsiReferenceParameterList getParameterList() {
return PsiTreeUtil.getChildOfType(this, PsiReferenceParameterList.class);
}
@NotNull
@Override
public PsiType[] getTypeParameters() {
final PsiReferenceParameterList parameterList = getParameterList();
return parameterList != null ? parameterList.getTypeArguments() : PsiType.EMPTY_ARRAY;
}
@Override
public boolean isQualified() {
return getQualifier() != null;
}
@Override
public String getQualifiedName() {
return getCanonicalText();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements PsiReferenceExpression, SourceJavaCodeReference {
public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase implements PsiReferenceExpression, SourceJavaCodeReference {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl");
private volatile String myCachedQName = null;
@@ -108,7 +108,8 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
}
else {
PsiManagerEx manager = getManager();
PsiReferenceExpression classRef = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createReferenceExpression(qualifierClass);
PsiReferenceExpression classRef = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createReferenceExpression(
qualifierClass);
final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
LeafElement dot = Factory.createSingleLeafElement(JavaTokenType.DOT, ".", 0, 1, treeCharTab, manager);
addInternal(dot, dot, SourceTreeToPsiMap.psiElementToTree(getParameterList()), Boolean.TRUE);
@@ -122,7 +123,8 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
final String qualifiedName = qualifierClass.getQualifiedName();
final List<PsiJavaCodeReferenceElement> refs = getImportsFromClass(importList, qualifiedName);
if (refs.size() < JavaCodeStyleSettingsFacade.getInstance(qualifierClass.getProject()).getNamesCountToUseImportOnDemand()) {
importList.add(JavaPsiFacade.getInstance(qualifierClass.getProject()).getElementFactory().createImportStaticStatement(qualifierClass, staticName));
importList.add(JavaPsiFacade.getInstance(qualifierClass.getProject()).getElementFactory().createImportStaticStatement(qualifierClass,
staticName));
} else {
for (PsiJavaCodeReferenceElement ref : refs) {
final PsiImportStaticStatement importStatement = PsiTreeUtil.getParentOfType(ref, PsiImportStaticStatement.class);
@@ -130,7 +132,8 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
importStatement.delete();
}
}
importList.add(JavaPsiFacade.getInstance(qualifierClass.getProject()).getElementFactory().createImportStaticStatement(qualifierClass, "*"));
importList.add(JavaPsiFacade.getInstance(qualifierClass.getProject()).getElementFactory().createImportStaticStatement(qualifierClass,
"*"));
}
}
@@ -174,16 +177,6 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
return getQualifierExpression();
}
@Override
public PsiReference getReference() {
return this;
}
@Override
public PsiElement resolve() {
return advancedResolve(false).getElement();
}
@Override
public void clearCaches() {
myCachedQName = null;
@@ -316,18 +309,6 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
return getCachedTextSkipWhiteSpaceAndComments();
}
@Override
public String getQualifiedName() {
return getCanonicalText();
}
@Override
public String getReferenceName() {
PsiElement element = getReferenceNameElement();
if (element == null) return null;
return element.getText();
}
private final Function<PsiReferenceExpressionImpl, PsiType> ourTypeEvaluator = new TypeEvaluator();
private static class TypeEvaluator implements NullableFunction<PsiReferenceExpressionImpl, PsiType> {
@@ -409,20 +390,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
// optimization: methodCallExpression should resolve to a method
if (parentIsMethodCall != resolvingToMethod) return false;
return element.getManager().areElementsEquivalent(element, resolve());
}
@Override
@NotNull
public Object[] getVariants() {
//this reference's variants are rather obtained with processVariants()
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
@Override
public boolean isSoft() {
return false;
return super.isReferenceTo(element);
}
@Override
@@ -435,7 +403,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
filter.addFilter(new AndFilter(ElementClassFilter.METHOD, new NotFilter(new ConstructorFilter())));
filter.addFilter(ElementClassFilter.VARIABLE);
FilterScopeProcessor proc = new FilterScopeProcessor(filter, processor) {
FilterScopeProcessor filterProcessor = new FilterScopeProcessor<CandidateInfo>(filter, processor) {
private final Set<String> myVarNames = new THashSet<String>();
@Override
@@ -454,7 +422,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
}
};
PsiScopesUtil.resolveAndWalk(proc, this, null, true);
PsiScopesUtil.resolveAndWalk(filterProcessor, this, null, true);
}
private static boolean seemsScrambled(PsiClass element) {
@@ -469,24 +437,11 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
Character.isLowerCase(qualifiedName.charAt(0));
}
@Override
@NotNull
public JavaResolveResult advancedResolve(boolean incompleteCode) {
final JavaResolveResult[] results = multiResolve(incompleteCode);
if (results.length == 1) return results[0];
return JavaResolveResult.EMPTY;
}
@Override
public PsiElement getReferenceNameElement() {
return findChildByRoleAsPsiElement(ChildRole.REFERENCE_NAME);
}
@Override
public PsiReferenceParameterList getParameterList() {
return (PsiReferenceParameterList)findChildByRoleAsPsiElement(ChildRole.REFERENCE_PARAMETER_LIST);
}
@Override
public int getTextOffset() {
ASTNode refName = findChildByRole(ChildRole.REFERENCE_NAME);
@@ -684,20 +639,6 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
return new TextRange(nameChild.getStartOffsetInParent(), getTextLength());
}
@Override
public PsiElement getElement() {
return this;
}
@Override
@NotNull
public PsiType[] getTypeParameters() {
final PsiReferenceParameterList parameterList = getParameterList();
if (parameterList == null) return PsiType.EMPTY_ARRAY;
return parameterList.getTypeArguments();
}
@Override
public String getClassNameText() {
String cachedQName = myCachedQName;
@@ -744,4 +685,3 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
return whiteSpaceAndComments;
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class C {
interface Simplest {
void m();
}
void simplest() { }
void test() {
<error descr="Incompatible types. Found: 'null', required: 'C.Simplest'">Simplest simplest = this::simplest;</error>
}
}
@@ -0,0 +1,20 @@
PsiJavaFile:MethodRef0.java
PsiMethodReferenceExpression:a.b.C::m
PsiReferenceExpression:a.b.C
PsiReferenceExpression:a.b
PsiReferenceExpression:a
PsiReferenceParameterList
<empty list>
PsiIdentifier:a('a')
PsiJavaToken:DOT('.')
PsiReferenceParameterList
<empty list>
PsiIdentifier:b('b')
PsiJavaToken:DOT('.')
PsiReferenceParameterList
<empty list>
PsiIdentifier:C('C')
PsiJavaToken:DOUBLE_COLON('::')
PsiReferenceParameterList
<empty list>
PsiIdentifier:m('m')
@@ -0,0 +1,27 @@
PsiJavaFile:MethodRef1.java
PsiMethodReferenceExpression:a.b.C<T>::new
PsiTypeElement:a.b.C<T>
PsiJavaCodeReferenceElement:a.b.C<T>
PsiJavaCodeReferenceElement:a.b
PsiJavaCodeReferenceElement:a
PsiIdentifier:a('a')
PsiReferenceParameterList
<empty list>
PsiJavaToken:DOT('.')
PsiIdentifier:b('b')
PsiReferenceParameterList
<empty list>
PsiJavaToken:DOT('.')
PsiIdentifier:C('C')
PsiReferenceParameterList
PsiJavaToken:LT('<')
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiJavaToken:GT('>')
PsiJavaToken:DOUBLE_COLON('::')
PsiReferenceParameterList
<empty list>
PsiKeyword:new('new')
@@ -0,0 +1,16 @@
PsiJavaFile:MethodRef2.java
PsiMethodReferenceExpression:C::<T>m
PsiReferenceExpression:C
PsiReferenceParameterList
<empty list>
PsiIdentifier:C('C')
PsiJavaToken:DOUBLE_COLON('::')
PsiReferenceParameterList
PsiJavaToken:LT('<')
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiJavaToken:GT('>')
PsiIdentifier:m('m')
@@ -0,0 +1,17 @@
PsiJavaFile:MethodRef3.java
PsiMethodReferenceExpression:a[i]::m
PsiArrayAccessExpression:a[i]
PsiReferenceExpression:a
PsiReferenceParameterList
<empty list>
PsiIdentifier:a('a')
PsiJavaToken:LBRACKET('[')
PsiReferenceExpression:i
PsiReferenceParameterList
<empty list>
PsiIdentifier:i('i')
PsiJavaToken:RBRACKET(']')
PsiJavaToken:DOUBLE_COLON('::')
PsiReferenceParameterList
<empty list>
PsiIdentifier:m('m')
@@ -0,0 +1,11 @@
PsiJavaFile:MethodRef4.java
PsiMethodReferenceExpression:int[]::clone
PsiTypeElement:int[]
PsiTypeElement:int
PsiKeyword:int('int')
PsiJavaToken:LBRACKET('[')
PsiJavaToken:RBRACKET(']')
PsiJavaToken:DOUBLE_COLON('::')
PsiReferenceParameterList
<empty list>
PsiIdentifier:clone('clone')
@@ -0,0 +1,55 @@
PsiJavaFile:MethodRef5.java
PsiMethodReferenceExpression:(f ? list.map(String::length) : Collections.emptyList())::iterator
PsiParenthesizedExpression:(f ? list.map(String::length) : Collections.emptyList())
PsiJavaToken:LPARENTH('(')
PsiConditionalExpression:f ? list.map(String::length) : Collections.emptyList()
PsiReferenceExpression:f
PsiReferenceParameterList
<empty list>
PsiIdentifier:f('f')
PsiWhiteSpace(' ')
PsiJavaToken:QUEST('?')
PsiWhiteSpace(' ')
PsiMethodCallExpression:list.map(String::length)
PsiReferenceExpression:list.map
PsiReferenceExpression:list
PsiReferenceParameterList
<empty list>
PsiIdentifier:list('list')
PsiJavaToken:DOT('.')
PsiReferenceParameterList
<empty list>
PsiIdentifier:map('map')
PsiExpressionList
PsiJavaToken:LPARENTH('(')
PsiMethodReferenceExpression:String::length
PsiReferenceExpression:String
PsiReferenceParameterList
<empty list>
PsiIdentifier:String('String')
PsiJavaToken:DOUBLE_COLON('::')
PsiReferenceParameterList
<empty list>
PsiIdentifier:length('length')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:COLON(':')
PsiWhiteSpace(' ')
PsiMethodCallExpression:Collections.emptyList()
PsiReferenceExpression:Collections.emptyList
PsiReferenceExpression:Collections
PsiReferenceParameterList
<empty list>
PsiIdentifier:Collections('Collections')
PsiJavaToken:DOT('.')
PsiReferenceParameterList
<empty list>
PsiIdentifier:emptyList('emptyList')
PsiExpressionList
PsiJavaToken:LPARENTH('(')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:DOUBLE_COLON('::')
PsiReferenceParameterList
<empty list>
PsiIdentifier:iterator('iterator')
@@ -0,0 +1,11 @@
PsiJavaFile:PrimitiveFieldAccess.java
PsiReferenceExpression:int.x
PsiClassObjectAccessExpression:int
PsiTypeElement:int
PsiKeyword:int('int')
PsiErrorElement:.class expected
<empty list>
PsiJavaToken:DOT('.')
PsiReferenceParameterList
<empty list>
PsiIdentifier:x('x')
@@ -184,4 +184,5 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
public void testIDEA84533() throws Exception { doTest(false, false); }
public void testClassLiteral() throws Exception { doTest(false, false); }
public void testExtensionMethods() throws Exception { doTest(false, false); }
public void testMethodReferences() throws Exception { doTest(false, false); }
}
@@ -111,9 +111,17 @@ public class ExpressionParserTest extends JavaParsingTestCase {
public void testQualifiedSuperMethodCall1() { doParserTest("d.super(0)"); }
public void testSuperMethodCallTypeParameterList() { doParserTest("super()"); }
public void testPrimitiveClassObjectAccess() { doParserTest("int.class"); }
public void testPrimitiveFieldAccess() { doParserTest("int.x"); }
public void testChainedClassObjectAccess() { doParserTest("A.class.B.class"); }
public void testChainedThisObjectAccess() { doParserTest("A.this.B.this"); }
public void testMethodRef0() { doParserTest("a.b.C::m"); }
public void testMethodRef1() { doParserTest("a.b.C<T>::new"); }
public void testMethodRef2() { doParserTest("C::<T>m"); }
public void testMethodRef3() { doParserTest("a[i]::m"); }
public void testMethodRef4() { doParserTest("int[]::clone"); }
public void testMethodRef5() { doParserTest("(f ? list.map(String::length) : Collections.emptyList())::iterator"); }
private void doParserTest(@NonNls final String text) {
doParserTest(text, new MyTestParser());
}
@@ -46,6 +46,8 @@ import java.util.List;
public class BookmarksAction extends AnAction implements DumbAware, MasterDetailPopupBuilder.Delegate {
private JBPopup myPopup;
@Override
public void update(AnActionEvent e) {
DataContext dataContext = e.getDataContext();
@@ -59,6 +61,7 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail
final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
if (project == null) return;
if (myPopup != null && myPopup.isVisible()) return;
final DefaultListModel model = buildModel(project);
@@ -72,13 +75,13 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail
actions.add(new MoveBookmarkUpAction(project, list));
actions.add(new MoveBookmarkDownAction(project, list));
final JBPopup popup = new MasterDetailPopupBuilder(project).
myPopup = new MasterDetailPopupBuilder(project).
setActionsGroup(actions).
setList(list).
setDelegate(this).createMasterDetailPopup();
editDescriptionAction.setPopup(popup);
popup.showCenteredInCurrentWindow(project);
editDescriptionAction.setPopup(myPopup);
myPopup.showCenteredInCurrentWindow(project);
}
@Override
@@ -126,7 +126,7 @@ public class OpenFileDescriptor implements Navigatable {
FileType type = FileTypeManager.getInstance().getKnownFileTypeOrAssociate(myFile,project);
if (type == null || !myFile.isValid()) return false;
if (type instanceof INativeFileType && requestFocus) {
if (type instanceof INativeFileType) {
return ((INativeFileType) type).openFileInAssociatedApplication(project, myFile);
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.INativeFileType;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.vfs.PersistentFSConstants;
@@ -179,7 +180,7 @@ public abstract class AutoScrollToSourceHandler {
if (vFile != null) {
// Attempt to navigate to the virtual file with unknown file type will show a modal dialog
// asking to register some file type for this file. This behaviour is undesirable when autoscrolling.
if (vFile.getFileType() == FileTypes.UNKNOWN) return;
if (vFile.getFileType() == FileTypes.UNKNOWN || vFile.getFileType() instanceof INativeFileType) return;
//IDEA-84881 Don't autoscroll to very large files
if (vFile.getLength() > PersistentFSConstants.getMaxIntellisenseFileSize()) return;
@@ -4,14 +4,10 @@ import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.util.Arrays;
/**
* @author evgeny.zakrevsky
@@ -91,7 +91,20 @@ public class AsyncProcessIcon extends AnimatedIcon {
}
public static class Big extends AsyncProcessIcon {
private static final Icon[] BIG_ICONS = findIcons("/process/big/step_", null);
private static final Icon[] BIG_ICONS = {
AllIcons.Process.Big.Step_1,
AllIcons.Process.Big.Step_2,
AllIcons.Process.Big.Step_3,
AllIcons.Process.Big.Step_4,
AllIcons.Process.Big.Step_5,
AllIcons.Process.Big.Step_6,
AllIcons.Process.Big.Step_7,
AllIcons.Process.Big.Step_8,
AllIcons.Process.Big.Step_9,
AllIcons.Process.Big.Step_10,
AllIcons.Process.Big.Step_11,
AllIcons.Process.Big.Step_12
};
private static final Icon BIG_PASSIVE_ICON = AllIcons.Process.Big.Step_passive;
public Big(@NonNls final String name) {
@@ -15,7 +15,7 @@
*/
package com.intellij.util.ui;
import com.intellij.openapi.util.IconLoader;
import com.intellij.icons.AllIcons;
import javax.swing.*;
import java.awt.*;
@@ -24,16 +24,26 @@ import java.awt.*;
* @author Konstantin Bulenkov
*/
public class RefreshFileSystemIcon extends AnimatedIcon {
private static final Icon[] ICONS = getIcons("/process/fs/step_", 18);
private static Icon[] getIcons(String path, int count) {
Icon[] icons = new Icon[count];
for (int i = 0; i < icons.length; i++) {
int index = i + 1;
icons[i] = IconLoader.getIcon(path + index + ".png");
}
return icons;
}
private static final Icon[] ICONS = {
AllIcons.Process.FS.Step_1,
AllIcons.Process.FS.Step_2,
AllIcons.Process.FS.Step_3,
AllIcons.Process.FS.Step_4,
AllIcons.Process.FS.Step_5,
AllIcons.Process.FS.Step_6,
AllIcons.Process.FS.Step_7,
AllIcons.Process.FS.Step_8,
AllIcons.Process.FS.Step_9,
AllIcons.Process.FS.Step_10,
AllIcons.Process.FS.Step_11,
AllIcons.Process.FS.Step_12,
AllIcons.Process.FS.Step_13,
AllIcons.Process.FS.Step_14,
AllIcons.Process.FS.Step_15,
AllIcons.Process.FS.Step_16,
AllIcons.Process.FS.Step_17,
AllIcons.Process.FS.Step_18
};
public RefreshFileSystemIcon() {
super("Refreshing filesystem", ICONS, EmptyIcon.ICON_16, 800);
@@ -16,10 +16,15 @@
package com.intellij.util.io;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.Nullable;
import sun.misc.Cleaner;
import sun.nio.ch.DirectBuffer;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
public abstract class DirectBufferWrapper extends ByteBufferWrapper {
protected static final Logger LOG = Logger.getInstance("#com.intellij.util.io.DirectBufferWrapper");
@@ -49,6 +54,24 @@ public abstract class DirectBufferWrapper extends ByteBufferWrapper {
@Override
public void unmap() {
if (isDirty()) flush();
if (myBuffer != null) disposeDirectBuffer((DirectBuffer)myBuffer);
myBuffer = null;
}
static boolean disposeDirectBuffer(final DirectBuffer buffer) {
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Nullable
public Object run() {
try {
Cleaner cleaner = buffer.cleaner();
if (cleaner != null) cleaner.clean(); // Already cleaned otherwise
return null;
}
catch (Exception e) {
return buffer;
}
}
}) == null;
}
}
@@ -16,16 +16,12 @@
package com.intellij.util.io;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.Nullable;
import sun.misc.Cleaner;
import sun.nio.ch.DirectBuffer;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* @author max
@@ -81,19 +77,7 @@ public abstract class MappedBufferWrapper extends ByteBufferWrapper {
return false;
}
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Nullable
public Object run() {
try {
Cleaner cleaner = ((DirectBuffer)buffer).cleaner();
if (cleaner != null) cleaner.clean(); // Already cleaned otherwise
return null;
}
catch (Exception e) {
return buffer;
}
}
}) == null;
return DirectBufferWrapper.disposeDirectBuffer((DirectBuffer)buffer);
}
private static boolean tryForce(MappedByteBuffer buffer) {
@@ -370,7 +370,7 @@
<categoryKey>intention.category.strings</categoryKey>
</intentionAction>
<intentionAction>
<className>com.siyeh.ipp.concatenation.MakeAppendChainIntoAppendSequenceIntention</className>
<className>com.siyeh.ipp.concatenation.MakeCallChainIntoCallSequenceIntention</className>
<categoryKey>intention.category.other</categoryKey>
</intentionAction>
<intentionAction>
@@ -81,8 +81,8 @@ replace.if.with.conditional.intention.name=Replace 'if else' with '?:'
replace.if.with.conditional.intention.family.name=Replace If Else with Conditional
replace.equality.with.equals.intention.name=Replace '==' with '.equals()'
replace.equality.with.equals.intention.family.name=Replace Equality with Equals
make.append.chain.into.append.sequence.intention.name=Make '.append()' chain into '.append()' sequence
make.append.chain.into.append.sequence.intention.family.name=Make Append Chain Into Append Sequence
make.call.chain.into.call.sequence.intention.name=Make method call chain into method call sequence
make.call.chain.into.call.sequence.intention.family.name=Make Call Chain Into Call Sequence
detail.exceptions.intention.name=Detail exceptions
detail.exceptions.intention.family.name=Detail Exceptions
flip.conditional.intention.name=Flip '?:'
@@ -1,56 +0,0 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* 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.siyeh.ipp.concatenation;
import com.intellij.psi.*;
import com.siyeh.ipp.base.PsiElementPredicate;
class AppendChainPredicate implements PsiElementPredicate {
public boolean satisfiedBy(PsiElement element) {
if (!AppendUtil.isAppendCall(element)) {
return false;
}
final PsiMethodCallExpression call = (PsiMethodCallExpression)element;
final PsiReferenceExpression methodExpression =
call.getMethodExpression();
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
if (!(qualifier instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression qualifierCall =
(PsiMethodCallExpression)element;
if (!AppendUtil.isAppendCall(qualifierCall)) {
return false;
}
final PsiElement parent = element.getParent();
if (parent instanceof PsiExpressionStatement) {
return true;
}
final PsiElement grandParent = parent.getParent();
if (parent instanceof PsiLocalVariable &&
grandParent instanceof PsiDeclarationStatement) {
final PsiDeclarationStatement declarationStatement =
(PsiDeclarationStatement)grandParent;
if (declarationStatement.getDeclaredElements().length == 1) {
return true;
}
}
return parent instanceof PsiAssignmentExpression &&
grandParent instanceof PsiExpressionStatement;
}
}
@@ -1,79 +0,0 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* 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.siyeh.ipp.concatenation;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NonNls;
class AppendUtil {
private AppendUtil() {
}
public static boolean isAppendCall(PsiElement element) {
if (!(element instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression methodCallExpression =
(PsiMethodCallExpression)element;
final PsiReferenceExpression methodExpression =
methodCallExpression.getMethodExpression();
@NonNls final String callName = methodExpression.getReferenceName();
if (!"append".equals(callName)) {
return false;
}
final PsiMethod method = methodCallExpression.resolveMethod();
final PsiClass containingClass;
if (method == null) {
// if the argument has no type because of invalid code
// this uses the qualifier as type, so the conversion too
// append sequence is still applicable
final PsiExpression qualifierExpression =
methodExpression.getQualifierExpression();
if (qualifierExpression == null) {
return false;
}
final PsiType type = qualifierExpression.getType();
if (!(type instanceof PsiClassType)) {
return false;
}
final PsiClassType classType = (PsiClassType)type;
containingClass = classType.resolve();
}
else {
containingClass = method.getContainingClass();
}
if (containingClass == null) {
return false;
}
final String name = containingClass.getQualifiedName();
if (CommonClassNames.JAVA_LANG_STRING_BUFFER.equals(name) ||
CommonClassNames.JAVA_LANG_STRING_BUILDER.equals(name)) {
return true;
}
final Project project = containingClass.getProject();
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final PsiClass appendableClass =
psiFacade.findClass("java.lang.Appendable",
GlobalSearchScope.allScope(project));
if (appendableClass == null) {
return false;
}
return containingClass.isInheritor(appendableClass, true);
}
}
@@ -1,139 +0,0 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* 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.siyeh.ipp.concatenation;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MakeAppendChainIntoAppendSequenceIntention extends Intention {
@Override
@NotNull
protected PsiElementPredicate getElementPredicate() {
return new AppendChainPredicate();
}
@Override
public void processIntention(PsiElement element)
throws IncorrectOperationException {
final PsiExpression call = (PsiExpression)element;
final List<String> argumentsList = new ArrayList<String>();
PsiExpression currentCall = call;
while (AppendUtil.isAppendCall(currentCall)) {
final PsiMethodCallExpression methodCallExpression =
(PsiMethodCallExpression)currentCall;
final PsiExpressionList arguments =
methodCallExpression.getArgumentList();
final String argumentsText = arguments.getText();
argumentsList.add(argumentsText);
final PsiReferenceExpression methodExpression =
methodCallExpression.getMethodExpression();
currentCall = methodExpression.getQualifierExpression();
if (currentCall == null) {
return;
}
}
final String targetText;
final PsiStatement appendStatement;
@NonNls final String firstStatement;
final PsiElement parent = call.getParent();
if (parent instanceof PsiExpressionStatement) {
targetText = currentCall.getText();
appendStatement = (PsiStatement)parent;
firstStatement = null;
}
else {
final PsiElement grandParent = parent.getParent();
appendStatement = (PsiStatement)grandParent;
if (parent instanceof PsiAssignmentExpression &&
grandParent instanceof PsiExpressionStatement) {
final PsiAssignmentExpression assignment =
(PsiAssignmentExpression)parent;
final PsiExpression lhs = assignment.getLExpression();
targetText = lhs.getText();
final PsiJavaToken token = assignment.getOperationSign();
firstStatement = targetText + token.getText() +
currentCall.getText() + ';';
}
else {
final PsiDeclarationStatement declaration =
(PsiDeclarationStatement)appendStatement;
final PsiVariable variable =
(PsiVariable)declaration.getDeclaredElements()[0];
targetText = variable.getName();
final PsiType variableType = variable.getType();
if (variable.hasModifierProperty(PsiModifier.FINAL)) {
firstStatement =
"final " + variableType.getPresentableText() +
' ' + variable.getName() + '=' +
currentCall.getText() + ';';
}
else {
firstStatement = variableType.getPresentableText() +
' ' + variable.getName() + '=' +
currentCall.getText() + ';';
}
}
}
final StringBuilder builder = new StringBuilder("{");
if (firstStatement != null) {
builder.append(firstStatement);
}
Collections.reverse(argumentsList);
for (String argument : argumentsList) {
builder.append(targetText);
builder.append(".append");
builder.append(argument);
builder.append(';');
}
builder.append('}');
final PsiManager manager = element.getManager();
final Project project = manager.getProject();
final PsiElementFactory factory =
JavaPsiFacade.getElementFactory(project);
final PsiElement appendStatementParent = appendStatement.getParent();
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
final PsiCodeBlock codeBlock =
factory.createCodeBlockFromText(builder.toString(),
appendStatement);
if (appendStatementParent instanceof PsiLoopStatement ||
appendStatementParent instanceof PsiIfStatement) {
final PsiElement insertedStatement =
appendStatement.replace(codeBlock);
codeStyleManager.reformat(insertedStatement);
}
else {
final PsiStatement[] statements = codeBlock.getStatements();
for (PsiStatement statement : statements) {
final PsiElement insertedStatement =
appendStatementParent.addBefore(statement,
appendStatement);
codeStyleManager.reformat(insertedStatement);
}
appendStatement.delete();
}
}
}
@@ -0,0 +1,184 @@
/*
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
*
* 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.siyeh.ipp.concatenation;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.HighlightUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MakeCallChainIntoCallSequenceIntention extends Intention {
@Override
@NotNull
protected PsiElementPredicate getElementPredicate() {
return new MethodCallChainPredicate();
}
@Override
public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
final List<String> callTexts = new ArrayList<String>();
PsiExpression root = (PsiExpression)element;
while (root instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) root;
final PsiExpressionList arguments = methodCallExpression.getArgumentList();
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
callTexts.add(methodExpression.getReferenceName() + arguments.getText());
root = methodExpression.getQualifierExpression();
if (root == null) {
return;
}
}
final PsiType rootType = root.getType();
if (rootType == null) {
return;
}
final String targetText;
final PsiStatement appendStatement;
@NonNls final String firstStatement;
final String variableDeclaration;
final boolean showRenameTemplate;
final PsiElement parent = element.getParent();
if (parent instanceof PsiExpressionStatement) {
targetText = root.getText();
appendStatement = (PsiStatement)parent;
firstStatement = null;
variableDeclaration = null;
showRenameTemplate = false;
}
else {
final PsiElement grandParent = parent.getParent();
appendStatement = (PsiStatement)grandParent;
if (parent instanceof PsiAssignmentExpression && grandParent instanceof PsiExpressionStatement) {
final PsiAssignmentExpression assignment = (PsiAssignmentExpression)parent;
final PsiExpression lhs = assignment.getLExpression();
if (!(lhs instanceof PsiReferenceExpression)) {
return;
}
final PsiReferenceExpression expression = (PsiReferenceExpression)lhs;
final PsiElement target = expression.resolve();
if (!(target instanceof PsiVariable)) {
return;
}
final PsiVariable variable = (PsiVariable)target;
final PsiType variableType = variable.getType();
if (variableType.equals(rootType)) {
targetText = lhs.getText();
final PsiJavaToken token = assignment.getOperationSign();
firstStatement = targetText + token.getText() + root.getText() + ';';
showRenameTemplate = false;
} else {
targetText = "x";
showRenameTemplate = true;
final Project project = element.getProject();
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
if (codeStyleSettings.GENERATE_FINAL_LOCALS) {
firstStatement = "final " + rootType.getCanonicalText() + ' ' + targetText + '=' + root.getText() + ';';
} else {
firstStatement = rootType.getCanonicalText() + ' ' + targetText + '=' + root.getText() + ';';
}
}
variableDeclaration = null;
}
else {
final PsiDeclarationStatement declaration = (PsiDeclarationStatement)appendStatement;
final PsiVariable variable = (PsiVariable)declaration.getDeclaredElements()[0];
final PsiType variableType = variable.getType();
if (variableType.equals(rootType)) {
targetText = variable.getName();
if (variable.hasModifierProperty(PsiModifier.FINAL)) {
firstStatement = "final " + variableType.getCanonicalText() + ' ' + variable.getName() + '=' + root.getText() + ';';
}
else {
firstStatement = variableType.getCanonicalText() + ' ' + variable.getName() + '=' + root.getText() + ';';
}
variableDeclaration = null;
showRenameTemplate = false;
} else {
if (variable.hasModifierProperty(PsiModifier.FINAL)) {
variableDeclaration = "final " + variableType.getCanonicalText() + ' ' + variable.getName() + '=';
}
else {
variableDeclaration = variableType.getCanonicalText() + ' ' + variable.getName() + '=';
}
targetText = "x";
showRenameTemplate = true;
final Project project = element.getProject();
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
if (codeStyleSettings.GENERATE_FINAL_LOCALS) {
firstStatement = "final " + rootType.getCanonicalText() + " x=" + root.getText() + ';';
} else {
firstStatement = rootType.getCanonicalText() + " x=" + root.getText() + ';';
}
}
}
}
final StringBuilder builder = new StringBuilder("{\n");
if (firstStatement != null) {
builder.append(firstStatement);
}
Collections.reverse(callTexts);
for (int i = 0, size = callTexts.size(); i < size; i++) {
final String callText = callTexts.get(i);
if (i == size - 1 && variableDeclaration != null) {
builder.append(variableDeclaration);
}
builder.append(targetText).append('.').append(callText).append(";\n");
}
builder.append('}');
final PsiManager manager = element.getManager();
final Project project = manager.getProject();
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiElement appendStatementParent = appendStatement.getParent();
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
final PsiCodeBlock codeBlock = factory.createCodeBlockFromText(builder.toString(), appendStatement);
if (appendStatementParent instanceof PsiLoopStatement || appendStatementParent instanceof PsiIfStatement) {
final PsiElement insertedCodeBlock = appendStatement.replace(codeBlock);
final PsiCodeBlock reformattedCodeBlock = (PsiCodeBlock)codeStyleManager.reformat(insertedCodeBlock);
if (showRenameTemplate) {
final PsiStatement[] statements = reformattedCodeBlock.getStatements();
final PsiVariable variable = (PsiVariable)((PsiDeclarationStatement) statements[0]).getDeclaredElements()[0];
HighlightUtil.showRenameTemplate(appendStatementParent, variable);
}
}
else {
final PsiStatement[] statements = codeBlock.getStatements();
PsiVariable variable = null;
for (int i = 0, length = statements.length; i < length; i++) {
final PsiElement insertedStatement = appendStatementParent.addBefore(statements[i], appendStatement);
if (i == 0 && showRenameTemplate) {
variable = (PsiVariable)((PsiDeclarationStatement) insertedStatement).getDeclaredElements()[0];
}
codeStyleManager.reformat(insertedStatement);
}
appendStatement.delete();
if (variable != null) {
HighlightUtil.showRenameTemplate(appendStatementParent, variable);
}
}
}
}
@@ -0,0 +1,96 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* 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.siyeh.ipp.concatenation;
import com.intellij.psi.*;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.Nullable;
class MethodCallChainPredicate implements PsiElementPredicate {
public boolean satisfiedBy(PsiElement element) {
if (!isCallChain(element)) {
return false;
}
final PsiElement parent = element.getParent();
if (parent instanceof PsiExpressionStatement) {
return true;
}
else if (parent instanceof PsiLocalVariable) {
final PsiElement grandParent = parent.getParent();
if (!(grandParent instanceof PsiDeclarationStatement)) {
return false;
}
final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)grandParent;
return declarationStatement.getDeclaredElements().length == 1;
}
else if (parent instanceof PsiAssignmentExpression) {
final PsiElement grandParent = parent.getParent();
return grandParent instanceof PsiExpressionStatement;
}
return false;
}
private static boolean isCallChain(PsiElement element) {
PsiClass aClass1 = getQualifierExpressionType(element);
if (aClass1 == null) {
return false;
}
boolean first = true;
while (aClass1 != null) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
PsiClass aClass2 = getQualifierExpressionType(qualifierExpression);
if (!first) {
if (aClass2 == null) {
return true;
}
} else {
first = false;
}
if (!aClass1.equals(aClass2)) {
return false;
}
aClass1 = aClass2;
element = qualifierExpression;
}
return true;
}
@Nullable
private static PsiClass getQualifierExpressionType(PsiElement element) {
if (!(element instanceof PsiMethodCallExpression)) {
return null;
}
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
final PsiMethod method = methodCallExpression.resolveMethod();
if (method != null) {
return method.getContainingClass();
}
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
if (!(qualifierExpression instanceof PsiMethodCallExpression)) {
return null;
}
final PsiType type = qualifierExpression.getType();
if (!(type instanceof PsiClassType)) {
return null;
}
final PsiClassType classType = (PsiClassType)type;
return classType.resolve();
}
}
@@ -15,7 +15,14 @@
*/
package com.siyeh.ipp.psiutils;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.template.Expression;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateBuilderImpl;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.MacroCallNode;
import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
import com.intellij.find.FindManager;
import com.intellij.find.FindModel;
import com.intellij.openapi.application.Application;
@@ -27,11 +34,16 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Query;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -118,4 +130,32 @@ public class HighlightUtil {
}
return builder;
}
public static void showRenameTemplate(PsiElement context, PsiNameIdentifierOwner element) {
context = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(context);
final Query<PsiReference> query = ReferencesSearch.search(element, element.getUseScope());
final Collection<PsiReference> references = query.findAll();
final Project project = context.getProject();
final FileEditorManager fileEditorManager =
FileEditorManager.getInstance(project);
final Editor editor = fileEditorManager.getSelectedTextEditor();
if (editor == null) {
return;
}
final TemplateBuilderImpl builder = new TemplateBuilderImpl(context);
final Expression macroCallNode = new MacroCallNode(
new SuggestVariableNameMacro());
final PsiElement identifier = element.getNameIdentifier();
builder.replaceElement(identifier, "PATTERN", macroCallNode, true);
for (PsiReference reference : references) {
builder.replaceElement(reference, "PATTERN", "PATTERN", false);
}
final Template template = builder.buildInlineTemplate();
final TextRange textRange = context.getTextRange();
final int startOffset = textRange.getStartOffset();
editor.getCaretModel().moveToOffset(startOffset);
final TemplateManager templateManager =
TemplateManager.getInstance(project);
templateManager.startTemplate(editor, template);
}
}
@@ -1,6 +0,0 @@
<html>
<body>
This intention replaces chains of <b>StringBuffer.append()</b> calls with
the equivalent sequence of call statements.
</body>
</html>
@@ -0,0 +1,5 @@
<html>
<body>
This intention replaces chains of method calls with the equivalent sequence of call statements.
</body>
</html>