mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
Lambda expressions support: first round
This commit is contained in:
+11
-1
@@ -2540,7 +2540,8 @@ public class HighlightUtil {
|
||||
BIN_LITERALS(LanguageLevel.JDK_1_7, "feature.binary.literals"),
|
||||
UNDERSCORES(LanguageLevel.JDK_1_7, "feature.underscores.in.literals"),
|
||||
EXTENSION_METHODS(LanguageLevel.JDK_1_8, "feature.extension.methods"),
|
||||
METHOD_REFERENCES(LanguageLevel.JDK_1_8, "feature.method.references");
|
||||
METHOD_REFERENCES(LanguageLevel.JDK_1_8, "feature.method.references"),
|
||||
LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions");
|
||||
|
||||
private final LanguageLevel level;
|
||||
private final String key;
|
||||
@@ -2617,4 +2618,13 @@ public class HighlightUtil {
|
||||
final String message = "Method references type check is not yet implemented";
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.WEAK_WARNING, expression, message);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkLambdaFeature(final PsiLambdaExpression expression) {
|
||||
final HighlightInfo info = checkFeature(expression, Feature.LAMBDA_EXPRESSIONS);
|
||||
if (info != null) return info;
|
||||
// todo[r.sh] stub; remove after implementing support in TypeConversionUtil
|
||||
final String message = "Lambda expressions type check is not yet implemented";
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.WEAK_WARNING, expression, message);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -234,7 +234,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkPolyadicOperatorApplicable(expression));
|
||||
}
|
||||
|
||||
@Override public void visitBreakStatement(PsiBreakStatement statement) {
|
||||
@Override
|
||||
public void visitLambdaExpression(PsiLambdaExpression expression) {
|
||||
myHolder.add(HighlightUtil.checkLambdaFeature(expression));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBreakStatement(PsiBreakStatement statement) {
|
||||
super.visitBreakStatement(statement);
|
||||
if (!myHolder.hasErrorResults()) {
|
||||
myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findExitedStatement()));
|
||||
|
||||
+77
-120
@@ -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.
|
||||
@@ -48,12 +48,11 @@ import java.util.*;
|
||||
public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.codeStyle.JavaCodeStyleManagerImpl");
|
||||
|
||||
@NonNls private static final String IMPL_TYPNAME_SUFFIX = "Impl";
|
||||
@NonNls private static final String IMPL_SUFFIX = "Impl";
|
||||
@NonNls private static final String GET_PREFIX = "get";
|
||||
@NonNls private static final String IS_PREFIX = "is";
|
||||
@NonNls private static final String FIND_PREFIX = "find";
|
||||
@NonNls private static final String CREATE_PREFIX = "create";
|
||||
@NonNls private static final String WITH_PREFIX = "with";
|
||||
@NonNls private static final String SET_PREFIX = "set";
|
||||
|
||||
private final Project myProject;
|
||||
@@ -72,9 +71,10 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
CheckUtil.checkWritable(element);
|
||||
if (!SourceTreeToPsiMap.hasTreeElement(element)) return element;
|
||||
|
||||
return SourceTreeToPsiMap.treeElementToPsi(
|
||||
new ReferenceAdjuster(myProject).process((TreeElement)element.getNode(), (flags & DO_NOT_ADD_IMPORTS) == 0,
|
||||
(flags & UNCOMPLETE_CODE) != 0));
|
||||
final boolean addImports = (flags & DO_NOT_ADD_IMPORTS) == 0;
|
||||
final boolean incompleteCode = (flags & UNCOMPLETE_CODE) != 0;
|
||||
final TreeElement reference = new ReferenceAdjuster(myProject).process((TreeElement)element.getNode(), addImports, incompleteCode);
|
||||
return SourceTreeToPsiMap.treeToPsiNotNull(reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,7 +88,8 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
|
||||
@Override
|
||||
public PsiElement qualifyClassReferences(@NotNull PsiElement element) {
|
||||
return SourceTreeToPsiMap.treeElementToPsi(new ReferenceAdjuster(true, true).process((TreeElement)element.getNode(), false, false));
|
||||
final TreeElement reference = new ReferenceAdjuster(true, true).process((TreeElement)element.getNode(), false, false);
|
||||
return SourceTreeToPsiMap.treeToPsiNotNull(reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,10 +118,10 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
|
||||
@Override
|
||||
public void removeRedundantImports(@NotNull final PsiJavaFile file) throws IncorrectOperationException {
|
||||
final Collection<PsiImportStatementBase> redundants = findRedundantImports(file);
|
||||
if (redundants == null) return;
|
||||
final Collection<PsiImportStatementBase> redundant = findRedundantImports(file);
|
||||
if (redundant == null) return;
|
||||
|
||||
for (final PsiImportStatementBase importStatement : redundants) {
|
||||
for (final PsiImportStatementBase importStatement : redundant) {
|
||||
final PsiJavaCodeReferenceElement ref = importStatement.getImportReference();
|
||||
//Do not remove non-resolving refs
|
||||
if (ref == null || ref.resolve() == null) {
|
||||
@@ -140,20 +141,21 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
if( imports.length == 0 ) return null;
|
||||
|
||||
Set<PsiImportStatementBase> allImports = new THashSet<PsiImportStatementBase>(Arrays.asList(imports));
|
||||
final Collection<PsiImportStatementBase> redundants;
|
||||
final Collection<PsiImportStatementBase> redundant;
|
||||
if (JspPsiUtil.isInJspFile(file)) {
|
||||
// remove only duplicate imports
|
||||
redundants = new THashSet<PsiImportStatementBase>(TObjectHashingStrategy.IDENTITY);
|
||||
ContainerUtil.addAll(redundants, imports);
|
||||
redundants.removeAll(allImports);
|
||||
@SuppressWarnings("unchecked") final TObjectHashingStrategy<PsiImportStatementBase> strategy = TObjectHashingStrategy.IDENTITY;
|
||||
redundant = new THashSet<PsiImportStatementBase>(strategy);
|
||||
ContainerUtil.addAll(redundant, imports);
|
||||
redundant.removeAll(allImports);
|
||||
for (PsiImportStatementBase importStatement : imports) {
|
||||
if (importStatement instanceof JspxImportStatement && ((JspxImportStatement)importStatement).isForeignFileImport()) {
|
||||
redundants.remove(importStatement);
|
||||
redundant.remove(importStatement);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
redundants = allImports;
|
||||
redundant = allImports;
|
||||
final List<PsiFile> roots = file.getViewProvider().getAllFiles();
|
||||
for (PsiElement root : roots) {
|
||||
root.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@@ -164,7 +166,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
final PsiElement resolveScope = resolveResult.getCurrentFileResolveScope();
|
||||
if (resolveScope instanceof PsiImportStatementBase) {
|
||||
final PsiImportStatementBase importStatementBase = (PsiImportStatementBase)resolveScope;
|
||||
redundants.remove(importStatementBase);
|
||||
redundant.remove(importStatementBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +185,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
});
|
||||
}
|
||||
}
|
||||
return redundants;
|
||||
return redundant;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -334,9 +336,10 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
|
||||
private void suggestNamesForCollectionInheritors(final PsiType type,
|
||||
final VariableKind variableKind,
|
||||
Collection<String> suggestions, boolean correctKeywords) {
|
||||
final Collection<String> suggestions,
|
||||
final boolean correctKeywords) {
|
||||
PsiType componentType = PsiUtil.extractIterableTypeParameter(type, false);
|
||||
if( componentType == null ) {
|
||||
if (componentType == null) {
|
||||
return;
|
||||
}
|
||||
String typeName = normalizeTypeName(getTypeName(componentType));
|
||||
@@ -347,12 +350,11 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
|
||||
@Nullable
|
||||
private static String normalizeTypeName(String typeName) {
|
||||
if( typeName == null )
|
||||
{
|
||||
if (typeName == null) {
|
||||
return null;
|
||||
}
|
||||
if (typeName.endsWith(IMPL_TYPNAME_SUFFIX) && typeName.length() > IMPL_TYPNAME_SUFFIX.length()) {
|
||||
return typeName.substring(0, typeName.length() - IMPL_TYPNAME_SUFFIX.length());
|
||||
if (typeName.endsWith(IMPL_SUFFIX) && typeName.length() > IMPL_SUFFIX.length()) {
|
||||
return typeName.substring(0, typeName.length() - IMPL_SUFFIX.length());
|
||||
}
|
||||
return typeName;
|
||||
}
|
||||
@@ -363,47 +365,27 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClassType classType = (PsiClassType)type;
|
||||
final String className = classType.getClassName();
|
||||
if (className != null) {
|
||||
return className;
|
||||
}
|
||||
else {
|
||||
final PsiClass aClass = classType.resolve();
|
||||
if (aClass instanceof PsiAnonymousClass) {
|
||||
return ((PsiAnonymousClass)aClass).getBaseClassType().getClassName();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (className != null) return className;
|
||||
final PsiClass aClass = classType.resolve();
|
||||
return aClass instanceof PsiAnonymousClass ? ((PsiAnonymousClass)aClass).getBaseClassType().getClassName() : null;
|
||||
}
|
||||
else if (type instanceof PsiPrimitiveType) {
|
||||
return type.getPresentableText();
|
||||
}
|
||||
else if (type instanceof PsiWildcardType) {
|
||||
return getTypeName(((PsiWildcardType)type).getExtendsBound());
|
||||
}
|
||||
else if (type instanceof PsiIntersectionType) {
|
||||
return getTypeName(((PsiIntersectionType)type).getRepresentative());
|
||||
}
|
||||
else if (type instanceof PsiCapturedWildcardType) {
|
||||
return getTypeName(((PsiCapturedWildcardType)type).getWildcard());
|
||||
}
|
||||
else if (type instanceof PsiDisjunctionType) {
|
||||
return getTypeName(((PsiDisjunctionType)type).getLeastUpperBound());
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiPrimitiveType) {
|
||||
return type.getPresentableText();
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiWildcardType) {
|
||||
return getTypeName(((PsiWildcardType)type).getExtendsBound());
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiIntersectionType) {
|
||||
return getTypeName(((PsiIntersectionType)type).getRepresentative());
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiCapturedWildcardType) {
|
||||
return getTypeName(((PsiCapturedWildcardType)type).getWildcard());
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiDisjunctionType) {
|
||||
return getTypeName(((PsiDisjunctionType)type).getLeastUpperBound());
|
||||
}
|
||||
else {
|
||||
LOG.error("Unknown type:" + type);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,66 +393,40 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
private static String getLongTypeName(PsiType type) {
|
||||
if (type instanceof PsiClassType) {
|
||||
PsiClass aClass = ((PsiClassType)type).resolve();
|
||||
if( aClass == null )
|
||||
{
|
||||
if (aClass == null) {
|
||||
return null;
|
||||
}
|
||||
if (aClass instanceof PsiAnonymousClass) {
|
||||
else if (aClass instanceof PsiAnonymousClass) {
|
||||
PsiClass baseClass = ((PsiAnonymousClass)aClass).getBaseClassType().resolve();
|
||||
if( baseClass == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return baseClass.getQualifiedName();
|
||||
}
|
||||
return aClass.getQualifiedName();
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiArrayType) {
|
||||
return getLongTypeName(((PsiArrayType)type).getComponentType()) + "[]";
|
||||
return baseClass != null ? baseClass.getQualifiedName() : null;
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiPrimitiveType) {
|
||||
return type.getPresentableText();
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiWildcardType) {
|
||||
final PsiType bound = ((PsiWildcardType)type).getBound();
|
||||
if (bound != null) {
|
||||
return getLongTypeName(bound);
|
||||
}
|
||||
else {
|
||||
return CommonClassNames.JAVA_LANG_OBJECT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiCapturedWildcardType) {
|
||||
final PsiType bound = ((PsiCapturedWildcardType)type).getWildcard().getBound();
|
||||
if (bound != null) {
|
||||
return getLongTypeName(bound);
|
||||
}
|
||||
else {
|
||||
return CommonClassNames.JAVA_LANG_OBJECT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiIntersectionType) {
|
||||
return getLongTypeName(((PsiIntersectionType)type).getRepresentative());
|
||||
}
|
||||
else {
|
||||
if (type instanceof PsiDisjunctionType) {
|
||||
return getLongTypeName(((PsiDisjunctionType)type).getLeastUpperBound());
|
||||
}
|
||||
else {
|
||||
LOG.error("Unknown type:" + type);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return aClass.getQualifiedName();
|
||||
}
|
||||
}
|
||||
else if (type instanceof PsiArrayType) {
|
||||
return getLongTypeName(((PsiArrayType)type).getComponentType()) + "[]";
|
||||
}
|
||||
else if (type instanceof PsiPrimitiveType) {
|
||||
return type.getPresentableText();
|
||||
}
|
||||
else if (type instanceof PsiWildcardType) {
|
||||
final PsiType bound = ((PsiWildcardType)type).getBound();
|
||||
return bound != null ? getLongTypeName(bound) : CommonClassNames.JAVA_LANG_OBJECT;
|
||||
}
|
||||
else if (type instanceof PsiCapturedWildcardType) {
|
||||
final PsiType bound = ((PsiCapturedWildcardType)type).getWildcard().getBound();
|
||||
return bound != null ? getLongTypeName(bound) : CommonClassNames.JAVA_LANG_OBJECT;
|
||||
}
|
||||
else if (type instanceof PsiIntersectionType) {
|
||||
return getLongTypeName(((PsiIntersectionType)type).getRepresentative());
|
||||
}
|
||||
else if (type instanceof PsiDisjunctionType) {
|
||||
return getLongTypeName(((PsiDisjunctionType)type).getLeastUpperBound());
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NamesByExprInfo {
|
||||
@@ -701,10 +657,10 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
break;
|
||||
}
|
||||
}
|
||||
PsiParameter[] parms = method.getParameterList().getParameters();
|
||||
if (index < parms.length) {
|
||||
String name = parms[index].getName();
|
||||
if (name != null && TypeConversionUtil.areTypesAssignmentCompatible(subst.substitute(parms[index].getType()), expr)) {
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (index < parameters.length) {
|
||||
String name = parameters[index].getName();
|
||||
if (name != null && TypeConversionUtil.areTypesAssignmentCompatible(subst.substitute(parameters[index].getType()), expr)) {
|
||||
name = variableNameToPropertyName(name, VariableKind.PARAMETER);
|
||||
String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords);
|
||||
if (expressions.length == 1) {
|
||||
@@ -760,6 +716,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
buffer.append(Character.toLowerCase(c));
|
||||
continue;
|
||||
}
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
i++;
|
||||
if (i < name.length()) {
|
||||
c = name.charAt(i);
|
||||
|
||||
@@ -375,4 +375,8 @@ public abstract class JavaElementVisitor extends PsiElementVisitor {
|
||||
public void visitPolyadicExpression(PsiPolyadicExpression expression) {
|
||||
visitExpression(expression);
|
||||
}
|
||||
|
||||
public void visitLambdaExpression(PsiLambdaExpression expression) {
|
||||
visitExpression(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a Java lambda expression.
|
||||
*/
|
||||
public interface PsiLambdaExpression extends PsiExpression {
|
||||
/**
|
||||
* Returns this lambda expression's parameter list.
|
||||
*
|
||||
* @return parameter list.
|
||||
*/
|
||||
@NotNull
|
||||
PsiParameterList getParameterList();
|
||||
|
||||
/**
|
||||
* Returns PSI element representing lambda expression body: {@link PsiCodeBlock}, {@link PsiExpression}, or null if none.
|
||||
*
|
||||
* @return lambda expression body.
|
||||
*/
|
||||
@Nullable
|
||||
PsiElement getBody();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A type which represents a function denoted by a lambda expression.
|
||||
*/
|
||||
public class PsiLambdaExpressionType extends PsiType {
|
||||
private final PsiLambdaExpression myExpression;
|
||||
|
||||
public PsiLambdaExpressionType(PsiLambdaExpression expression) {
|
||||
super(PsiAnnotation.EMPTY_ARRAY);
|
||||
myExpression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return "<lambda expression>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return getPresentableText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return getCanonicalText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myExpression.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsToText(@NonNls final String text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> A accept(@NotNull final PsiTypeVisitor<A> visitor) {
|
||||
return visitor.visitType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlobalSearchScope getResolveScope() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType[] getSuperTypes() {
|
||||
return PsiType.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A type which represents an omitted type for parameter of lambda expression.
|
||||
*/
|
||||
public class PsiLambdaParameterType extends PsiType {
|
||||
private final PsiParameter myParameter;
|
||||
|
||||
public PsiLambdaParameterType(PsiParameter parameter) {
|
||||
super(PsiAnnotation.EMPTY_ARRAY);
|
||||
myParameter = parameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return "<lambda parameter>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return getPresentableText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return getCanonicalText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myParameter.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsToText(@NonNls final String text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> A accept(@NotNull final PsiTypeVisitor<A> visitor) {
|
||||
return visitor.visitType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlobalSearchScope getResolveScope() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType[] getSuperTypes() {
|
||||
return PsiType.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class PsiMethodReferenceType extends PsiType {
|
||||
|
||||
@Override
|
||||
public <A> A accept(@NotNull final PsiTypeVisitor<A> visitor) {
|
||||
return visitor.visitMethodReferenceType(this);
|
||||
return visitor.visitType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -56,8 +56,4 @@ public class PsiTypeVisitor<A> {
|
||||
public A visitDiamondType(PsiDiamondType diamondType) {
|
||||
return visitType(diamondType);
|
||||
}
|
||||
|
||||
public A visitMethodReferenceType(PsiMethodReferenceType methodReferenceType) {
|
||||
return visitType(methodReferenceType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,6 +644,7 @@ public class TypeConversionUtil {
|
||||
|
||||
// todo[r.sh] implement
|
||||
if (right instanceof PsiMethodReferenceType && left instanceof PsiClassType) return true;
|
||||
if (right instanceof PsiLambdaExpressionType && left instanceof PsiClassType) return true;
|
||||
|
||||
if (left instanceof PsiIntersectionType) {
|
||||
PsiType[] conjuncts = ((PsiIntersectionType)left).getConjuncts();
|
||||
|
||||
@@ -43,6 +43,8 @@ public class DeclarationParser {
|
||||
JavaTokenType.IDENTIFIER, JavaTokenType.COMMA, JavaTokenType.EXTENDS_KEYWORD, JavaTokenType.IMPLEMENTS_KEYWORD);
|
||||
private static final TokenSet APPEND_TO_METHOD_SET = TokenSet.create(
|
||||
JavaTokenType.IDENTIFIER, JavaTokenType.COMMA, JavaTokenType.THROWS_KEYWORD);
|
||||
private static final TokenSet PARAM_LIST_STOPPERS = TokenSet.create(
|
||||
JavaTokenType.RPARENTH, JavaTokenType.LBRACE, JavaTokenType.ARROW);
|
||||
|
||||
private static final String WHITESPACES = "\n\r \t";
|
||||
private static final String LINE_ENDS = "\n\r";
|
||||
@@ -456,19 +458,28 @@ public class DeclarationParser {
|
||||
|
||||
@NotNull
|
||||
public PsiBuilder.Marker parseParameterList(final PsiBuilder builder) {
|
||||
return parseElementList(builder, false);
|
||||
return parseElementList(builder, ListType.NORMAL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiBuilder.Marker parseResourceList(final PsiBuilder builder) {
|
||||
return parseElementList(builder, true);
|
||||
return parseElementList(builder, ListType.RESOURCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiBuilder.Marker parseElementList(final PsiBuilder builder, final boolean resources) {
|
||||
assert builder.getTokenType() == JavaTokenType.LPARENTH : builder.getTokenType();
|
||||
public PsiBuilder.Marker parseLambdaParameterList(final PsiBuilder builder, final boolean typed) {
|
||||
return parseElementList(builder, typed ? ListType.LAMBDA_TYPED : ListType.LAMBDA_UNTYPED);
|
||||
}
|
||||
|
||||
private enum ListType { NORMAL, RESOURCE, LAMBDA_TYPED, LAMBDA_UNTYPED }
|
||||
|
||||
@NotNull
|
||||
private PsiBuilder.Marker parseElementList(final PsiBuilder builder, final ListType type) {
|
||||
final boolean lambda = (type == ListType.LAMBDA_TYPED || type == ListType.LAMBDA_UNTYPED);
|
||||
final boolean resources = (type == ListType.RESOURCE);
|
||||
final PsiBuilder.Marker elementList = builder.mark();
|
||||
builder.advanceLexer();
|
||||
final boolean leftParenth = expect(builder, JavaTokenType.LPARENTH);
|
||||
assert lambda || leftParenth : builder.getTokenType();
|
||||
|
||||
final IElementType delimiter = resources ? JavaTokenType.SEMICOLON : JavaTokenType.COMMA;
|
||||
final String noDelimiterMsg = resources ? "expected.semicolon" : "expected.comma";
|
||||
@@ -480,10 +491,11 @@ public class DeclarationParser {
|
||||
boolean noElements = true;
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == null || tokenType == JavaTokenType.RPARENTH || tokenType == JavaTokenType.LBRACE) {
|
||||
if (tokenType == null || PARAM_LIST_STOPPERS.contains(tokenType)) {
|
||||
final boolean noLastElement = !delimiterExpected && (!noElements && !resources || noElements && resources);
|
||||
if (noLastElement) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier.or.type"));
|
||||
final String key = lambda ? "expected.parameter" : "expected.identifier.or.type";
|
||||
error(builder, JavaErrorMessages.message(key));
|
||||
}
|
||||
if (tokenType == JavaTokenType.RPARENTH) {
|
||||
if (invalidElements != null) {
|
||||
@@ -498,7 +510,9 @@ public class DeclarationParser {
|
||||
invalidElements.error(errorMessage);
|
||||
}
|
||||
invalidElements = null;
|
||||
error(builder, JavaErrorMessages.message("expected.rparen"));
|
||||
if (leftParenth) {
|
||||
error(builder, JavaErrorMessages.message("expected.rparen"));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -516,7 +530,9 @@ public class DeclarationParser {
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PsiBuilder.Marker listElement = resources ? parseResource(builder) : parseParameter(builder, true, false);
|
||||
final PsiBuilder.Marker listElement = resources ? parseResource(builder) :
|
||||
lambda ? parseLambdaParameter(builder, type == ListType.LAMBDA_TYPED) :
|
||||
parseParameter(builder, true, false);
|
||||
if (listElement != null) {
|
||||
delimiterExpected = true;
|
||||
if (invalidElements != null) {
|
||||
@@ -562,36 +578,45 @@ public class DeclarationParser {
|
||||
|
||||
@Nullable
|
||||
public PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunctiveType) {
|
||||
return parseListElement(builder, ellipsis, disjunctiveType, false);
|
||||
return parseListElement(builder, true, ellipsis, disjunctiveType, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiBuilder.Marker parseResource(final PsiBuilder builder) {
|
||||
return parseListElement(builder, false, false, true);
|
||||
return parseListElement(builder, true, false, false, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiBuilder.Marker parseLambdaParameter(final PsiBuilder builder, final boolean typed) {
|
||||
return parseListElement(builder, typed, true, false, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiBuilder.Marker parseListElement(final PsiBuilder builder,
|
||||
final boolean ellipsis,
|
||||
final boolean disjunctiveType,
|
||||
final boolean resource) {
|
||||
final boolean typed,
|
||||
final boolean ellipsis,
|
||||
final boolean disjunctiveType,
|
||||
final boolean resource) {
|
||||
final PsiBuilder.Marker param = builder.mark();
|
||||
|
||||
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
|
||||
|
||||
int flags = ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD;
|
||||
if (ellipsis) flags |= ReferenceParser.ELLIPSIS;
|
||||
if (disjunctiveType) flags |= ReferenceParser.DISJUNCTIONS;
|
||||
final ReferenceParser.TypeInfo typeInfo = myParser.getReferenceParser().parseTypeInfo(builder, flags);
|
||||
ReferenceParser.TypeInfo typeInfo = null;
|
||||
if (typed) {
|
||||
int flags = ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD;
|
||||
if (ellipsis) flags |= ReferenceParser.ELLIPSIS;
|
||||
if (disjunctiveType) flags |= ReferenceParser.DISJUNCTIONS;
|
||||
typeInfo = myParser.getReferenceParser().parseTypeInfo(builder, flags);
|
||||
|
||||
if (typeInfo == null) {
|
||||
if (modListInfo.second) {
|
||||
param.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.type"));
|
||||
emptyElement(builder, JavaElementType.TYPE);
|
||||
if (typeInfo == null) {
|
||||
if (modListInfo.second) {
|
||||
param.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.type"));
|
||||
emptyElement(builder, JavaElementType.TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -514,6 +514,19 @@ public class ExpressionParser {
|
||||
|
||||
if (tokenType == JavaTokenType.LPARENTH) {
|
||||
final PsiBuilder.Marker parenth = builder.mark();
|
||||
|
||||
final IElementType nextToken1 = builder.lookAhead(1);
|
||||
final IElementType nextToken2 = builder.lookAhead(2);
|
||||
if (nextToken1 == JavaTokenType.IDENTIFIER) {
|
||||
if (nextToken2 == JavaTokenType.COMMA ||
|
||||
nextToken2 == JavaTokenType.RPARENTH && builder.lookAhead(3) == JavaTokenType.ARROW) {
|
||||
return parseLambdaExpression(builder, parenth, false);
|
||||
}
|
||||
}
|
||||
else if (nextToken1 == JavaTokenType.RPARENTH && nextToken2 == JavaTokenType.ARROW) {
|
||||
return parseLambdaExpression(builder, parenth, false);
|
||||
}
|
||||
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker inner = parse(builder);
|
||||
@@ -554,6 +567,10 @@ public class ExpressionParser {
|
||||
}
|
||||
|
||||
if (tokenType == JavaTokenType.IDENTIFIER) {
|
||||
if (builder.lookAhead(1) == JavaTokenType.ARROW) {
|
||||
return parseLambdaExpression(builder, builder.mark(), false);
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker refExpr;
|
||||
if (annotation != null) {
|
||||
final PsiBuilder.Marker refParam = annotation.precede();
|
||||
@@ -810,6 +827,32 @@ public class ExpressionParser {
|
||||
return start;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiBuilder.Marker parseLambdaExpression(final PsiBuilder builder, final PsiBuilder.Marker start, final boolean typed) {
|
||||
myParser.getDeclarationParser().parseLambdaParameterList(builder, typed);
|
||||
return parseLambdaExpressionFromArrow(builder, start);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiBuilder.Marker parseLambdaExpressionFromArrow(final PsiBuilder builder, final PsiBuilder.Marker start) {
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker body;
|
||||
if (builder.getTokenType() == JavaTokenType.LBRACE) {
|
||||
body = myParser.getStatementParser().parseCodeBlock(builder);
|
||||
}
|
||||
else {
|
||||
body = parse(builder);
|
||||
}
|
||||
|
||||
if (body == null) {
|
||||
builder.error(JavaErrorMessages.message("expected.lbrace"));
|
||||
}
|
||||
|
||||
start.done(JavaElementType.LAMBDA_EXPRESSION);
|
||||
return start;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiBuilder.Marker parseArgumentList(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker list = builder.mark();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.
|
||||
@@ -17,9 +17,7 @@ package com.intellij.psi.impl.source;
|
||||
|
||||
import com.intellij.lang.LighterAST;
|
||||
import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.impl.ASTNodeBuilder;
|
||||
import com.intellij.lang.impl.PsiBuilderImpl;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
@@ -32,7 +30,6 @@ import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.io.StringRef;
|
||||
|
||||
|
||||
public class JavaLightStubBuilder extends LightStubBuilder {
|
||||
@Override
|
||||
protected StubElement createStubForFile(final PsiFile file, final LighterAST tree) {
|
||||
@@ -53,20 +50,17 @@ public class JavaLightStubBuilder extends LightStubBuilder {
|
||||
|
||||
@Override
|
||||
public boolean skipChildProcessingWhenBuildingStubs(final IElementType nodeType, final IElementType childType) {
|
||||
return childType == JavaElementType.PARAMETER && nodeType != JavaElementType.PARAMETER_LIST;
|
||||
return childType == JavaElementType.PARAMETER && nodeType != JavaElementType.PARAMETER_LIST ||
|
||||
childType == JavaElementType.PARAMETER_LIST && nodeType == JavaElementType.LAMBDA_EXPRESSION;
|
||||
}
|
||||
|
||||
static int totalMethods;
|
||||
static int nonexpandedMethods;
|
||||
|
||||
@Override
|
||||
public boolean skipChildProcessingWhenBuildingStubs(LightStubBuilder builder,
|
||||
LighterAST tree,
|
||||
LighterASTNode parent,
|
||||
LighterASTNode child) {
|
||||
public boolean skipChildProcessingWhenBuildingStubs(final LightStubBuilder builder,
|
||||
final LighterAST tree,
|
||||
final LighterASTNode parent,
|
||||
final LighterASTNode child) {
|
||||
if (child.getTokenType() == JavaElementType.CODE_BLOCK) {
|
||||
if (child instanceof ASTNodeBuilder.ASTUnparsedNodeMarker) {
|
||||
++totalMethods;
|
||||
ASTNodeBuilder.ASTUnparsedNodeMarker nodeMarker = (ASTNodeBuilder.ASTUnparsedNodeMarker)child;
|
||||
final ASTNodeBuilder nodeBuilder = nodeMarker.getBuilder();
|
||||
final int endLexemIndex = nodeMarker.getEndLexemIndex();
|
||||
@@ -89,7 +83,6 @@ public class JavaLightStubBuilder extends LightStubBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
++nonexpandedMethods;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -167,7 +167,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
|
||||
}
|
||||
|
||||
myCachedType = null;
|
||||
return JavaSharedImplUtil.getType(this);
|
||||
return JavaSharedImplUtil.getType(getTypeElement(), getNameIdentifier(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -118,7 +118,13 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
|
||||
}
|
||||
|
||||
myCachedType = null;
|
||||
return JavaSharedImplUtil.getType(this);
|
||||
|
||||
final PsiTypeElement typeElement = getTypeElement();
|
||||
if (typeElement == null && isLambdaParameter()) {
|
||||
return new PsiLambdaParameterType(this);
|
||||
}
|
||||
|
||||
return JavaSharedImplUtil.getType(typeElement, getNameIdentifier(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -134,13 +140,21 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
|
||||
return null;
|
||||
}
|
||||
}
|
||||
PsiTypeElement typeElement = getTypeElement();
|
||||
PsiIdentifier nameIdentifier = getNameIdentifier();
|
||||
return JavaSharedImplUtil.getTypeNoResolve(typeElement, nameIdentifier, this);
|
||||
|
||||
final PsiTypeElement typeElement = getTypeElement();
|
||||
if (typeElement == null && isLambdaParameter()) {
|
||||
return new PsiLambdaParameterType(this);
|
||||
}
|
||||
|
||||
return JavaSharedImplUtil.getTypeNoResolve(typeElement, getNameIdentifier(), this);
|
||||
}
|
||||
|
||||
private boolean isLambdaParameter() {
|
||||
final PsiElement parent = getParent();
|
||||
return parent instanceof PsiParameterList && parent.getParent() instanceof PsiLambdaExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiTypeElement getTypeElement() {
|
||||
return (PsiTypeElement)getNode().findChildByRoleAsPsiElement(ChildRole.TYPE);
|
||||
}
|
||||
@@ -233,7 +247,8 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
|
||||
}
|
||||
|
||||
myCachedType = null;
|
||||
return SourceTreeToPsiMap.psiToTreeNotNull(getTypeElement()).findChildByType(JavaTokenType.ELLIPSIS) != null;
|
||||
final PsiTypeElement typeElement = getTypeElement();
|
||||
return typeElement != null && SourceTreeToPsiMap.psiToTreeNotNull(typeElement).findChildByType(JavaTokenType.ELLIPSIS) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -54,7 +54,7 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
|
||||
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, METHOD_REF_EXPRESSION, EMPTY_EXPRESSION);
|
||||
CLASS_OBJECT_ACCESS_EXPRESSION, METHOD_REF_EXPRESSION, LAMBDA_EXPRESSION, EMPTY_EXPRESSION);
|
||||
|
||||
TokenSet ANNOTATION_MEMBER_VALUE_BIT_SET = TokenSet.orSet(EXPRESSION_BIT_SET,
|
||||
TokenSet.create(ANNOTATION, ANNOTATION_ARRAY_INITIALIZER));
|
||||
|
||||
@@ -105,6 +105,7 @@ public interface JavaElementType {
|
||||
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 LAMBDA_EXPRESSION = new JavaCompositeElementType("LAMBDA_EXPRESSION", PsiLambdaExpressionImpl.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);
|
||||
|
||||
@@ -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.
|
||||
@@ -32,30 +32,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class JavaSharedImplUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.JavaSharedImplUtil");
|
||||
|
||||
private JavaSharedImplUtil() {
|
||||
}
|
||||
|
||||
public static PsiType getType(PsiVariable variable) {
|
||||
PsiTypeElement typeElement = variable.getTypeElement();
|
||||
PsiIdentifier nameIdentifier = variable.getNameIdentifier();
|
||||
return getType(typeElement, nameIdentifier, variable);
|
||||
}
|
||||
private JavaSharedImplUtil() { }
|
||||
|
||||
public static PsiType getType(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor, @NotNull PsiElement context) {
|
||||
int cStyleArrayCount = 0;
|
||||
ASTNode name = SourceTreeToPsiMap.psiElementToTree(anchor);
|
||||
for (ASTNode child = name.getTreeNext(); child != null; child = child.getTreeNext()) {
|
||||
IElementType i = child.getElementType();
|
||||
if (i == JavaTokenType.LBRACKET) {
|
||||
cStyleArrayCount++;
|
||||
}
|
||||
else if (i != JavaTokenType.RBRACKET && i != TokenType.WHITE_SPACE &&
|
||||
i != JavaTokenType.C_STYLE_COMMENT &&
|
||||
i != JavaDocElementType.DOC_COMMENT &&
|
||||
i != JavaTokenType.END_OF_LINE_COMMENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int cStyleArrayCount = countBrackets(anchor);
|
||||
PsiType type;
|
||||
if (typeElement instanceof PsiTypeElementImpl) {
|
||||
type = ((PsiTypeElementImpl)typeElement).getDetachedType(context);
|
||||
@@ -63,33 +43,34 @@ public class JavaSharedImplUtil {
|
||||
else {
|
||||
type = typeElement.getType();
|
||||
}
|
||||
|
||||
for (int i = 0; i < cStyleArrayCount; i++) {
|
||||
type = type.createArrayType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static PsiType getTypeNoResolve(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor, @NotNull PsiElement context) {
|
||||
int cStyleArrayCount = countBrackets(anchor);
|
||||
PsiType type = typeElement.getTypeNoResolve(context);
|
||||
for (int i = 0; i < cStyleArrayCount; i++) {
|
||||
type = type.createArrayType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static int countBrackets(PsiElement anchor) {
|
||||
int cStyleArrayCount = 0;
|
||||
ASTNode name = SourceTreeToPsiMap.psiElementToTree(anchor);
|
||||
ASTNode name = SourceTreeToPsiMap.psiToTreeNotNull(anchor);
|
||||
for (ASTNode child = name.getTreeNext(); child != null; child = child.getTreeNext()) {
|
||||
IElementType i = child.getElementType();
|
||||
if (i == JavaTokenType.LBRACKET) {
|
||||
cStyleArrayCount++;
|
||||
}
|
||||
else if (i != JavaTokenType.RBRACKET && i != TokenType.WHITE_SPACE &&
|
||||
i != JavaTokenType.C_STYLE_COMMENT &&
|
||||
i != JavaDocElementType.DOC_COMMENT &&
|
||||
i != JavaTokenType.END_OF_LINE_COMMENT) {
|
||||
else if (i != JavaTokenType.RBRACKET && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
PsiType type = typeElement.getTypeNoResolve(context);
|
||||
|
||||
for (int i = 0; i < cStyleArrayCount; i++) {
|
||||
type = type.createArrayType();
|
||||
}
|
||||
return type;
|
||||
return cStyleArrayCount;
|
||||
}
|
||||
|
||||
public static void normalizeBrackets(PsiVariable variable) {
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements PsiLambdaExpression {
|
||||
public PsiLambdaExpressionImpl() {
|
||||
super(JavaElementType.LAMBDA_EXPRESSION);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiParameterList getParameterList() {
|
||||
return PsiTreeUtil.getRequiredChildOfType(this, PsiParameterList.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public PsiElement getBody() {
|
||||
return PsiTreeUtil.getChildOfAnyType(this, PsiExpression.class, PsiCodeBlock.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return new PsiLambdaExpressionType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull final PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor)visitor).visitLambdaExpression(this);
|
||||
}
|
||||
else {
|
||||
visitor.visitElement(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiLambdaExpression:" + getText();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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.
|
||||
@@ -95,7 +95,7 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca
|
||||
@Override
|
||||
@NotNull
|
||||
public final PsiType getType() {
|
||||
return JavaSharedImplUtil.getType(this);
|
||||
return JavaSharedImplUtil.getType(getTypeElement(), getNameIdentifier(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
@@ -158,6 +158,7 @@ public class ReplaceExpressionUtil {
|
||||
i == JavaElementType.ARRAY_INITIALIZER_EXPRESSION ||
|
||||
i == JavaElementType.JAVA_CODE_REFERENCE ||
|
||||
i == JavaElementType.METHOD_REF_EXPRESSION ||
|
||||
i == JavaElementType.LAMBDA_EXPRESSION ||
|
||||
i == JavaElementType.EMPTY_EXPRESSION) {
|
||||
return 14;
|
||||
}
|
||||
|
||||
@@ -354,4 +354,5 @@ feature.binary.literals=Binary literals
|
||||
feature.underscores.in.literals=Underscores in literals
|
||||
feature.extension.methods=Extension methods
|
||||
feature.method.references=Method references
|
||||
feature.lambda.expressions=Lambda expressions
|
||||
insufficient.language.level={0} are not supported at this language level
|
||||
|
||||
+3
-1
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
@@ -38,7 +39,8 @@ class UnsupportedFeatures {
|
||||
|
||||
try <error descr="Try-with-resources are not supported at this language level">(Reader r = new FileReader("/dev/null"))</error> { }
|
||||
|
||||
I i = <error descr="Method references are not supported at this language level">UnsupportedFeatures::m</error>;
|
||||
I i1 = <error descr="Method references are not supported at this language level">UnsupportedFeatures::m</error>;
|
||||
I i2 = <error descr="Lambda expressions are not supported at this language level">() -> { }</error>;
|
||||
}
|
||||
|
||||
interface I {
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 use(Simplest s) { }
|
||||
|
||||
void test() {
|
||||
Simplest simplest = <weak_warning descr="Lambda expressions type check is not yet implemented">() -> { }</weak_warning>;
|
||||
use(<weak_warning descr="Lambda expressions type check is not yet implemented">() -> { }</weak_warning>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:LambdaExpression0.java
|
||||
PsiLambdaExpression:p -> 42
|
||||
PsiParameterList:p
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:42
|
||||
PsiJavaToken:INTEGER_LITERAL('42')
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:LambdaExpression1.java
|
||||
PsiLambdaExpression:p ->
|
||||
PsiParameterList:p
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiErrorElement:'{' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
@@ -0,0 +1,23 @@
|
||||
PsiJavaFile:LambdaExpression10.java
|
||||
PsiTypeCastExpression:(I)(p -> null)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiTypeElement:I
|
||||
PsiJavaCodeReferenceElement:I
|
||||
PsiIdentifier:I('I')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiParenthesizedExpression:(p -> null)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLambdaExpression:p -> null
|
||||
PsiParameterList:p
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:LambdaExpression11.java
|
||||
PsiLambdaExpression:() -> { }
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,14 @@
|
||||
PsiJavaFile:LambdaExpression2.java
|
||||
PsiLambdaExpression:p -> {
|
||||
PsiParameterList:p
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiErrorElement:'}' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:LambdaExpression3.java
|
||||
PsiLambdaExpression:(p) -> { }
|
||||
PsiParameterList:(p)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,20 @@
|
||||
PsiJavaFile:LambdaExpression4.java
|
||||
PsiLambdaExpression:(p, v) -> null
|
||||
PsiParameterList:(p, v)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiParameter:v
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:v('v')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
@@ -0,0 +1,21 @@
|
||||
PsiJavaFile:LambdaExpression5.java
|
||||
PsiLambdaExpression:(p, v -> null
|
||||
PsiParameterList:(p, v
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiParameter:v
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:v('v')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:LambdaExpression6.java
|
||||
PsiLambdaExpression:(p, v, -> null
|
||||
PsiParameterList:(p, v,
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiParameter:v
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:v('v')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Parameter expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:LambdaExpression7.java
|
||||
PsiParenthesizedExpression:(p -> null)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLambdaExpression:p -> null
|
||||
PsiParameterList:p
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:LambdaExpression8.java
|
||||
PsiTypeCastExpression:(I)(p) -> null
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiTypeElement:I
|
||||
PsiJavaCodeReferenceElement:I
|
||||
PsiIdentifier:I('I')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiLambdaExpression:(p) -> null
|
||||
PsiParameterList:(p)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
@@ -0,0 +1,20 @@
|
||||
PsiJavaFile:LambdaExpression9.java
|
||||
PsiTypeCastExpression:(I)p -> null
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiTypeElement:I
|
||||
PsiJavaCodeReferenceElement:I
|
||||
PsiIdentifier:I('I')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiLambdaExpression:p -> null
|
||||
PsiParameterList:p
|
||||
PsiParameter:p
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:p('p')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
+1
@@ -146,4 +146,5 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
|
||||
public void testClassLiteral() throws Exception { doTest(false, false); }
|
||||
public void testExtensionMethods() throws Exception { doTest(false, false); }
|
||||
public void testMethodReferences() throws Exception { doTest(false, true, false); }
|
||||
public void testLambdaExpressions() throws Exception { doTest(false, true, false); }
|
||||
}
|
||||
|
||||
+13
@@ -122,6 +122,19 @@ public class ExpressionParserTest extends JavaParsingTestCase {
|
||||
public void testMethodRef4() { doParserTest("int[]::clone"); }
|
||||
public void testMethodRef5() { doParserTest("(f ? list.map(String::length) : Collections.emptyList())::iterator"); }
|
||||
|
||||
public void testLambdaExpression0() { doParserTest("p -> 42"); }
|
||||
public void testLambdaExpression1() { doParserTest("p -> "); }
|
||||
public void testLambdaExpression2() { doParserTest("p -> {"); }
|
||||
public void testLambdaExpression3() { doParserTest("(p) -> { }"); }
|
||||
public void testLambdaExpression4() { doParserTest("(p, v) -> null"); }
|
||||
public void testLambdaExpression5() { doParserTest("(p, v -> null"); }
|
||||
public void testLambdaExpression6() { doParserTest("(p, v, -> null"); }
|
||||
public void testLambdaExpression7() { doParserTest("(p -> null)"); }
|
||||
public void testLambdaExpression8() { doParserTest("(I)(p) -> null"); }
|
||||
public void testLambdaExpression9() { doParserTest("(I)p -> null"); }
|
||||
public void testLambdaExpression10() { doParserTest("(I)(p -> null)"); }
|
||||
public void testLambdaExpression11() { doParserTest("() -> { }"); }
|
||||
|
||||
private void doParserTest(@NonNls final String text) {
|
||||
doParserTest(text, new MyTestParser());
|
||||
}
|
||||
|
||||
@@ -221,6 +221,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
|
||||
doTest("class C { {\n" +
|
||||
" new O.P() { };\n" +
|
||||
" X.new Y() { };\n" +
|
||||
" f(p -> new R() { });\n" +
|
||||
"} }",
|
||||
|
||||
"PsiJavaFileStub []\n" +
|
||||
@@ -233,7 +234,8 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
|
||||
" CLASS_INITIALIZER:PsiClassInitializerStub\n" +
|
||||
" MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" +
|
||||
" ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=O.P]\n" +
|
||||
" ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=Y inqualifnew]\n");
|
||||
" ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=Y inqualifnew]\n" +
|
||||
" ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=R]\n");
|
||||
}
|
||||
|
||||
public void testEnums() {
|
||||
|
||||
Reference in New Issue
Block a user