EclipseJDT Source Viewer

Home|eclipse_jdt/src/org/eclipse/jdt/core/dom/CharacterLiteral.java
1/*******************************************************************************
2 * Copyright (c) 2000, 2019 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 *     IBM Corporation - initial API and implementation
13 *******************************************************************************/
14
15package org.eclipse.jdt.core.dom;
16
17import java.util.ArrayList;
18import java.util.List;
19
20import org.eclipse.jdt.core.compiler.InvalidInputException;
21import org.eclipse.jdt.internal.compiler.parser.Scanner;
22import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
23import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
24import org.eclipse.jdt.internal.compiler.util.Util;
25
26/**
27 * Character literal nodes.
28 *
29 * @since 2.0
30 * @noinstantiate This class is not intended to be instantiated by clients.
31 */
32@SuppressWarnings("rawtypes")
33public class CharacterLiteral extends Expression {
34
35    /**
36     * The "escapedValue" structural property of this node type (type: {@link String}).
37     * @since 3.0
38     */
39    public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY =
40        new SimplePropertyDescriptor(CharacterLiteral.class"escapedValue"String.classMANDATORY); //$NON-NLS-1$
41
42    /**
43     * A list of property descriptors (element type:
44     * {@link StructuralPropertyDescriptor}),
45     * or null if uninitialized.
46     */
47    private static final List PROPERTY_DESCRIPTORS;
48
49    static {
50        List properyList = new ArrayList(2);
51        createPropertyList(CharacterLiteral.classproperyList);
52        addProperty(ESCAPED_VALUE_PROPERTYproperyList);
53        PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
54    }
55
56    /**
57     * Returns a list of structural property descriptors for this node type.
58     * Clients must not modify the result.
59     *
60     * @param apiLevel the API level; one of the
61     * <code>AST.JLS*</code> constants
62
63     * @return a list of property descriptors (element type:
64     * {@link StructuralPropertyDescriptor})
65     * @since 3.0
66     */
67    public static List propertyDescriptors(int apiLevel) {
68        return PROPERTY_DESCRIPTORS;
69    }
70
71    /**
72     * The literal string, including quotes and escapes; defaults to the
73     * literal for the character 'X'.
74     */
75    private String escapedValue = "\'X\'";//$NON-NLS-1$
76
77    /**
78     * Creates a new unparented character literal node owned by the given AST.
79     * By default, the character literal denotes an unspecified character.
80     * <p>
81     * N.B. This constructor is package-private.
82     * </p>
83     *
84     * @param ast the AST that is to own this node
85     */
86    CharacterLiteral(AST ast) {
87        super(ast);
88    }
89
90    @Override
91    final List internalStructuralPropertiesForType(int apiLevel) {
92        return propertyDescriptors(apiLevel);
93    }
94
95    @Override
96    final Object internalGetSetObjectProperty(SimplePropertyDescriptor propertyboolean getObject value) {
97        if (property == ESCAPED_VALUE_PROPERTY) {
98            if (get) {
99                return getEscapedValue();
100            } else {
101                setEscapedValue((Stringvalue);
102                return null;
103            }
104        }
105        // allow default implementation to flag the error
106        return super.internalGetSetObjectProperty(propertygetvalue);
107    }
108
109    @Override
110    final int getNodeType0() {
111        return CHARACTER_LITERAL;
112    }
113
114    @Override
115    ASTNode clone0(AST target) {
116        CharacterLiteral result = new CharacterLiteral(target);
117        result.setSourceRange(getStartPosition(), getLength());
118        result.setEscapedValue(getEscapedValue());
119        return result;
120    }
121
122    @Override
123    final boolean subtreeMatch0(ASTMatcher matcherObject other) {
124        // dispatch to correct overloaded match method
125        return matcher.match(this, other);
126    }
127
128    @Override
129    void accept0(ASTVisitor visitor) {
130        visitor.visit(this);
131        visitor.endVisit(this);
132    }
133
134    /**
135     * Returns the string value of this literal node. The value is the sequence
136     * of characters that would appear in the source program, including
137     * enclosing single quotes and embedded escapes.
138     *
139     * @return the escaped string value, including enclosing single quotes
140     *    and embedded escapes
141     */
142    public String getEscapedValue() {
143        return this.escapedValue;
144    }
145
146    /**
147     * Sets the string value of this literal node. The value is the sequence
148     * of characters that would appear in the source program, including
149     * enclosing single quotes and embedded escapes. For example,
150     * <ul>
151     * <li><code>'a'</code> <code>setEscapedValue("\'a\'")</code></li>
152     * <li><code>'\n'</code> <code>setEscapedValue("\'\\n\'")</code></li>
153     * </ul>
154     *
155     * @param value the string value, including enclosing single quotes
156     *    and embedded escapes
157     * @exception IllegalArgumentException if the argument is incorrect
158     */
159    public void setEscapedValue(String value) {
160        // check setInternalEscapedValue(String) if this method is changed
161        if (value == null) {
162            throw new IllegalArgumentException();
163        }
164        Scanner scanner = this.ast.scanner;
165        char[] source = value.toCharArray();
166        scanner.setSource(source);
167        scanner.resetTo(0source.length);
168        try {
169            int tokenType = scanner.getNextToken();
170            switch(tokenType) {
171                case TerminalTokens.TokenNameCharacterLiteral:
172                    break;
173                default:
174                    throw new IllegalArgumentException();
175            }
176        } catch(InvalidInputException e) {
177            throw new IllegalArgumentException();
178        }
179        preValueChange(ESCAPED_VALUE_PROPERTY);
180        this.escapedValue = value;
181        postValueChange(ESCAPED_VALUE_PROPERTY);
182    }
183
184
185    /* (omit javadoc for this method)
186     * This method is a copy of setEscapedValue(String) that doesn't do any validation.
187     */
188    void internalSetEscapedValue(String value) {
189        preValueChange(ESCAPED_VALUE_PROPERTY);
190        this.escapedValue = value;
191        postValueChange(ESCAPED_VALUE_PROPERTY);
192    }
193
194    /**
195     * Returns the value of this literal node.
196     * <p>
197     * For example,
198     * <pre>
199     * CharacterLiteral s;
200     * s.setEscapedValue("\'x\'");
201     * assert s.charValue() == 'x';
202     * </pre>
203     *
204     * @return the character value without enclosing quotes and embedded
205     *    escapes
206     * @exception IllegalArgumentException if the literal value cannot be converted
207     */
208    public char charValue() {
209        Scanner scanner = this.ast.scanner;
210        char[] source = this.escapedValue.toCharArray();
211        scanner.setSource(source);
212        scanner.resetTo(0source.length);
213        int firstChar = scanner.getNextChar();
214        int secondChar = scanner.getNextChar();
215
216        if (firstChar == -1 || firstChar != '\'') {
217            throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
218        }
219        char value = (charsecondChar;
220        int nextChar = scanner.getNextChar();
221        if (secondChar == '\\') {
222            if (nextChar == -1) {
223                throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
224            }
225            switch(nextChar) {
226                case 'b' :
227                    value = '\b';
228                    break;
229                case 't' :
230                    value = '\t';
231                    break;
232                case 'n' :
233                    value = '\n';
234                    break;
235                case 'f' :
236                    value = '\f';
237                    break;
238                case 'r' :
239                    value = '\r';
240                    break;
241                case '\"':
242                    value = '\"';
243                    break;
244                case '\'':
245                    value = '\'';
246                    break;
247                case '\\':
248                    value = '\\';
249                    break;
250                default : //octal (well-formed: ended by a ' )
251                    try {
252                        if (ScannerHelper.isDigit((charnextChar)) {
253                            int number = ScannerHelper.getNumericValue((charnextChar);
254                            nextChar = scanner.getNextChar();
255                            if (nextChar == -1) {
256                                throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
257                            }
258                            if (nextChar != '\'') {
259                                if (!ScannerHelper.isDigit((charnextChar)) {
260                                    throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
261                                }
262                                number = (number * 8) + ScannerHelper.getNumericValue((charnextChar);
263                                nextChar = scanner.getNextChar();
264                                if (nextChar == -1) {
265                                    throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
266                                }
267                                if (nextChar != '\'') {
268                                    if (!ScannerHelper.isDigit((charnextChar)) {
269                                        throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
270                                    }
271                                    number = (number * 8) + ScannerHelper.getNumericValue((charnextChar);
272                                }
273                            }
274                            return (charnumber;
275                        } else {
276                            throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
277                        }
278                    } catch (InvalidInputException e) {
279                        throw new IllegalArgumentException("illegal character literal"e);//$NON-NLS-1$
280                    }
281            }
282            nextChar = scanner.getNextChar();
283            if (nextChar == -1) {
284                throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
285            }
286        }
287        if (nextChar == -1 || nextChar != '\'') {
288            throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
289        }
290        return value;
291    }
292    /**
293     * Sets the value of this character literal node to the given character.
294     * <p>
295     * For example,
296     * <pre>
297     * CharacterLiteral s;
298     * s.setCharValue('x');
299     * assert s.charValue() == 'x';
300     * assert s.getEscapedValue().equals("\'x\'");
301     * </pre>
302     *
303     * @param value the character value
304     */
305    public void setCharValue(char value) {
306        StringBuffer b = new StringBuffer(3);
307
308        b.append('\''); // opening delimiter
309        Util.appendEscapedChar(bvaluefalse);
310        b.append('\''); // closing delimiter
311        setEscapedValue(b.toString());
312    }
313
314    @Override
315    int memSize() {
316        int size = BASE_NODE_SIZE + 1 * 4 + stringSize(this.escapedValue);
317        return size;
318    }
319
320    @Override
321    int treeSize() {
322        return memSize();
323    }
324}
325
326
MembersX
CharacterLiteral:propertyDescriptors
CharacterLiteral:internalGetSetObjectProperty
CharacterLiteral:getNodeType0
CharacterLiteral:charValue:Block:value
CharacterLiteral:treeSize
CharacterLiteral:internalStructuralPropertiesForType
CharacterLiteral:clone0
CharacterLiteral:subtreeMatch0
CharacterLiteral:ESCAPED_VALUE_PROPERTY
CharacterLiteral:PROPERTY_DESCRIPTORS
CharacterLiteral:memSize:Block:size
CharacterLiteral:setEscapedValue
CharacterLiteral:charValue:Block:scanner
CharacterLiteral:setCharValue
CharacterLiteral:CharacterLiteral
CharacterLiteral:internalSetEscapedValue
CharacterLiteral:charValue:Block:Block:Block:Block:number
CharacterLiteral:setEscapedValue:Block:Block:tokenType
CharacterLiteral:clone0:Block:result
CharacterLiteral:charValue:Block:secondChar
CharacterLiteral:charValue:Block:nextChar
CharacterLiteral:charValue:Block:source
CharacterLiteral:memSize
CharacterLiteral:setEscapedValue:Block:scanner
CharacterLiteral:setEscapedValue:Block:source
CharacterLiteral:accept0
CharacterLiteral:escapedValue
CharacterLiteral:charValue
CharacterLiteral:setCharValue:Block:b
CharacterLiteral:Block:properyList
CharacterLiteral:charValue:Block:firstChar
CharacterLiteral:getEscapedValue
Members
X