diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
index 71d6899249a1..198726115763 100644
--- a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
+++ b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
@@ -25,10 +25,10 @@ import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import static com.intellij.BitUtil.isSet;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.PsiBuilderUtil.nextTokenType;
import static com.intellij.lang.java.parser.JavaParserUtil.*;
-import static com.intellij.lang.java.parser.JavaParserUtil.emptyElement;
public class ReferenceParser {
@@ -147,10 +147,6 @@ public class ReferenceParser {
return typeInfo;
}
- private static boolean isSet(final int mask, final int flag) {
- return (mask & flag) != 0;
- }
-
@NotNull
private static PsiBuilder.Marker parseWildcardType(final PsiBuilder builder) {
final PsiBuilder.Marker type = builder.mark();
diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
index 12e62429979d..95bb4aedd329 100644
--- a/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
@@ -559,16 +559,24 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps
@NotNull
public PsiTypeCodeFragment createTypeCodeFragment(@NotNull final String text, final PsiElement context, final boolean isPhysical) {
- return createTypeCodeFragment(text, context, false, isPhysical, false);
+ return createTypeCodeFragment(text, context, isPhysical, 0);
}
+ @NotNull
+ public PsiTypeCodeFragment createTypeCodeFragment(@NotNull final String text, final PsiElement context, final boolean isPhysical, final int flags) {
+ final PsiTypeCodeFragmentImpl result = new PsiTypeCodeFragmentImpl(myManager.getProject(), isPhysical, "fragment.java", text, flags);
+ result.setContext(context);
+ return result;
+ }
@NotNull
public PsiTypeCodeFragment createTypeCodeFragment(@NotNull final String text,
final PsiElement context,
final boolean isVoidValid,
final boolean isPhysical) {
- return createTypeCodeFragment(text, context, true, isPhysical, false);
+ int flags = 0;
+ if (isVoidValid) flags |= ALLOW_VOID;
+ return createTypeCodeFragment(text, context, isPhysical, flags);
}
@NotNull
@@ -577,12 +585,10 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps
final boolean isVoidValid,
final boolean isPhysical,
final boolean allowEllipsis) {
- final PsiTypeCodeFragmentImpl result = new PsiTypeCodeFragmentImpl(myManager.getProject(), isPhysical, allowEllipsis, "fragment.java", text);
- result.setContext(context);
- if (isVoidValid) {
- result.putUserData(PsiUtil.VALID_VOID_TYPE_IN_CODE_FRAGMENT, Boolean.TRUE);
- }
- return result;
+ int flags = 0;
+ if (isVoidValid) flags |= ALLOW_VOID;
+ if (allowEllipsis) flags |= ALLOW_ELLIPSIS;
+ return createTypeCodeFragment(text, context, isPhysical, flags);
}
@NotNull
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeCodeFragmentImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeCodeFragmentImpl.java
index 38633eec4b4e..d96859a418d8 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeCodeFragmentImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeCodeFragmentImpl.java
@@ -15,61 +15,70 @@
*/
package com.intellij.psi.impl.source;
+import com.intellij.BitUtil;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.JavaElementType;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import static com.intellij.BitUtil.isSet;
+
/**
* @author dsl
*/
public class PsiTypeCodeFragmentImpl extends PsiCodeFragmentImpl implements PsiTypeCodeFragment {
private final boolean myAllowEllipsis;
+ private final boolean myAllowDisjunction;
- public PsiTypeCodeFragmentImpl(Project manager,
- boolean isPhysical,
- boolean allowEllipsis,
- @NonNls String name,
- CharSequence text) {
- super(manager, JavaElementType.TYPE_TEXT, isPhysical, name, text);
- myAllowEllipsis = allowEllipsis;
+ public PsiTypeCodeFragmentImpl(final Project project,
+ final boolean isPhysical,
+ final @NonNls String name,
+ final CharSequence text,
+ final int flags) {
+ super(project, JavaElementType.TYPE_TEXT, isPhysical, name, text);
+
+ myAllowEllipsis = BitUtil.isSet(flags, PsiElementFactory.ALLOW_ELLIPSIS);
+ myAllowDisjunction = BitUtil.isSet(flags, PsiElementFactory.ALLOW_DISJUNCTION);
+
+ if (isSet(flags, PsiElementFactory.ALLOW_VOID)) {
+ putUserData(PsiUtil.VALID_VOID_TYPE_IN_CODE_FRAGMENT, Boolean.TRUE);
+ }
}
@NotNull
- public PsiType getType()
- throws TypeSyntaxException, NoTypeException {
- class SyntaxError extends RuntimeException {}
+ public PsiType getType() throws TypeSyntaxException, NoTypeException {
+ class MyTypeSyntaxException extends RuntimeException {
+ MyTypeSyntaxException(final String message) { super(message); }
+ }
+
try {
accept(new PsiRecursiveElementWalkingVisitor() {
- @Override public void visitErrorElement(PsiErrorElement element) {
- throw new SyntaxError();
+ @Override
+ public void visitErrorElement(PsiErrorElement element) {
+ throw new MyTypeSyntaxException(element.getErrorDescription());
}
});
}
- catch(SyntaxError e) {
- throw new TypeSyntaxException();
+ catch (MyTypeSyntaxException e) {
+ throw new TypeSyntaxException(e.getMessage());
}
- PsiElement child = getFirstChild();
- while (child != null && !(child instanceof PsiTypeElement)) {
- child = child.getNextSibling();
- }
- PsiTypeElement typeElement = (PsiTypeElement)child;
+
+ final PsiTypeElement typeElement = PsiTreeUtil.getChildOfType(this, PsiTypeElement.class);
if (typeElement == null) {
- throw new NoTypeException();
+ throw new NoTypeException("No type found in '" + getText() + "'");
}
- PsiType type = typeElement.getType();
- PsiElement sibling = typeElement.getNextSibling();
- while (sibling instanceof PsiWhiteSpace) {
- sibling = sibling.getNextSibling();
+
+ final PsiType type = typeElement.getType();
+ if (type instanceof PsiEllipsisType && !myAllowEllipsis) {
+ throw new TypeSyntaxException("Ellipsis not allowed: " + type);
}
- if (sibling instanceof PsiJavaToken && "...".equals(sibling.getText())) {
- if (myAllowEllipsis) return new PsiEllipsisType(type);
- else throw new TypeSyntaxException();
- } else {
- return type;
+ else if (type instanceof PsiDisjunctionType && !myAllowDisjunction) {
+ throw new TypeSyntaxException("Disjunction not allowed: " + type);
}
+ return type;
}
public boolean isVoidValid() {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java
index 3a6026e33880..9060dfdc225e 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java
@@ -38,8 +38,6 @@ import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Constructor;
-import static com.intellij.lang.PsiBuilderUtil.expect;
-
public interface JavaElementType {
class JavaCompositeElementType extends IJavaElementType implements ICompositeElementType {
private final Constructor extends ASTNode> myConstructor;
@@ -238,8 +236,8 @@ public interface JavaElementType {
return JavaParserUtil.parseFragment(chameleon,
new JavaParserUtil.ParserWrapper() {
public void parse(final PsiBuilder builder) {
- ReferenceParser.parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
- expect(builder, JavaTokenType.ELLIPSIS); // todo[r.sh] parse ellipsis and fix PsiTypeCodeFragmentImpl.getType()
+ ReferenceParser.parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.ELLIPSIS |
+ ReferenceParser.WILDCARD | ReferenceParser.DISJUNCTIONS);
}
});
}
diff --git a/java/openapi/src/com/intellij/psi/PsiElementFactory.java b/java/openapi/src/com/intellij/psi/PsiElementFactory.java
index d74a242b882b..15589b5f0345 100644
--- a/java/openapi/src/com/intellij/psi/PsiElementFactory.java
+++ b/java/openapi/src/com/intellij/psi/PsiElementFactory.java
@@ -287,10 +287,10 @@ public interface PsiElementFactory extends PsiJavaParserFacade {
@NotNull PsiReferenceExpression createReferenceExpression(@NotNull PsiPackage aPackage) throws IncorrectOperationException;
/**
- * Creates a Java idenitifier with the specified text.
+ * Creates a Java identifier with the specified text.
*
* @param text the text of the identifier to create.
- * @return the idenitifier instance.
+ * @return the identifier instance.
* @throws IncorrectOperationException if text is not a valid Java identifier.
*/
@NotNull PsiIdentifier createIdentifier(@NotNull @NonNls String text) throws IncorrectOperationException;
@@ -371,6 +371,19 @@ public interface PsiElementFactory extends PsiJavaParserFacade {
@NotNull
JavaCodeFragment createCodeBlockCodeFragment(@NotNull String text, PsiElement context, boolean isPhysical);
+ /**
+ * Flag for {@linkplain #createTypeCodeFragment(String, PsiElement, boolean, int)} - allows void type.
+ */
+ int ALLOW_VOID = 0x01;
+ /**
+ * Flag for {@linkplain #createTypeCodeFragment(String, PsiElement, boolean, int)} - allows type with ellipsis.
+ */
+ int ALLOW_ELLIPSIS = 0x02;
+ /**
+ * Flag for {@linkplain #createTypeCodeFragment(String, PsiElement, boolean, int)} - allows disjunctive type.
+ */
+ int ALLOW_DISJUNCTION = 0x02;
+
/**
* Creates a Java type code fragment from the text of the name of a Java type (the name
* of a primitive type, array type or class), with void and ellipsis
@@ -386,35 +399,31 @@ public interface PsiElementFactory extends PsiJavaParserFacade {
/**
* Creates a Java type code fragment from the text of the name of a Java type (the name
- * of a primitive type, array type or class), with void optionally treated
- * as a valid type, and ellipsis not treated as a valid type.
+ * of a primitive type, array type or class).
+ * {@code void}, ellipsis and disjunctive types are optionally treated as valid ones.
*
- * @param text the text of the Java type to create.
- * @param context the context for resolving references from the code fragment.
- * @param isVoidValid whether void is a valid type for the fragment.
- * @param isPhysical whether the code fragment is created as a physical element
- * (see {@link PsiElement#isPhysical()}).
+ * @param text the text of the Java type to create.
+ * @param context the context for resolving references from the code fragment.
+ * @param isPhysical whether the code fragment is created as a physical element
+ * (see {@link PsiElement#isPhysical()}).
+ * @param flags types allowed to present in text.
* @return the created code fragment.
*/
+ @NotNull PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, PsiElement context, boolean isPhysical, int flags);
+
+ /**
+ * @deprecated use {@link #createTypeCodeFragment(String, PsiElement, boolean, int)} (todo[r.sh] to remove in IDEA 11).
+ */
@NotNull PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, PsiElement context, boolean isVoidValid, boolean isPhysical);
/**
- * Creates a Java type code fragment from the text of the name of a Java type (the name
- * of a primitive type, array type or class), with void optionally treated
- * as a valid type, and ellipsis not treated as a valid type.
- *
- * @param text the text of the Java type to create.
- * @param context the context for resolving references from the code fragment.
- * @param isVoidValid whether void is a valid type for the fragment.
- * @param isPhysical whether the code fragment is created as a physical element
- * (see {@link PsiElement#isPhysical()}).
- * @param allowEllipsis whether {@link PsiEllipsisType} is a valid type for the element.
- * @return the created code fragment.
+ * @deprecated use {@link #createTypeCodeFragment(String, PsiElement, boolean, int)} (todo[r.sh] to remove in IDEA 11).
*/
@NotNull PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text,
- PsiElement context,
- boolean isVoidValid,
- boolean isPhysical, boolean allowEllipsis);
+ PsiElement context,
+ boolean isVoidValid,
+ boolean isPhysical,
+ boolean allowEllipsis);
/**
* Returns a synthetic Java class containing methods which are defined on Java arrays.
diff --git a/java/openapi/src/com/intellij/psi/PsiTypeCodeFragment.java b/java/openapi/src/com/intellij/psi/PsiTypeCodeFragment.java
index bec5c949135c..81589dac65d5 100644
--- a/java/openapi/src/com/intellij/psi/PsiTypeCodeFragment.java
+++ b/java/openapi/src/com/intellij/psi/PsiTypeCodeFragment.java
@@ -43,9 +43,15 @@ public interface PsiTypeCodeFragment extends JavaCodeFragment {
*/
boolean isVoidValid();
- class IncorrectTypeException extends Exception {}
+ class IncorrectTypeException extends Exception {
+ public IncorrectTypeException(final String message) { super(message); }
+ }
- class TypeSyntaxException extends IncorrectTypeException {}
+ class TypeSyntaxException extends IncorrectTypeException {
+ public TypeSyntaxException(final String message) { super(message); }
+ }
- class NoTypeException extends IncorrectTypeException {}
+ class NoTypeException extends IncorrectTypeException {
+ public NoTypeException(final String message) { super(message); }
+ }
}
diff --git a/platform/util/src/com/intellij/BitUtil.java b/platform/util/src/com/intellij/BitUtil.java
new file mode 100644
index 000000000000..bab83c8d082f
--- /dev/null
+++ b/platform/util/src/com/intellij/BitUtil.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2011 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;
+
+public class BitUtil {
+ private BitUtil() { }
+
+ public static boolean isSet(final int mask, final int flag) {
+ return (mask & flag) != 0;
+ }
+}