summaryrefslogtreecommitdiff
path: root/sources/scalac/symtab/SymbolNameWriter.java
blob: bd4b17c9061fef3dec184c83e1bbd9b037c4eb41 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.symtab;

import scalac.Global;
import scalac.util.NameTransformer;

/**
 * This class provides methods to turn symbol names into strings.
 *
 * There are several kinds of owner/symbol relationships:
 *  - root/symbol
 *  - package/symbol
 *  - class/class
 *  - class/member
 *  - owner/parameter
 *  - none/symbol
 *  - error/symbol
 *  - other relationships
 *
 * The separator to use for each of these relationships are specified
 * independently. When a separator is set to '\0' the corresponding
 * owners are dropped from the resulting string. ROOT, NONE and ERROR
 * owners are also dropped. The choice of the separator to use is done
 * by the method "getOwnerSymbolSeparator(Symbol)"
 *
 * Symbol names are usually encoded. There is support to decode these
 * names.
 *
 * Each symbol has an unique identifier. There is support to print
 * these unique identifiers.
 */
public class SymbolNameWriter {

    //########################################################################
    // Private Fields

    /** The string buffer */
    private StringBuffer buffer;

    /** The root/symbol separator */
    private char root;

    /** The package/symbol separator */
    private char peckage;

    /** The class/class separator */
    private char clasz;

    /** The class/member separator */
    private char member;

    /** The owner/parameter separator */
    private char parameter;

    /** The none/symbol separator */
    private char none;

    /** The error/symbol separator */
    private char error;

    /** The other relationships separator */
    private char other;

    /** The name decoding status */
    private boolean decode;

    /** The symbol/unique-identifier separator */
    private char unique;

    /** The number of pending characters */
    private int pending;

    /** The prefix for the current operation (null if none) */
    private String prefix;

    //########################################################################
    // Public Constructors

    /**
     * Initializes this instance with an empty string buffer. This is
     * equivalent to calling "SymbolStringifier(null)".
     */
    public SymbolNameWriter() {
        this(null);
    }

    /**
     * Initializes this instance with given string buffer. All
     * separators are set to '.' excepted the root/symbol separator
     * which is set to '\0'. The symbol name decoding is disabled. The
     * unique identifier printing is disabled.
     */
    public SymbolNameWriter(StringBuffer buffer) {
        setStringBuffer(buffer).setAllSeparators('.').setRootSeparator('\0');
    }

    //########################################################################
    // Public Method - Configuration operations

    /** Sets the string buffer. */
    public SymbolNameWriter setStringBuffer(StringBuffer buffer) {
        this.buffer = buffer;
        return this;
    }

    /** Sets all separators. */
    public SymbolNameWriter setAllSeparators(char separator) {
        setRootSeparator(separator);
        setPackageSeparator(separator);
        setClassSeparator(separator);
        setMemberSeparator(separator);
        setParameterSeparator(separator);
        setNoneSeparator(separator);
        setErrorSeparator(separator);
        setOtherSeparator(separator);
        return this;
    }

    /** Sets the root/symbol separator. */
    public SymbolNameWriter setRootSeparator(char separator) {
        this.root = separator;
        return this;
    }

    /** Sets the package/symbol separator. */
    public SymbolNameWriter setPackageSeparator(char separator) {
        this.peckage = separator;
        return this;
    }

    /** Sets the class/class separator. */
    public SymbolNameWriter setClassSeparator(char separator) {
        this.clasz = separator;
        return this;
    }

    /** Sets the class/member separator. */
    public SymbolNameWriter setMemberSeparator(char separator) {
        this.member = separator;
        return this;
    }

    /** Sets the owner/parameter separator. */
    public SymbolNameWriter setParameterSeparator(char separator) {
        this.parameter = separator;
        return this;
    }

    /** Sets the none/symbol separator. */
    public SymbolNameWriter setNoneSeparator(char separator) {
        this.none = separator;
        return this;
    }

    /** Sets the error/symbol separator. */
    public SymbolNameWriter setErrorSeparator(char separator) {
        this.error = separator;
        return this;
    }

    /** Sets the other relationships separator. */
    public SymbolNameWriter setOtherSeparator(char separator) {
        this.other = separator;
        return this;
    }

