/* * Copyright (C) 2015 Julio Vilmar Gesser and Mike DeHaan * * This file is part of antlr-java-parser. * * antlr-java-parser is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * antlr-java-parser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with antlr-java-parser. If not, see <http://www.gnu.org/licenses/>. * */ package com.github.antlrjavaparser.adapter; import com.github.antlrjavaparser.Java7Parser; import com.github.antlrjavaparser.api.expr.ArrayAccessExpr; import com.github.antlrjavaparser.api.expr.ClassExpr; import com.github.antlrjavaparser.api.expr.Expression; import com.github.antlrjavaparser.api.expr.FieldAccessExpr; import com.github.antlrjavaparser.api.expr.MethodCallExpr; import com.github.antlrjavaparser.api.expr.NameExpr; import com.github.antlrjavaparser.api.expr.ObjectCreationExpr; import com.github.antlrjavaparser.api.expr.ThisExpr; import com.github.antlrjavaparser.api.type.ClassOrInterfaceType; import com.github.antlrjavaparser.api.type.ReferenceType; import com.github.antlrjavaparser.api.type.Type; import com.github.antlrjavaparser.api.type.VoidType; import java.util.List; public class PrimaryContextAdapter implements Adapter<Expression, Java7Parser.PrimaryContext> { public Expression adapt(Java7Parser.PrimaryContext context, AdapterParameters adapterParameters) { /* primary locals [int operationType] : parExpression {$operationType = 1;} | THIS (DOT Identifier)* (thisSuffix)? {$operationType = 2;} | Identifier (DOT Identifier)* (identifierSuffix)? {$operationType = 3;} | SUPER superSuffix {$operationType = 4;} | literal {$operationType = 5;} | creator {$operationType = 6;} | primitiveType (LBRACKET RBRACKET)* DOT CLASS {$operationType = 7;} | VOID DOT CLASS {$operationType = 8;} ; superSuffix : arguments | DOT (typeArguments)? Identifier (arguments)? ; thisSuffix locals [int operationType] : (LBRACKET expression RBRACKET)+ {$operationType = 1;} | arguments {$operationType = 2;} | DOT nonWildcardTypeArguments Identifier arguments {$operationType = 3;} | DOT SUPER arguments {$operationType = 4;} | innerCreator {$operationType = 5;} ; identifierSuffix : (LBRACKET RBRACKET)+ DOT CLASS {$operationType = 1;} | (LBRACKET expression RBRACKET)+ {$operationType = 2;} | arguments {$operationType = 3;} | DOT CLASS {$operationType = 4;} | DOT nonWildcardTypeArguments Identifier arguments {$operationType = 5;} | DOT THIS {$operationType = 6;} | DOT SUPER arguments {$operationType = 7;} | innerCreator {$operationType = 8;} ; */ if (context.parExpression() != null) { return Adapters.getParExpressionContextAdapter().adapt(context.parExpression(), adapterParameters); } else if (context.operationType == 2) { return handleThisSuffix(context, adapterParameters); } else if(context.operationType == 3) { return handleIdentifierSuffix(context, adapterParameters); } else if (context.SUPER() != null) { return Adapters.getSuperSuffixContextAdapter().adapt(context.superSuffix(), adapterParameters); } else if (context.literal() != null) { return Adapters.getLiteralContextAdapter().adapt(context.literal(), adapterParameters); } else if (context.creator() != null) { return Adapters.getCreatorContextAdapter().adapt(context.creator(), adapterParameters); } else if (context.primitiveType() != null) { ClassExpr classExpr = new ClassExpr(); AdapterUtil.setComments(classExpr, context, adapterParameters); AdapterUtil.setPosition(classExpr, context); Type type = Adapters.getPrimitiveTypeContextAdapter().adapt(context.primitiveType(), adapterParameters); if (context.LBRACKET() != null && context.LBRACKET().size() > 0) { ReferenceType referenceType = new ReferenceType(); referenceType.setType(type); referenceType.setArrayCount(context.LBRACKET().size()); type = referenceType; } classExpr.setType(type); return classExpr; } else if (context.VOID() != null) { ClassExpr classExpr = new ClassExpr(); AdapterUtil.setComments(classExpr, context, adapterParameters); AdapterUtil.setPosition(classExpr, context); classExpr.setType(new VoidType()); return classExpr; } throw new RuntimeException("Unknown or unhandled primary context"); } // THIS (DOT Identifier)* (identifierSuffix)? {$operationType = 2;} // Identifier (DOT Identifier)* (identifierSuffix)? {$operationType = 3;} private Expression handleIdentifierSuffix(Java7Parser.PrimaryContext primaryContext, AdapterParameters adapterParameters) { /* identifierSuffix locals [int operationType] : (LBRACKET RBRACKET)+ DOT CLASS {$operationType = 1;} | (LBRACKET expression RBRACKET)+ {$operationType = 2;} | arguments {$operationType = 3;} | DOT CLASS {$operationType = 4;} | DOT nonWildcardTypeArguments Identifier arguments {$operationType = 5;} | DOT THIS {$operationType = 6;} | innerCreator {$operationType = 7;} ; //this.m.m.m[].class; // 0 : (LBRACKET RBRACKET)+ DOT CLASS // ClassOrInterfaceType ClassOrInterfaceType ClassOrInterfaceType ReferenceType ClassExpr this.m.m.m[1]; // 1 | (LBRACKET expression RBRACKET)+ // NameExpr FieldAccessExpr FieldAccessExpr ArrayAccessExpr this.m.m.m(""); // 2 | arguments // NameExpr FieldAccessExpr MethodCallExpr //this.m.m.m.class; // 3 | DOT CLASS // ClassOrInterfaceType ClassOrInterfaceType ClassOrInterfaceType ReferenceType ClassExpr this.m.m.<T>m(""); // 4 | DOT nonWildcardTypeArguments Identifier arguments // NameExpr FieldAccessExpr MethodCallExpr this.m.m.m.this; // 5 | DOT THIS // NameExpr FieldAccessExpr FieldAccessExpr ThisExpr //m.m.super(""); // 6 | DOT SUPER arguments */ NameExpr nameExpr = new NameExpr(); nameExpr.setName(primaryContext.Identifier(0).getText()); Expression leftExpression = nameExpr; for (int i = 1; i < primaryContext.Identifier().size(); i++) { FieldAccessExpr fieldAccessExpr = new FieldAccessExpr(); fieldAccessExpr.setField(primaryContext.Identifier(i).getText()); fieldAccessExpr.setScope(leftExpression); leftExpression = fieldAccessExpr; } // if identifierSuffix is null/not specified if (primaryContext.identifierSuffix() == null) { return leftExpression; } ClassOrInterfaceType rootType = new ClassOrInterfaceType(); if (primaryContext.Identifier() != null && primaryContext.Identifier().size() > 0) { rootType.setName(primaryContext.Identifier(0).getText()); } switch (primaryContext.identifierSuffix().operationType) { case 1: case 4: // Need to consider these Identifiers as Types // The last one should be a referenceType ClassOrInterfaceType leftType = rootType; for (int i = 0; i < primaryContext.Identifier().size(); i++) { ClassOrInterfaceType classOrInterfaceType = new ClassOrInterfaceType(); classOrInterfaceType.setName(primaryContext.Identifier(i).getText()); // Don't set the scope on the first type (because it will be itself) if (i > 0) { classOrInterfaceType.setScope(leftType); } leftType = classOrInterfaceType; } ReferenceType referenceType = new ReferenceType(); referenceType.setType(leftType); if (primaryContext.identifierSuffix().LBRACKET() != null) { referenceType.setArrayCount(primaryContext.identifierSuffix().LBRACKET().size()); } ClassExpr classExpr = new ClassExpr(); classExpr.setType(referenceType); return classExpr; case 2: for (int i = 0; i < primaryContext.identifierSuffix().LBRACKET().size(); i++) { ArrayAccessExpr arrayAccessExpr = new ArrayAccessExpr(); arrayAccessExpr.setName(leftExpression); arrayAccessExpr.setIndex(Adapters.getExpressionContextAdapter().adapt(primaryContext.identifierSuffix().expression(i), adapterParameters)); leftExpression = arrayAccessExpr; } return leftExpression; case 3: MethodCallExpr methodCallExpr = new MethodCallExpr(); if (leftExpression instanceof NameExpr) { methodCallExpr.setName(((NameExpr)leftExpression).getName()); } else if (leftExpression instanceof FieldAccessExpr) { methodCallExpr.setName(((FieldAccessExpr)leftExpression).getField()); // Set the leftExpression back one since we're changing the top one to a method call leftExpression = ((FieldAccessExpr) leftExpression).getScope(); methodCallExpr.setScope(leftExpression); } methodCallExpr.setArgs(Adapters.getArgumentsContextAdapter().adapt(primaryContext.identifierSuffix().arguments(), adapterParameters)); leftExpression = methodCallExpr; return leftExpression; case 5: List<Type> typeList = Adapters.getTypeListContextAdapter().adapt(primaryContext.identifierSuffix().nonWildcardTypeArguments().typeList(), adapterParameters); MethodCallExpr typeArgMethodCallExpr = new MethodCallExpr(); typeArgMethodCallExpr.setName(primaryContext.identifierSuffix().Identifier().getText()); typeArgMethodCallExpr.setTypeArgs(typeList); typeArgMethodCallExpr.setScope(leftExpression); typeArgMethodCallExpr.setArgs(Adapters.getArgumentsContextAdapter().adapt(primaryContext.identifierSuffix().arguments(), adapterParameters)); leftExpression = typeArgMethodCallExpr; return leftExpression; case 6: ThisExpr thisExpr= new ThisExpr(); thisExpr.setClassExpr(leftExpression); return thisExpr; case 7: ObjectCreationExpr objectCreationExpr = Adapters.getInnerCreatorContextAdapter().adapt(primaryContext.identifierSuffix().innerCreator(), adapterParameters); objectCreationExpr.setScope(leftExpression); return objectCreationExpr; } return null; } // THIS (DOT Identifier)* (thisSuffix)? {$operationType = 2;} private Expression handleThisSuffix(Java7Parser.PrimaryContext primaryContext, AdapterParameters adapterParameters) { /* thisSuffix locals [int operationType] : (LBRACKET expression RBRACKET)+ {$operationType = 1;} | arguments {$operationType = 2;} | DOT nonWildcardTypeArguments Identifier arguments {$operationType = 3;} | innerCreator {$operationType = 4;} ; //this.m.m.m[].class; // 0 : (LBRACKET RBRACKET)+ DOT CLASS // ClassOrInterfaceType ClassOrInterfaceType ClassOrInterfaceType ReferenceType ClassExpr this.m.m.m[1]; // 1 | (LBRACKET expression RBRACKET)+ // NameExpr FieldAccessExpr FieldAccessExpr ArrayAccessExpr this.m.m.m(""); // 2 | arguments // NameExpr FieldAccessExpr MethodCallExpr //this.m.m.m.class; // 3 | DOT CLASS // ClassOrInterfaceType ClassOrInterfaceType ClassOrInterfaceType ReferenceType ClassExpr this.m.m.<T>m(""); // 4 | DOT nonWildcardTypeArguments Identifier arguments // NameExpr FieldAccessExpr MethodCallExpr this.m.m.m.this; // 5 | DOT THIS // NameExpr FieldAccessExpr FieldAccessExpr ThisExpr //m.m.super(""); // 6 | DOT SUPER arguments */ ThisExpr thisExpr = new ThisExpr(); Expression leftExpression = thisExpr; for (int i = 0; i < primaryContext.Identifier().size(); i++) { FieldAccessExpr fieldAccessExpr = new FieldAccessExpr(); fieldAccessExpr.setField(primaryContext.Identifier(i).getText()); fieldAccessExpr.setScope(leftExpression); leftExpression = fieldAccessExpr; } // if thisSuffix is null/not specified if (primaryContext.thisSuffix() == null) { return leftExpression; } ClassOrInterfaceType rootType = new ClassOrInterfaceType(); if (primaryContext.Identifier() != null && primaryContext.Identifier().size() > 0) { rootType.setName(primaryContext.Identifier(0).getText()); } switch (primaryContext.thisSuffix().operationType) { case 1: for (int i = 0; i < primaryContext.thisSuffix().LBRACKET().size(); i++) { ArrayAccessExpr arrayAccessExpr = new ArrayAccessExpr(); arrayAccessExpr.setName(leftExpression); arrayAccessExpr.setIndex(Adapters.getExpressionContextAdapter().adapt(primaryContext.thisSuffix().expression(i), adapterParameters)); leftExpression = arrayAccessExpr; } return leftExpression; case 2: MethodCallExpr methodCallExpr = new MethodCallExpr(); if (leftExpression instanceof FieldAccessExpr) { methodCallExpr.setName(((FieldAccessExpr)leftExpression).getField()); // Set the leftExpression back one since we're changing the top one to a method call leftExpression = ((FieldAccessExpr) leftExpression).getScope(); methodCallExpr.setScope(leftExpression); } if (methodCallExpr.getName() == null) { throw new RuntimeException("Syntax Error: possibly calling 'this' as a method with arguments. Something like 'this(\"\")'"); } methodCallExpr.setArgs(Adapters.getArgumentsContextAdapter().adapt(primaryContext.thisSuffix().arguments(), adapterParameters)); leftExpression = methodCallExpr; return leftExpression; case 3: List<Type> typeList = Adapters.getTypeListContextAdapter().adapt(primaryContext.thisSuffix().nonWildcardTypeArguments().typeList(), adapterParameters); MethodCallExpr typeArgMethodCallExpr = new MethodCallExpr(); typeArgMethodCallExpr.setName(primaryContext.thisSuffix().Identifier().getText()); typeArgMethodCallExpr.setTypeArgs(typeList); typeArgMethodCallExpr.setScope(leftExpression); typeArgMethodCallExpr.setArgs(Adapters.getArgumentsContextAdapter().adapt(primaryContext.thisSuffix().arguments(), adapterParameters)); leftExpression = typeArgMethodCallExpr; return leftExpression; case 4: ObjectCreationExpr objectCreationExpr = Adapters.getInnerCreatorContextAdapter().adapt(primaryContext.thisSuffix().innerCreator(), adapterParameters); objectCreationExpr.setScope(leftExpression); return objectCreationExpr; } return null; } }