mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] switch expressions: parser/PSI (IDEA-196643)
This commit is contained in:
@@ -381,6 +381,10 @@ public abstract class JavaElementVisitor extends PsiElementVisitor {
|
||||
visitExpression(expression);
|
||||
}
|
||||
|
||||
public void visitSwitchExpression(PsiSwitchExpression expression) {
|
||||
visitExpression(expression);
|
||||
}
|
||||
|
||||
public void visitModule(PsiJavaModule module) {
|
||||
visitElement(module);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a Java {@code switch} statement or {@code switch} expression.
|
||||
*
|
||||
* @see PsiSwitchStatement
|
||||
* @see PsiSwitchExpression
|
||||
*/
|
||||
public interface PsiSwitchBlock extends PsiElement {
|
||||
/**
|
||||
* Returns the expression on which the switch is performed, or {@code null} if the statement is incomplete.
|
||||
*/
|
||||
@Nullable PsiExpression getExpression();
|
||||
|
||||
/**
|
||||
* Returns the body of the switch statement, or {@code null} if the statement is incomplete.
|
||||
*/
|
||||
@Nullable PsiCodeBlock getBody();
|
||||
|
||||
@Nullable PsiJavaToken getLParenth();
|
||||
@Nullable PsiJavaToken getRParenth();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi;
|
||||
|
||||
/**
|
||||
* Represents a Java {@code switch} expression.
|
||||
*
|
||||
* @see PsiSwitchLabelStatement
|
||||
* @see PsiSwitchLabeledRuleStatement
|
||||
*/
|
||||
public interface PsiSwitchExpression extends PsiSwitchBlock, PsiExpression { }
|
||||
@@ -1,30 +1,10 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a Java {@code switch} statement.
|
||||
*
|
||||
* @see PsiSwitchLabelStatement
|
||||
* @see PsiSwitchLabeledRuleStatement
|
||||
*/
|
||||
public interface PsiSwitchStatement extends PsiStatement {
|
||||
/**
|
||||
* Returns the expression on which the switch is performed, or {@code null} if the statement is incomplete.
|
||||
*/
|
||||
@Nullable
|
||||
PsiExpression getExpression();
|
||||
|
||||
/**
|
||||
* Returns the body of the switch statement, or {@code null} if the statement is incomplete.
|
||||
*/
|
||||
@Nullable
|
||||
PsiCodeBlock getBody();
|
||||
|
||||
@Nullable
|
||||
PsiJavaToken getLParenth();
|
||||
|
||||
@Nullable
|
||||
PsiJavaToken getRParenth();
|
||||
}
|
||||
public interface PsiSwitchStatement extends PsiSwitchBlock, PsiStatement { }
|
||||
@@ -295,6 +295,9 @@ public class ExpressionParser {
|
||||
typeCast.done(JavaElementType.TYPE_CAST_EXPRESSION);
|
||||
return typeCast;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.SWITCH_KEYWORD) {
|
||||
return myParser.getStatementParser().parseExprInParenthWithBlock(builder, JavaElementType.SWITCH_EXPRESSION, true);
|
||||
}
|
||||
else {
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ public class StatementParser {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiBuilder.Marker parseExprInParenthWithBlock(PsiBuilder builder, IElementType type, boolean block) {
|
||||
public PsiBuilder.Marker parseExprInParenthWithBlock(@NotNull PsiBuilder builder, @NotNull IElementType type, boolean block) {
|
||||
PsiBuilder.Marker statement = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
|
||||
@@ -39,7 +39,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, LAMBDA_EXPRESSION, EMPTY_EXPRESSION);
|
||||
CLASS_OBJECT_ACCESS_EXPRESSION, METHOD_REF_EXPRESSION, LAMBDA_EXPRESSION, SWITCH_EXPRESSION, EMPTY_EXPRESSION);
|
||||
|
||||
TokenSet ANNOTATION_MEMBER_VALUE_BIT_SET = TokenSet.orSet(EXPRESSION_BIT_SET, TokenSet.create(ANNOTATION, ANNOTATION_ARRAY_INITIALIZER));
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ public interface JavaElementType {
|
||||
IElementType FOREACH_STATEMENT = new JavaCompositeElementType("FOREACH_STATEMENT", PsiForeachStatementImpl::new);
|
||||
IElementType DO_WHILE_STATEMENT = new JavaCompositeElementType("DO_WHILE_STATEMENT", PsiDoWhileStatementImpl::new);
|
||||
IElementType SWITCH_STATEMENT = new JavaCompositeElementType("SWITCH_STATEMENT", PsiSwitchStatementImpl::new);
|
||||
IElementType SWITCH_EXPRESSION = new JavaCompositeElementType("SWITCH_EXPRESSION", PsiSwitchExpressionImpl::new);
|
||||
IElementType SWITCH_LABEL_STATEMENT = new JavaCompositeElementType("SWITCH_LABEL_STATEMENT", PsiSwitchLabelStatementImpl::new);
|
||||
IElementType SWITCH_LABELED_RULE = new JavaCompositeElementType("SWITCH_LABELED_RULE", PsiSwitchLabeledRuleStatementImpl::new);
|
||||
IElementType BREAK_STATEMENT = new JavaCompositeElementType("BREAK_STATEMENT", PsiBreakStatementImpl::new);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.impl.source.tree.java;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.CompositePsiElement;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
|
||||
public abstract class PsiSwitchBlockImpl extends CompositePsiElement implements PsiSwitchBlock {
|
||||
protected PsiSwitchBlockImpl(IElementType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiExpression getExpression() {
|
||||
return (PsiExpression)findPsiChildByType(ElementType.EXPRESSION_BIT_SET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiCodeBlock getBody() {
|
||||
return (PsiCodeBlock)findPsiChildByType(JavaElementType.CODE_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiJavaToken getLParenth() {
|
||||
return (PsiJavaToken)findPsiChildByType(JavaTokenType.LPARENTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiJavaToken getRParenth() {
|
||||
return (PsiJavaToken)findPsiChildByType(JavaTokenType.RPARENTH);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.impl.source.tree.java;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaSourceUtil;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PsiSwitchExpressionImpl extends PsiSwitchBlockImpl implements PsiSwitchExpression {
|
||||
public PsiSwitchExpressionImpl() {
|
||||
super(JavaElementType.SWITCH_EXPRESSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiExpression getExpression() {
|
||||
return (PsiExpression)findPsiChildByType(ElementType.EXPRESSION_BIT_SET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return null; //tbd
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor)visitor).visitSwitchExpression(this);
|
||||
}
|
||||
else {
|
||||
super.accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceChildInternal(@NotNull ASTNode child, @NotNull TreeElement newElement) {
|
||||
super.replaceChildInternal(child, JavaSourceUtil.addParenthToReplacedChild(child, newElement, getManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
PsiExpression expression = getExpression();
|
||||
return "PsiSwitchExpression: " + (expression != null ? expression.getText() : "(incomplete)");
|
||||
}
|
||||
}
|
||||
+25
-81
@@ -1,78 +1,36 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.impl.source.tree.java;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.Constants;
|
||||
import com.intellij.psi.JavaElementVisitor;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiSwitchStatement;
|
||||
import com.intellij.psi.impl.source.tree.ChildRole;
|
||||
import com.intellij.psi.impl.source.tree.CompositePsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.ChildRoleBase;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PsiSwitchStatementImpl extends CompositePsiElement implements PsiSwitchStatement, Constants {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiSwitchStatementImpl");
|
||||
public class PsiSwitchStatementImpl extends PsiSwitchBlockImpl implements PsiSwitchStatement {
|
||||
private static final Logger LOG = Logger.getInstance(PsiSwitchBlockImpl.class);
|
||||
|
||||
public PsiSwitchStatementImpl() {
|
||||
super(SWITCH_STATEMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiExpression getExpression() {
|
||||
return (PsiExpression)findChildByRoleAsPsiElement(ChildRole.SWITCH_EXPRESSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiCodeBlock getBody() {
|
||||
return (PsiCodeBlock)findChildByRoleAsPsiElement(ChildRole.SWITCH_BODY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiJavaToken getLParenth() {
|
||||
return (PsiJavaToken)findChildByRoleAsPsiElement(ChildRole.LPARENTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiJavaToken getRParenth() {
|
||||
return (PsiJavaToken)findChildByRoleAsPsiElement(ChildRole.RPARENTH);
|
||||
super(JavaElementType.SWITCH_STATEMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode findChildByRole(int role) {
|
||||
LOG.assertTrue(ChildRole.isUnique(role));
|
||||
switch(role){
|
||||
default:
|
||||
return null;
|
||||
|
||||
case ChildRole.SWITCH_KEYWORD:
|
||||
return findChildByType(SWITCH_KEYWORD);
|
||||
|
||||
case ChildRole.LPARENTH:
|
||||
return findChildByType(LPARENTH);
|
||||
|
||||
case ChildRole.SWITCH_EXPRESSION:
|
||||
return findChildByType(EXPRESSION_BIT_SET);
|
||||
|
||||
case ChildRole.RPARENTH:
|
||||
return findChildByType(RPARENTH);
|
||||
|
||||
case ChildRole.SWITCH_BODY:
|
||||
return findChildByType(CODE_BLOCK);
|
||||
switch (role) {
|
||||
case ChildRole.SWITCH_KEYWORD: return findChildByType(JavaTokenType.SWITCH_KEYWORD);
|
||||
case ChildRole.LPARENTH: return findChildByType(JavaTokenType.LPARENTH);
|
||||
case ChildRole.SWITCH_EXPRESSION: return findChildByType(ElementType.EXPRESSION_BIT_SET);
|
||||
case ChildRole.RPARENTH: return findChildByType(JavaTokenType.RPARENTH);
|
||||
case ChildRole.SWITCH_BODY: return findChildByType(JavaElementType.CODE_BLOCK);
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,26 +38,12 @@ public class PsiSwitchStatementImpl extends CompositePsiElement implements PsiSw
|
||||
public int getChildRole(@NotNull ASTNode child) {
|
||||
LOG.assertTrue(child.getTreeParent() == this);
|
||||
IElementType i = child.getElementType();
|
||||
if (i == SWITCH_KEYWORD) {
|
||||
return ChildRole.SWITCH_KEYWORD;
|
||||
}
|
||||
else if (i == LPARENTH) {
|
||||
return ChildRole.LPARENTH;
|
||||
}
|
||||
else if (i == RPARENTH) {
|
||||
return ChildRole.RPARENTH;
|
||||
}
|
||||
else {
|
||||
if (EXPRESSION_BIT_SET.contains(child.getElementType())) {
|
||||
return ChildRole.SWITCH_EXPRESSION;
|
||||
}
|
||||
else if (child.getElementType() == CODE_BLOCK) {
|
||||
return ChildRole.SWITCH_BODY;
|
||||
}
|
||||
else {
|
||||
return ChildRoleBase.NONE;
|
||||
}
|
||||
}
|
||||
if (i == JavaTokenType.SWITCH_KEYWORD) return ChildRole.SWITCH_KEYWORD;
|
||||
if (i == JavaTokenType.LPARENTH) return ChildRole.LPARENTH;
|
||||
if (i == JavaTokenType.RPARENTH) return ChildRole.RPARENTH;
|
||||
if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) return ChildRole.SWITCH_EXPRESSION;
|
||||
if (child.getElementType() == JavaElementType.CODE_BLOCK) return ChildRole.SWITCH_BODY;
|
||||
return ChildRoleBase.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,4 +60,4 @@ public class PsiSwitchStatementImpl extends CompositePsiElement implements PsiSw
|
||||
public String toString() {
|
||||
return "PsiSwitchStatement";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
PsiJavaFile:Switch0.java
|
||||
PsiSwitchExpression: i
|
||||
PsiKeyword:switch('switch')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiReferenceExpression:i
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:i('i')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiSwitchLabeledRule
|
||||
PsiKeyword:case('case')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiExpressionList
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiExpressionStatement
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiSwitchLabeledRule
|
||||
PsiKeyword:default('default')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiExpressionStatement
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -146,6 +146,8 @@ public class ExpressionParserTest extends JavaParsingTestCase {
|
||||
|
||||
public void testRawLiteral0() { doParserTest("`.`"); }
|
||||
|
||||
public void testSwitch0() { doParserTest("switch (i) { case 1 -> 1; default -> 2; }"); }
|
||||
|
||||
private void doParserTest(String text) {
|
||||
doParserTest(text, builder -> JavaParser.INSTANCE.getExpressionParser().parse(builder));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user