    /** Sets the name decoding status. */
    public SymbolNameWriter setNameDecoding(boolean decode) {
        this.decode = decode;
        return this;
    }

    /** Sets the symbol/unique-identifier separator. */
    public SymbolNameWriter setUniqueSeparator(char separator) {
        this.unique = separator;
        return this;
    }

    //########################################################################
    // Public Method - To string operations

    /** Returns the string formed by the symbol. */
    public String toString(Symbol symbol) {
        assert buffer == null;
        String string = appendSymbol(symbol).toString();
        setStringBuffer(null);
        return string;
    }

    /** Returns the string formed by the prefix and symbol. */
    public String toString(String prefix, Symbol symbol) {
        assert buffer == null;
        String string = appendSymbol(prefix, symbol).toString();
        setStringBuffer(null);
        return string;
    }

    /** Returns the string formed by the symbol and suffix. */
    public String toString(Symbol symbol, String suffix) {
        assert buffer == null;
        String string = appendSymbol(symbol, suffix).toString();
        setStringBuffer(null);
        return string;
    }

    /** Returns the string formed by the prefix, symbol and suffix. */
    public String toString(String prefix, Symbol symbol, String suffix) {
        assert buffer == null;
        String string = appendSymbol(prefix, symbol, suffix).toString();
        setStringBuffer(null);
        return string;
    }

    //########################################################################
    // Public Method - Append operations

    /** Appends given symbol. */
    public StringBuffer appendSymbol(Symbol symbol) {
        String name = getSymbolName(symbol);
        this.pending += name.length();
        char separator = getSymbolSeparator(symbol);
        return appendPrefix(symbol.owner(), separator).append(name);;
    }

    /** Appends given prefix and symbol. */
    public StringBuffer appendSymbol(String prefix, Symbol symbol) {
        assert this.prefix == null && prefix != null;
        this.prefix = prefix;
        return appendSymbol(symbol);
    }

    /** Appends given symbol and suffix. */
    public StringBuffer appendSymbol(Symbol symbol, String suffix) {
        this.pending += suffix.length();
        return appendSymbol(symbol).append(suffix);
    }

    /** Appends given prefix, symbol and suffix. */
    public StringBuffer appendSymbol(String prefix, Symbol symbol,
        String suffix)
    {
        assert this.prefix == null && prefix != null;
        this.prefix = prefix;
        this.pending += suffix.length();
        return appendSymbol(symbol).append(suffix);
    }

    /** Appends prefix formed by given owner and separator. */
    public StringBuffer appendPrefix(Symbol owner, char separator) {
        if (separator == 0) return getStringBuffer();
        this.pending += 1;
        return appendSymbol(owner).append(separator);
    }

    //########################################################################
    // Public Method - Query operations

    /** Returns the name to use for given symbol. */
    public String getSymbolName(Symbol symbol) {
        String name = symbol.name.toString();
        if (decode) name = NameTransformer.decode(name);
        if (unique != 0) name =name+unique+Global.instance.uniqueID.id(symbol);
        return name;
    }

    /** Returns the owner/symbol separator to use for given symbol. */
    public char getSymbolSeparator(Symbol symbol) {
        if (symbol.isRoot() || symbol.isNone() || symbol.isError()) return 0;
        if (symbol.isParameter()) return parameter;
        Symbol owner = symbol.owner();
        if (owner.isRoot()) return root;
        if (owner.isNone()) return none;
        if (owner.isError()) return error;
        if (owner.isPackageClass()) return peckage;
        if (owner.isClass()) return symbol.isClass() ? clasz : member;
        return other;
    }

    /** Returns the string buffer. */
    public StringBuffer getStringBuffer() {
        if (prefix != null) pending += prefix.length();
        if (buffer == null) {
            this.buffer = new StringBuffer(pending);
        } else {
            buffer.ensureCapacity(buffer.length() + pending);
        }
        if (prefix != null) buffer.append(prefix);
        this.pending = 0;
        this.prefix = null;
        return buffer;
    }

    /** Returns the content of the string buffer. */
    public String toString() {
        return buffer == null ? "" : buffer.toString();
    }

    //########################################################################
}