JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/GeneratedJavaParserBase.java
1/*
2 * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser.
3 * Copyright (C) 2011, 2013-2020 The JavaParser Team.
4 *
5 * This file is part of JavaParser.
6 *
7 * JavaParser can be used either under the terms of
8 * a) the GNU Lesser General Public License as published by
9 *     the Free Software Foundation, either version 3 of the License, or
10 *     (at your option) any later version.
11 * b) the terms of the Apache License
12 *
13 * You should have received a copy of both licenses in LICENCE.LGPL and
14 * LICENCE.APACHE. Please refer to those files for details.
15 *
16 * JavaParser is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 */
21
22package com.github.javaparser;
23
24import com.github.javaparser.ast.ArrayCreationLevel;
25import com.github.javaparser.ast.Node;
26import com.github.javaparser.ast.NodeList;
27import com.github.javaparser.ast.body.Parameter;
28import com.github.javaparser.ast.comments.CommentsCollection;
29import com.github.javaparser.ast.expr.*;
30import com.github.javaparser.ast.stmt.Statement;
31import com.github.javaparser.ast.type.ArrayType;
32import com.github.javaparser.ast.type.Type;
33import com.github.javaparser.ast.type.UnknownType;
34import com.github.javaparser.utils.Pair;
35
36import java.util.*;
37
38import static com.github.javaparser.GeneratedJavaParserConstants.EOF;
39import static com.github.javaparser.ast.type.ArrayType.unwrapArrayTypes;
40import static com.github.javaparser.ast.type.ArrayType.wrapInArrayTypes;
41import static com.github.javaparser.utils.Utils.assertNotNull;
42
43/**
44 * Base class for {@link GeneratedJavaParser}
45 */
46abstract class GeneratedJavaParserBase {
47    //// Interface with the generated code
48    abstract GeneratedJavaParserTokenManager getTokenSource();
49
50    abstract void ReInit(Provider provider);
51
52    /* Returns the JavaParser specific token type of the last matched token */
53    abstract JavaToken token();
54
55    abstract Token getNextToken();
56
57    ////
58
59    /* The problems encountered while parsing */
60    List<Problemproblems = new ArrayList<>();
61    /* Configuration flag whether we store tokens and tokenranges */
62    boolean storeTokens;
63
64    /* Resets the parser for reuse, gaining a little performance */
65    void reset(Provider provider) {
66        ReInit(provider);
67        problems = new ArrayList<>();
68        getTokenSource().reset();
69    }
70
71    /**
72     * Return the list of JavaParser specific tokens that have been encountered while parsing code using this parser.
73     *
74     * @return a list of tokens
75     */
76    public List<JavaTokengetTokens() {
77        return getTokenSource().getTokens();
78    }
79
80    /* The collection of comments encountered */
81    CommentsCollection getCommentsCollection() {
82        return getTokenSource().getCommentsCollection();
83    }
84
85    /* Reports a problem to the user */
86    void addProblem(String message) {
87        // TODO tokenRange only takes the final token. Need all the tokens.
88        problems.add(new Problem(messagetokenRange(), null));
89    }
90
91    /* Returns a tokenRange that spans the last matched token */
92    TokenRange tokenRange() {
93        if (storeTokens) {
94            return new TokenRange(token(), token());
95        }
96        return null;
97    }
98
99    /**
100     * Return a TokenRange spanning from begin to end
101     */
102    TokenRange range(JavaToken beginJavaToken end) {
103        if (storeTokens) {
104            return new TokenRange(beginend);
105        }
106        return null;
107    }
108
109    /**
110     * Return a TokenRange spanning from begin to end
111     */
112    TokenRange range(Node beginJavaToken end) {
113        if (storeTokens) {
114            return new TokenRange(begin.getTokenRange().get().getBegin(), end);
115        }
116        return null;
117    }
118
119    /**
120     * Return a TokenRange spanning from begin to end
121     */
122    TokenRange range(JavaToken beginNode end) {
123        if (storeTokens) {
124            return new TokenRange(beginend.getTokenRange().get().getEnd());
125        }
126        return null;
127    }
128
129    /**
130     * Return a TokenRange spanning from begin to end
131     */
132    TokenRange range(Node beginNode end) {
133        if (storeTokens) {
134            return new TokenRange(begin.getTokenRange().get().getBegin(), end.getTokenRange().get().getEnd());
135        }
136        return null;
137    }
138
139    /**
140     * @return secondChoice if firstChoice is JavaToken.UNKNOWN, otherwise firstChoice
141     */
142    JavaToken orIfInvalid(JavaToken firstChoiceJavaToken secondChoice) {
143        if (storeTokens) {
144            assertNotNull(firstChoice);
145            assertNotNull(secondChoice);
146            if (firstChoice.valid() || secondChoice.invalid()) {
147                return firstChoice;
148            }
149            return secondChoice;
150        }
151        return null;
152    }
153
154    /**
155     * @return the begin-token secondChoice if firstChoice is JavaToken.UNKNOWN, otherwise firstChoice
156     */
157    JavaToken orIfInvalid(JavaToken firstChoiceNode secondChoice) {
158        if (storeTokens) {
159            return orIfInvalid(firstChoicesecondChoice.getTokenRange().get().getBegin());
160        }
161        return null;
162    }
163
164    /**
165     * Get the token that starts the NodeList l
166     */
167    JavaToken nodeListBegin(NodeList<?> l) {
168        if (!storeTokens || l.isEmpty()) {
169            return JavaToken.INVALID;
170        }
171        return l.get(0).getTokenRange().get().getBegin();
172    }
173
174    /* Sets the kind of the last matched token to newKind */
175    void setTokenKind(int newKind) {
176        token().setKind(newKind);
177    }
178
179    /* Makes the parser keep a list of tokens */
180    void setStoreTokens(boolean storeTokens) {
181        this.storeTokens = storeTokens;
182        getTokenSource().setStoreTokens(storeTokens);
183    }
184
185    /* Called from within a catch block to skip forward to a known token,
186        and report the occurred exception as a problem. */
187    TokenRange recover(int recoveryTokenTypeParseException p) {
188        JavaToken begin = null;
189        if (p.currentToken != null) {
190            begin = token();
191        }
192        Token t;
193        do {
194            t = getNextToken();
195        } while (t.kind != recoveryTokenType && t.kind != EOF);
196
197        JavaToken end = token();
198
199        TokenRange tokenRange = null;
200        if (begin != null && end != null) {
201            tokenRange = range(beginend);
202        }
203
204        problems.add(new Problem(makeMessageForParseException(p), tokenRangep));
205        return tokenRange;
206    }
207
208    /**
209     * Quickly create a new, empty, NodeList
210     */
211    <T extends NodeNodeList<TemptyNodeList() {
212        return new NodeList<>();
213    }
214
215    /**
216     * Add obj to list and return it. Create a new list if list is null
217     */
218    <T extends NodeNodeList<Tadd(NodeList<TlistT obj) {
219        if (list == null) {
220            list = new NodeList<>();
221        }
222        list.add(obj);
223        return list;
224    }
225
226    /**
227     * Add obj to list only when list is not null
228     */
229    <T extends NodeNodeList<TaddWhenNotNull(NodeList<TlistT obj) {
230        if (obj == null) {
231            return list;
232        }
233        return add(listobj);
234    }
235
236    /**
237     * Add obj to list at position pos
238     */
239    <T extends NodeNodeList<Tprepend(NodeList<TlistT obj) {
240        if (list == null) {
241            list = new NodeList<>();
242        }
243        list.addFirst(obj);
244        return list;
245    }
246
247    /**
248     * Add obj to list
249     */
250    <TList<Tadd(List<TlistT obj) {
251        if (list == null) {
252            list = new LinkedList<>();
253        }
254        list.add(obj);
255        return list;
256    }
257
258    /**
259     * Propagate expansion of the range on the right to the parent. This is necessary when the right border of the child
260     * is determining the right border of the parent (i.e., the child is the last element of the parent). In this case
261     * when we "enlarge" the child we should enlarge also the parent.
262     */
263    private void propagateRangeGrowthOnRight(Node nodeNode endNode) {
264        if (storeTokens) {
265            node.getParentNode().ifPresent(nodeParent -> {
266                boolean isChildOnTheRightBorderOfParent = node.getTokenRange().get().getEnd().equals(nodeParent.getTokenRange().get().getEnd());
267                if (isChildOnTheRightBorderOfParent) {
268                    propagateRangeGrowthOnRight(nodeParentendNode);
269                }
270            });
271            node.setTokenRange(range(nodeendNode));
272        }
273    }
274
275    /**
276     * Workaround for rather complex ambiguity that lambda's create
277     */
278    Expression generateLambda(Expression retStatement lambdaBody) {
279        if (ret instanceof EnclosedExpr) {
280            Expression inner = ((EnclosedExprret).getInner();
281            SimpleName id = ((NameExprinner).getName();
282            NodeList<Parameterparams = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), new NodeList<>(), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
283            ret = new LambdaExpr(range(retlambdaBody), paramslambdaBodytrue);
284        } else if (ret instanceof NameExpr) {
285            SimpleName id = ((NameExprret).getName();
286            NodeList<Parameterparams = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), new NodeList<>(), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
287            ret = new LambdaExpr(range(retlambdaBody), paramslambdaBodyfalse);
288        } else if (ret instanceof LambdaExpr) {
289            ((LambdaExprret).setBody(lambdaBody);
290            propagateRangeGrowthOnRight(retlambdaBody);
291        } else if (ret instanceof CastExpr) {
292            CastExpr castExpr = (CastExprret;
293            Expression inner = generateLambda(castExpr.getExpression(), lambdaBody);
294            castExpr.setExpression(inner);
295        } else {
296            addProblem("Failed to parse lambda expression! Please create an issue at https://github.com/javaparser/javaparser/issues");
297        }
298        return ret;
299    }
300
301    /**
302     * Throws together an ArrayCreationExpr from a lot of pieces
303     */
304    ArrayCreationExpr juggleArrayCreation(TokenRange rangeList<TokenRangelevelRangesType typeNodeList<ExpressiondimensionsList<NodeList<AnnotationExpr>> arrayAnnotationsArrayInitializerExpr arrayInitializerExpr) {
305        NodeList<ArrayCreationLevellevels = new NodeList<>();
306
307        for (int i = 0i < arrayAnnotations.size(); i++) {
308            levels.add(new ArrayCreationLevel(levelRanges.get(i), dimensions.get(i), arrayAnnotations.get(i)));
309        }
310        return new ArrayCreationExpr(rangetypelevelsarrayInitializerExpr);
311    }
312
313    /**
314     * Throws together a Type, taking care of all the array brackets
315     */
316    Type juggleArrayType(Type partialTypeList<ArrayType.ArrayBracketPairadditionalBrackets) {
317        Pair<TypeList<ArrayType.ArrayBracketPair>> partialParts = unwrapArrayTypes(partialType);
318        Type elementType = partialParts.a;
319        List<ArrayType.ArrayBracketPairleftMostBrackets = partialParts.b;
320        return wrapInArrayTypes(elementTypeadditionalBracketsleftMostBrackets).clone();
321    }
322
323    /**
324     * This is the code from ParseException.initialise, modified to be more horizontal.
325     */
326    private String makeMessageForParseException(ParseException exception) {
327        final StringBuilder sb = new StringBuilder("Parse error. Found ");
328        final StringBuilder expected = new StringBuilder();
329
330        int maxExpectedTokenSequenceLength = 0;
331        TreeSet<StringsortedOptions = new TreeSet<>();
332        for (int i = 0i < exception.expectedTokenSequences.lengthi++) {
333            if (maxExpectedTokenSequenceLength < exception.expectedTokenSequences[i].length) {
334                maxExpectedTokenSequenceLength = exception.expectedTokenSequences[i].length;
335            }
336            for (int j = 0j < exception.expectedTokenSequences[i].lengthj++) {
337                sortedOptions.add(exception.tokenImage[exception.expectedTokenSequences[i][j]]);
338            }
339        }
340
341        for (String option : sortedOptions) {
342            expected.append(" ").append(option);
343        }
344
345        Token token = exception.currentToken.next;
346        for (int i = 0i < maxExpectedTokenSequenceLengthi++) {
347            String tokenText = token.image;
348            String escapedTokenText = ParseException.add_escapes(tokenText);
349            if (i != 0) {
350                sb.append(" ");
351            }
352            if (token.kind == 0) {
353                sb.append(exception.tokenImage[0]);
354                break;
355            }
356            escapedTokenText = "\"" + escapedTokenText + "\"";
357            String image = exception.tokenImage[token.kind];
358            if (image.equals(escapedTokenText)) {
359                sb.append(image);
360            } else {
361                sb.append(" ")
362                        .append(escapedTokenText)
363                        .append(" ")
364                        .append(image);
365            }
366            token = token.next;
367        }
368
369        if (exception.expectedTokenSequences.length != 0) {
370            int numExpectedTokens = exception.expectedTokenSequences.length;
371            sb.append(", expected")
372                    .append(numExpectedTokens == 1 ? "" : " one of ")
373                    .append(expected.toString());
374        }
375        return sb.toString();
376    }
377
378    /**
379     * Converts a NameExpr or a FieldAccessExpr scope to a Name.
380     */
381    Name scopeToName(Expression scope) {
382        if (scope.isNameExpr()) {
383            SimpleName simpleName = scope.asNameExpr().getName();
384            return new Name(simpleName.getTokenRange().get(), nullsimpleName.getIdentifier());
385        }
386        if (scope.isFieldAccessExpr()) {
387            FieldAccessExpr fieldAccessExpr = scope.asFieldAccessExpr();
388            return new Name(fieldAccessExpr.getTokenRange().get(), scopeToName(fieldAccessExpr.getScope()), fieldAccessExpr.getName().getIdentifier());
389
390        }
391        throw new IllegalStateException("Unexpected expression type: " + scope.getClass().getSimpleName());
392    }
393
394    String unquote(String s) {
395        return s.substring(1s.length() - 1);
396    }
397
398    String unTripleQuote(String s) {
399        int start = 3;
400        // Skip over the first end of line too:
401        if (s.charAt(start) == '\r') {
402            start++;
403        }
404        if (s.charAt(start) == '\n') {
405            start++;
406        }
407        return s.substring(starts.length() - 3);
408    }
409
410    void setYieldSupported() {
411        getTokenSource().setYieldSupported();
412    }
413}
414
MembersX
GeneratedJavaParserBase:makeMessageForParseException
GeneratedJavaParserBase:scopeToName
GeneratedJavaParserBase:makeMessageForParseException:Block:Block:escapedTokenText
GeneratedJavaParserBase:getTokens
GeneratedJavaParserBase:orIfInvalid
GeneratedJavaParserBase:recover
GeneratedJavaParserBase:juggleArrayCreation
GeneratedJavaParserBase:recover:Block:t
GeneratedJavaParserBase:recover:Block:tokenRange
GeneratedJavaParserBase:juggleArrayType:Block:leftMostBrackets
GeneratedJavaParserBase:juggleArrayType
GeneratedJavaParserBase:addWhenNotNull
GeneratedJavaParserBase:generateLambda:Block:Block:inner
GeneratedJavaParserBase:juggleArrayCreation:Block:levels
GeneratedJavaParserBase:addProblem
GeneratedJavaParserBase:makeMessageForParseException:Block:sortedOptions
GeneratedJavaParserBase:makeMessageForParseException:Block:Block:numExpectedTokens
GeneratedJavaParserBase:scopeToName:Block:Block:simpleName
GeneratedJavaParserBase:scopeToName:Block:Block:fieldAccessExpr
GeneratedJavaParserBase:storeTokens
GeneratedJavaParserBase:makeMessageForParseException:Block:Block:tokenText
GeneratedJavaParserBase:tokenRange
GeneratedJavaParserBase:unTripleQuote
GeneratedJavaParserBase:generateLambda:Block:Block:params
GeneratedJavaParserBase:setYieldSupported
GeneratedJavaParserBase:token
GeneratedJavaParserBase:add
GeneratedJavaParserBase:juggleArrayType:Block:partialParts
GeneratedJavaParserBase:recover:Block:end
GeneratedJavaParserBase:setTokenKind
GeneratedJavaParserBase:juggleArrayType:Block:elementType
GeneratedJavaParserBase:ReInit
GeneratedJavaParserBase:getTokenSource
GeneratedJavaParserBase:problems
GeneratedJavaParserBase:reset
GeneratedJavaParserBase:getNextToken
GeneratedJavaParserBase:generateLambda:Block:Block:castExpr
GeneratedJavaParserBase:generateLambda:Block:Block:id
GeneratedJavaParserBase:makeMessageForParseException:Block:maxExpectedTokenSequenceLength
GeneratedJavaParserBase:nodeListBegin
GeneratedJavaParserBase:unTripleQuote:Block:start
GeneratedJavaParserBase:makeMessageForParseException:Block:sb
GeneratedJavaParserBase:unquote
GeneratedJavaParserBase:range
GeneratedJavaParserBase:propagateRangeGrowthOnRight
GeneratedJavaParserBase:propagateRangeGrowthOnRight:Block:Block:Block:isChildOnTheRightBorderOfParent
GeneratedJavaParserBase:makeMessageForParseException:Block:expected
GeneratedJavaParserBase:setStoreTokens
GeneratedJavaParserBase:emptyNodeList
GeneratedJavaParserBase:prepend
GeneratedJavaParserBase:getCommentsCollection
GeneratedJavaParserBase:makeMessageForParseException:Block:Block:image
GeneratedJavaParserBase:generateLambda
GeneratedJavaParserBase:recover:Block:begin
GeneratedJavaParserBase:makeMessageForParseException:Block:token
Members
X