JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.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.printer.lexicalpreservation;
23
24import com.github.javaparser.JavaToken;
25import com.github.javaparser.TokenRange;
26import com.github.javaparser.TokenTypes;
27import com.github.javaparser.ast.Node;
28import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
29
30import java.util.Iterator;
31import java.util.List;
32import java.util.Optional;
33import java.util.function.Function;
34import java.util.stream.Collectors;
35import java.util.stream.IntStream;
36
37/**
38 * This class represents a group of {@link Removed} elements.
39 * The {@link Removed} elements are ideally consecutive for the methods in this class to work correctly.
40 *
41 * This class consists of methods that calculate information to better handle the difference application for the
42 * containing {@link Removed} elements.
43 *
44 * @see Iterable
45 *
46 * @author ThLeu
47 */
48final class RemovedGroup implements Iterable<Removed> {
49
50    private final Integer firstElementIndex;
51    private final List<RemovedremovedList;
52
53    private boolean isProcessed = false;
54
55    private RemovedGroup(Integer firstElementIndexList<RemovedremovedList) {
56        if (firstElementIndex == null) {
57            throw new IllegalArgumentException("firstElementIndex should not be null");
58        }
59
60        if (removedList == null || removedList.isEmpty()) {
61            throw new IllegalArgumentException("removedList should not be null or empty");
62        }
63
64        this.firstElementIndex = firstElementIndex;
65        this.removedList = removedList;
66    }
67
68    /**
69     * Factory method to create a RemovedGroup which consists of consecutive Removed elements
70     *
71     * @param firstElementIndex the difference index at which the RemovedGroup starts
72     * @param removedList list of the consecutive Removed elements
73     * @return a RemovedGroup object
74     * @throws IllegalArgumentException if the firstElementIndex is null or the removedList is empty or null
75     */
76    public static RemovedGroup of(Integer firstElementIndexList<RemovedremovedList) {
77        return new RemovedGroup(firstElementIndexremovedList);
78    }
79
80    /**
81     * Marks the RemovedGroup as processed which indicates that it should not be processed again
82     */
83    final void processed() {
84        isProcessed = true;
85    }
86
87    /**
88     * Returns whether the RemovedGroup was already processed and should not be processed again
89     *
90     * @return wheter the RemovedGroup was already processed
91     */
92    final boolean isProcessed() {
93        return isProcessed;
94    }
95
96    private List<IntegergetIndicesBeingRemoved() {
97        return IntStream.range(firstElementIndexfirstElementIndex + removedList.size())
98                .boxed()
99                .collect(Collectors.toList());
100    }
101
102    /**
103     * Returns the difference index of the last element being removed with this RemovedGroup
104     *
105     * @return the last difference incex of this RemovedGroup
106     */
107    final Integer getLastElementIndex() {
108        List<IntegerindicesBeingRemoved = getIndicesBeingRemoved();
109        return indicesBeingRemoved.get(indicesBeingRemoved.size() - 1);
110    }
111
112    /**
113     * Returns the first element of this RemovedGroup
114     *
115     * @return the first element of this RemovedGroup
116     */
117    final Removed getFirstElement() {
118        return removedList.get(0);
119    }
120
121    /**
122     * Returns the last element of this RemovedGroup
123     *
124     * @return the last element of this RemovedGroup
125     */
126    final Removed getLastElement() {
127        return removedList.get(removedList.size() - 1);
128    }
129
130    /**
131     * Returns true if the RemovedGroup equates to a complete line
132     * This is the case if there are only spaces and tabs left on the line besides the Removed elements.
133     * <br>
134     * Example:
135     * <pre>
136     * "  [Removed] [EOL]" -> this would be a complete line, regardless of spaces or tabs before or after the [Removed] element
137     * "  [Removed] void [EOL]" -> this would not be a complete line because of the "void"
138     * "  public [Removed] [EOL]" -> this would not be a complete line because of the "public"
139     * </pre>
140     *
141     * @return true if the RemovedGroup equates to a complete line
142     */
143    final boolean isACompleteLine() {
144        return hasOnlyWhitespace(getFirstElement(), hasOnlyWhitespaceInFrontFunction)
145                && hasOnlyWhitespace(getLastElement(), hasOnlyWhitespaceBehindFunction);
146    }
147
148    private final Function<JavaTokenBooleanhasOnlyWhitespaceJavaTokenInFrontFunction = begin -> hasOnlyWhiteSpaceForTokenFunction(begintoken -> token.getPreviousToken());
149    private final Function<JavaTokenBooleanhasOnlyWhitespaceJavaTokenBehindFunction = end -> hasOnlyWhiteSpaceForTokenFunction(endtoken -> token.getNextToken());
150    private final Function<TokenRangeBooleanhasOnlyWhitespaceInFrontFunction = tokenRange -> hasOnlyWhitespaceJavaTokenInFrontFunction.apply(tokenRange.getBegin());
151    private final Function<TokenRangeBooleanhasOnlyWhitespaceBehindFunction = tokenRange -> hasOnlyWhitespaceJavaTokenBehindFunction.apply(tokenRange.getEnd());
152
153    private boolean hasOnlyWhitespace(Removed startElementFunction<TokenRangeBooleanhasOnlyWhitespaceFunction) {
154        boolean hasOnlyWhitespace = false;
155        if (startElement.isChild()) {
156            LexicalDifferenceCalculator.CsmChild csmChild = (LexicalDifferenceCalculator.CsmChildstartElement.getElement();
157            Node child = csmChild.getChild();
158
159            Optional<TokenRangetokenRange = child.getTokenRange();
160            if (tokenRange.isPresent()) {
161                hasOnlyWhitespace = hasOnlyWhitespaceFunction.apply(tokenRange.get());
162            }
163        } else if (startElement.isToken()) {
164            CsmToken token = (CsmTokenstartElement.getElement();
165            if (TokenTypes.isEndOfLineToken(token.getTokenType())) {
166                hasOnlyWhitespace = true;
167            }
168        }
169        return hasOnlyWhitespace;
170    }
171
172    private boolean hasOnlyWhiteSpaceForTokenFunction(JavaToken tokenFunction<JavaTokenOptional<JavaToken>> tokenFunction) {
173        Optional<JavaTokentokenResult = tokenFunction.apply(token);
174
175        if (tokenResult.isPresent()) {
176            if (TokenTypes.isWhitespaceButNotEndOfLine(tokenResult.get().getKind())) {
177                return hasOnlyWhiteSpaceForTokenFunction(tokenResult.get(), tokenFunction);
178            } else if (TokenTypes.isEndOfLineToken(tokenResult.get().getKind())) {
179                return true;
180            } else {
181                return false;
182            }
183        }
184
185        return true;
186    }
187
188    /**
189     * Returns the indentation in front of this RemovedGroup if possible.
190     * If there is something else than whitespace in front, Optional.empty() is returned.
191     *
192     * @return the indentation in front of this RemovedGroup or Optional.empty()
193     */
194    final Optional<IntegergetIndentation() {
195        Removed firstElement = getFirstElement();
196
197        int indentation = 0;
198        if (firstElement.isChild()) {
199            LexicalDifferenceCalculator.CsmChild csmChild = (LexicalDifferenceCalculator.CsmChildfirstElement.getElement();
200            Node child = csmChild.getChild();
201
202            Optional<TokenRangetokenRange = child.getTokenRange();
203            if (tokenRange.isPresent()) {
204                JavaToken begin = tokenRange.get().getBegin();
205
206                if (hasOnlyWhitespaceJavaTokenInFrontFunction.apply(begin)) {
207                    Optional<JavaTokenpreviousToken = begin.getPreviousToken();
208
209                    while(previousToken.isPresent() && (TokenTypes.isWhitespaceButNotEndOfLine(previousToken.get().getKind()))) {
210                        indentation++;
211
212                        previousToken = previousToken.get().getPreviousToken();
213                    }
214
215                    if (previousToken.isPresent()) {
216                        if (TokenTypes.isEndOfLineToken(previousToken.get().getKind())) {
217                            return Optional.of(Integer.valueOf(indentation));
218                        } else {
219                            return Optional.empty();
220                        }
221                    } else {
222                        return Optional.of(Integer.valueOf(indentation));
223                    }
224                }
225            }
226        }
227
228        return Optional.empty();
229    }
230
231    @Override
232    public final Iterator<Removediterator() {
233        return new Iterator<Removed>() {
234            private int currentIndex = 0;
235
236            @Override
237            public boolean hasNext() {
238                return currentIndex < removedList.size() && removedList.get(currentIndex) != null;
239            }
240
241            @Override
242            public Removed next() {
243                return removedList.get(currentIndex++);
244            }
245
246        };
247    }
248}
249
MembersX
RemovedGroup:iterator:Block:hasNext
RemovedGroup:hasOnlyWhiteSpaceForTokenFunction
RemovedGroup:removedList
RemovedGroup:getIndentation
RemovedGroup:iterator:Block:next
RemovedGroup:RemovedGroup
RemovedGroup:of
RemovedGroup:hasOnlyWhitespaceJavaTokenBehindFunction
RemovedGroup:hasOnlyWhitespaceInFrontFunction
RemovedGroup:getIndentation:Block:Block:Block:begin
RemovedGroup:getLastElementIndex:Block:indicesBeingRemoved
RemovedGroup:getIndentation:Block:firstElement
RemovedGroup:iterator
RemovedGroup:getIndicesBeingRemoved
RemovedGroup:hasOnlyWhitespace:Block:Block:csmChild
RemovedGroup:getIndentation:Block:indentation
RemovedGroup:hasOnlyWhitespaceBehindFunction
RemovedGroup:firstElementIndex
RemovedGroup:getLastElement
RemovedGroup:hasOnlyWhitespace:Block:hasOnlyWhitespace
RemovedGroup:hasOnlyWhitespace:Block:Block:tokenRange
RemovedGroup:isProcessed
RemovedGroup:hasOnlyWhitespace:Block:Block:child
RemovedGroup:getLastElementIndex
RemovedGroup:processed
RemovedGroup:getIndentation:Block:Block:child
RemovedGroup:getIndentation:Block:Block:csmChild
RemovedGroup:getIndentation:Block:Block:tokenRange
RemovedGroup:getIndentation:Block:Block:Block:Block:previousToken
RemovedGroup:getFirstElement
RemovedGroup:iterator:Block:currentIndex
RemovedGroup:hasOnlyWhitespaceJavaTokenInFrontFunction
RemovedGroup:isACompleteLine
RemovedGroup:hasOnlyWhitespace:Block:Block:token
RemovedGroup:hasOnlyWhitespace
RemovedGroup:hasOnlyWhiteSpaceForTokenFunction:Block:tokenResult
Members
X