EclipseJDT Source Viewer

Home|eclipse_jdt/src/org/eclipse/jdt/core/dom/StringLiteral.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.TerminalTokens;
23import org.eclipse.jdt.internal.compiler.util.Util;
24
25/**
26 * String literal nodes.
27 *
28 * @since 2.0
29 * @noinstantiate This class is not intended to be instantiated by clients.
30 */
31@SuppressWarnings("rawtypes")
32public class StringLiteral extends Expression {
33
34    /**
35     * The "escapedValue" structural property of this node type (type: {@link String}).
36     * @since 3.0
37     */
38    public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY =
39        new SimplePropertyDescriptor(StringLiteral.class"escapedValue"String.classMANDATORY); //$NON-NLS-1$
40
41    /**
42     * A list of property descriptors (element type:
43     * {@link StructuralPropertyDescriptor}),
44     * or null if uninitialized.
45     */
46    private static final List PROPERTY_DESCRIPTORS;
47
48    static {
49        List propertyList = new ArrayList(2);
50        createPropertyList(StringLiteral.classpropertyList);
51        addProperty(ESCAPED_VALUE_PROPERTYpropertyList);
52        PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
53    }
54
55    /**
56     * Returns a list of structural property descriptors for this node type.
57     * Clients must not modify the result.
58     *
59     * @param apiLevel the API level; one of the
60     * <code>AST.JLS*</code> constants
61
62     * @return a list of property descriptors (element type:
63     * {@link StructuralPropertyDescriptor})
64     * @since 3.0
65     */
66    public static List propertyDescriptors(int apiLevel) {
67        return PROPERTY_DESCRIPTORS;
68    }
69
70    /**
71     * The literal string, including quotes and escapes; defaults to the
72     * literal for the empty string.
73     */
74    private String escapedValue = "\"\"";//$NON-NLS-1$
75
76    /**
77     * Creates a new unparented string literal node owned by the given AST.
78     * By default, the string literal denotes the empty string.
79     * <p>
80     * N.B. This constructor is package-private.
81     * </p>
82     *
83     * @param ast the AST that is to own this node
84     */
85    StringLiteral(AST ast) {
86        super(ast);
87    }
88
89    @Override
90    final List internalStructuralPropertiesForType(int apiLevel) {
91        return propertyDescriptors(apiLevel);
92    }
93
94    @Override
95    final Object internalGetSetObjectProperty(SimplePropertyDescriptor propertyboolean getObject value) {
96        if (property == ESCAPED_VALUE_PROPERTY) {
97            if (get) {
98                return getEscapedValue();
99            } else {
100                setEscapedValue((Stringvalue);
101                return null;
102            }
103        }
104        // allow default implementation to flag the error
105        return super.internalGetSetObjectProperty(propertygetvalue);
106    }
107
108    @Override
109    final int getNodeType0() {
110        return STRING_LITERAL;
111    }
112
113    @Override
114    ASTNode clone0(AST target) {
115        StringLiteral result = new StringLiteral(target);
116        result.setSourceRange(getStartPosition(), getLength());
117        result.setEscapedValue(getEscapedValue());
118        return result;
119    }
120
121    @Override
122    final boolean subtreeMatch0(ASTMatcher matcherObject other) {
123        // dispatch to correct overloaded match method
124        return matcher.match(this, other);
125    }
126
127    @Override
128    void accept0(ASTVisitor visitor) {
129        visitor.visit(this);
130        visitor.endVisit(this);
131    }
132
133    /**
134     * Returns the string value of this literal node to the given string
135     * literal token. The token is the sequence of characters that would appear
136     * in the source program, including enclosing double quotes and embedded
137     * escapes.
138     *
139     * @return the string literal token, including enclosing double
140     *    quotes and embedded escapes
141     */
142    public String getEscapedValue() {
143        return this.escapedValue;
144    }
145
146    /**
147     * Sets the string value of this literal node to the given string literal
148     * token. The token is the sequence of characters that would appear in the
149     * source program, including enclosing double quotes and embedded escapes.
150     * For example,
151     * <ul>
152     * <li><code>""</code> <code>setLiteral("\"\"")</code></li>
153     * <li><code>"hello world"</code> <code>setLiteral("\"hello world\"")</code></li>
154     * <li><code>"boo\nhoo"</code> <code>setLiteral("\"boo\\nhoo\"")</code></li>
155     * </ul>
156     *
157     * @param token the string literal token, including enclosing double
158     *    quotes and embedded escapes
159     * @exception IllegalArgumentException if the argument is incorrect
160     */
161    public void setEscapedValue(String token) {
162        // update internalSetEscapedValue(String) if this is changed
163        if (token == null) {
164            throw new IllegalArgumentException("Token cannot be null"); //$NON-NLS-1$
165        }
166        Scanner scanner = this.ast.scanner;
167        char[] source = token.toCharArray();
168        scanner.setSource(source);
169        scanner.resetTo(0source.length);
170        try {
171            int tokenType = scanner.getNextToken();
172            switch(tokenType) {
173                case TerminalTokens.TokenNameStringLiteral:
174                    break;
175                default:
176                    throw new IllegalArgumentException("Invalid string literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
177            }
178        } catch(InvalidInputException e) {
179            throw new IllegalArgumentException("Invalid string literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
180        }
181        preValueChange(ESCAPED_VALUE_PROPERTY);
182        this.escapedValue = token;
183        postValueChange(ESCAPED_VALUE_PROPERTY);
184    }
185
186    /* (omit javadoc for this method)
187     * This method is a copy of setEscapedValue(String) that doesn't do any validation.
188     */
189    void internalSetEscapedValue(String token) {
190        preValueChange(ESCAPED_VALUE_PROPERTY);
191        this.escapedValue = token;
192        postValueChange(ESCAPED_VALUE_PROPERTY);
193    }
194
195    /**
196     * Returns the value of this literal node.
197     * <p>
198     * For example,
199     * <pre>
200     * StringLiteral s;
201     * s.setEscapedValue("\"hello\\nworld\"");
202     * assert s.getLiteralValue().equals("hello\nworld");
203     * </pre>
204     * <p>
205     * Note that this is a convenience method that converts from the stored
206     * string literal token returned by <code>getEscapedLiteral</code>.
207     * </p>
208     *
209     * @return the string value without enclosing double quotes and embedded
210     *    escapes
211     * @exception IllegalArgumentException if the literal value cannot be converted
212     */
213    public String getLiteralValue() {
214        String s = getEscapedValue();
215        int len = s.length();
216        if (len < 2 || s.charAt(0) != '\"' || s.charAt(len-1) != '\"' ) {
217            throw new IllegalArgumentException();
218        }
219
220        Scanner scanner = this.ast.scanner;
221        char[] source = s.toCharArray();
222        scanner.setSource(source);
223        scanner.resetTo(0source.length);
224        try {
225            int tokenType = scanner.getNextToken();
226            switch(tokenType) {
227                case TerminalTokens.TokenNameStringLiteral:
228                    return scanner.getCurrentStringLiteral();
229                default:
230                    throw new IllegalArgumentException();
231            }
232        } catch(InvalidInputException e) {
233            throw new IllegalArgumentException();
234        }
235    }
236
237    /**
238     * Sets the value of this literal node.
239     * <p>
240     * For example,
241     * <pre>
242     * StringLiteral s;
243     * s.setLiteralValue("hello\nworld");
244     * assert s.getEscapedValue().equals("\"hello\\nworld\"");
245     * assert s.getLiteralValue().equals("hello\nworld");
246     * </pre>
247     * <p>
248     * Note that this is a convenience method that converts to the stored
249     * string literal token acceptable to <code>setEscapedLiteral</code>.
250     * </p>
251     *
252     * @param value the string value without enclosing double quotes and
253     *    embedded escapes
254     * @exception IllegalArgumentException if the argument is incorrect
255     */
256    public void setLiteralValue(String value) {
257        if (value == null) {
258            throw new IllegalArgumentException();
259        }
260        int len = value.length();
261        StringBuffer b = new StringBuffer(len + 2);
262
263        b.append("\""); // opening delimiter //$NON-NLS-1$
264        for (int i = 0i < leni++) {
265            char c = value.charAt(i);
266            Util.appendEscapedChar(bctrue);
267        }
268        b.append("\""); // closing delimiter //$NON-NLS-1$
269        setEscapedValue(b.toString());
270    }
271
272    @Override
273    int memSize() {
274        int size = BASE_NODE_SIZE + 1 * 4 + stringSize(this.escapedValue);
275        return size;
276    }
277
278    @Override
279    int treeSize() {
280        return memSize();
281    }
282}
283
MembersX
StringLiteral:escapedValue
StringLiteral:setEscapedValue:Block:source
StringLiteral:clone0
StringLiteral:setEscapedValue:Block:Block:tokenType
StringLiteral:internalStructuralPropertiesForType
StringLiteral:memSize
StringLiteral:subtreeMatch0
StringLiteral:treeSize
StringLiteral:setEscapedValue:Block:scanner
StringLiteral:propertyDescriptors
StringLiteral:getLiteralValue:Block:len
StringLiteral:Block:propertyList
StringLiteral:getLiteralValue:Block:source
StringLiteral:memSize:Block:size
StringLiteral:StringLiteral
StringLiteral:accept0
StringLiteral:ESCAPED_VALUE_PROPERTY
StringLiteral:setLiteralValue
StringLiteral:setLiteralValue:Block:len
StringLiteral:setLiteralValue:Block:Block:c
StringLiteral:getLiteralValue:Block:s
StringLiteral:PROPERTY_DESCRIPTORS
StringLiteral:setEscapedValue
StringLiteral:getLiteralValue
StringLiteral:getLiteralValue:Block:scanner
StringLiteral:getEscapedValue
StringLiteral:internalGetSetObjectProperty
StringLiteral:internalSetEscapedValue
StringLiteral:getLiteralValue:Block:Block:tokenType
StringLiteral:setLiteralValue:Block:b
StringLiteral:clone0:Block:result
StringLiteral:getNodeType0
Members
X