001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.cnd.modelimpl.csm;
043:
044: import antlr.collections.AST;
045: import java.io.DataInput;
046: import java.io.DataOutput;
047: import java.io.IOException;
048: import org.netbeans.modules.cnd.api.model.CsmClass;
049: import org.netbeans.modules.cnd.api.model.CsmDeclaration;
050: import org.netbeans.modules.cnd.api.model.CsmFile;
051: import org.netbeans.modules.cnd.api.model.CsmIdentifiable;
052: import org.netbeans.modules.cnd.api.model.CsmNamespace;
053: import org.netbeans.modules.cnd.api.model.CsmObject;
054: import org.netbeans.modules.cnd.api.model.CsmScope;
055: import org.netbeans.modules.cnd.api.model.CsmScopeElement;
056: import org.netbeans.modules.cnd.api.model.CsmType;
057: import org.netbeans.modules.cnd.api.model.CsmTypedef;
058: import org.netbeans.modules.cnd.api.model.CsmUID;
059: import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
060: import org.netbeans.modules.cnd.modelimpl.csm.core.FileImpl;
061: import org.netbeans.modules.cnd.modelimpl.parser.generated.CPPTokenTypes;
062: import org.netbeans.modules.cnd.modelimpl.csm.core.Disposable;
063: import org.netbeans.modules.cnd.modelimpl.csm.core.OffsetableDeclarationBase;
064: import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
065: import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
066: import org.netbeans.modules.cnd.modelimpl.textcache.QualifiedNameCache;
067: import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
068: import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
069: import org.netbeans.modules.cnd.utils.cache.CharSequenceKey;
070:
071: /**
072: * Implements CsmTypedef
073: * @author vk155633
074: */
075: public class TypedefImpl extends OffsetableDeclarationBase<CsmTypedef>
076: implements CsmTypedef, Disposable, CsmScopeElement {
077:
078: private final CharSequence name;
079: private final CsmType type;
080: private boolean typeUnnamed = false;
081:
082: // only one of containerRef/containerUID must be used (based on USE_REPOSITORY)
083: private/*final*/CsmObject containerRef;// can be set in onDispose or contstructor only
084: private/*final*/CsmUID<CsmIdentifiable> containerUID;
085:
086: public TypedefImpl(AST ast, CsmFile file, CsmObject container,
087: CsmType type, String name) {
088:
089: super (ast, file);
090:
091: if (container instanceof CsmIdentifiable) {
092: this .containerUID = UIDCsmConverter
093: .identifiableToUID((CsmIdentifiable) container);
094: assert (containerUID != null || container == null);
095: this .containerRef = null;
096: } else {
097: // yes, that's possible if it's somewhere within body
098: this .containerRef = container;
099: }
100:
101: if (type == null) {
102: this .type = createType(ast);
103: } else {
104: this .type = type;
105: }
106: this .name = QualifiedNameCache.getManager().getString(name);
107: }
108:
109: public boolean isTypeUnnamed() {
110: return typeUnnamed;
111: }
112:
113: public void setTypeUnnamed() {
114: typeUnnamed = true;
115: }
116:
117: // Moved to OffsetableDeclarationBase
118: // public String getUniqueName() {
119: // return getQualifiedName();
120: // }
121:
122: public CsmScope getScope() {
123: // TODO: ???
124: //return getContainingFile();
125: CsmObject container = _getContainer();
126: if (container instanceof CsmNamespace) {
127: return (CsmNamespace) container;
128: } else if (container instanceof CsmClass) {
129: return (CsmClass) container;
130: } else {
131: return getContainingFile();
132: }
133: }
134:
135: @Override
136: public void dispose() {
137: super .dispose();
138: onDispose();
139: if (this .type != null && this .type instanceof Disposable) {
140: ((Disposable) this .type).dispose();
141: }
142: CsmScope scope = getScope();
143: if (scope instanceof MutableDeclarationsContainer) {
144: ((MutableDeclarationsContainer) scope)
145: .removeDeclaration(this );
146: }
147: FileImpl file = (FileImpl) getContainingFile();
148: file.getProjectImpl().unregisterDeclaration(this );
149: }
150:
151: private void onDispose() {
152: if (TraceFlags.RESTORE_CONTAINER_FROM_UID) {
153: // restore container from it's UID
154: this .containerRef = UIDCsmConverter
155: .UIDtoIdentifiable(this .containerUID);
156: assert (this .containerRef != null || this .containerUID == null) : "null object for UID "
157: + this .containerUID;
158: }
159: }
160:
161: public CharSequence getQualifiedName() {
162: CsmObject container = _getContainer();
163: if (CsmKindUtilities.isClass(container)) {
164: return CharSequenceKey.create(((CsmClass) container)
165: .getQualifiedName()
166: + "::" + getQualifiedNamePostfix()); // NOI18N
167: } else if (CsmKindUtilities.isNamespace(container)) {
168: CharSequence nsName = ((CsmNamespace) container)
169: .getQualifiedName();
170: if (nsName != null && nsName.length() > 0) {
171: return CharSequenceKey.create(nsName.toString() + "::"
172: + getQualifiedNamePostfix()); // NOI18N
173: }
174: }
175: return getName();
176: }
177:
178: public CharSequence getName() {
179: /*if( name == null ) {
180: AST tokId = null;
181: for( AST token = getAst().getFirstChild(); token != null; token = token.getNextSibling() ) {
182: if( token.getType() == CPPTokenTypes.CSM_QUALIFIED_ID ) {
183: AST child = token.getFirstChild();
184: if( child != null && child.getType() == CPPTokenTypes.ID ) {
185: name = child.getText();
186: }
187: }
188: }
189: }
190: if( name == null ) {
191: name = "";
192: }*/
193: return name;
194: }
195:
196: public CsmDeclaration.Kind getKind() {
197: return CsmDeclaration.Kind.TYPEDEF;
198: }
199:
200: private final CsmType createType(AST node) {
201: //
202: // TODO: replace this horrible code with correct one
203: //
204: //if( type == null ) {
205: AST ptrOperator = null;
206: int arrayDepth = 0;
207: AST classifier = null;
208: for (AST token = node.getFirstChild(); token != null; token = token
209: .getNextSibling()) {
210: // if( token.getType() == CPPTokenTypes.CSM_TYPE_COMPOUND ||
211: // token.getType() == CPPTokenTypes.CSM_TYPE_BUILTIN ) {
212: // classifier = token;
213: // break;
214: // }
215: switch (token.getType()) {
216: case CPPTokenTypes.CSM_TYPE_COMPOUND:
217: case CPPTokenTypes.CSM_TYPE_BUILTIN:
218: classifier = token;
219: break;
220: case CPPTokenTypes.LITERAL_struct:
221: AST next = token.getNextSibling();
222: if (next != null
223: && next.getType() == CPPTokenTypes.CSM_QUALIFIED_ID) {
224: classifier = next;
225: break;
226: }
227: break;
228: }
229: if (classifier != null) {
230: break;
231: }
232: }
233: if (classifier != null) {
234: return TypeFactory.createType(classifier,
235: getContainingFile(), ptrOperator, arrayDepth);
236: }
237: //}
238: return null;
239: }
240:
241: public CsmType getType() {
242: return type;
243: }
244:
245: private CsmObject _getContainer() {
246: CsmObject container = this .containerRef;
247: if (container == null) {
248: container = UIDCsmConverter
249: .UIDtoIdentifiable(this .containerUID);
250: assert (container != null || this .containerUID == null) : "null object for UID "
251: + this .containerUID;
252: }
253: return container;
254: }
255:
256: ////////////////////////////////////////////////////////////////////////////
257: // impl of SelfPersistent
258:
259: @Override
260: public void write(DataOutput output) throws IOException {
261: super .write(output);
262: assert this .name != null;
263: output.writeUTF(this .name.toString());
264: output.writeBoolean(typeUnnamed);
265: assert this .type != null;
266: PersistentUtils.writeType(this .type, output);
267:
268: // not null
269: assert this .containerUID != null;
270: UIDObjectFactory.getDefaultFactory().writeUID(
271: this .containerUID, output);
272: }
273:
274: public TypedefImpl(DataInput input) throws IOException {
275: super (input);
276: this .name = QualifiedNameCache.getManager().getString(
277: input.readUTF());
278: assert this .name != null;
279: typeUnnamed = input.readBoolean();
280: this .type = PersistentUtils.readType(input);
281: assert this .type != null;
282:
283: this .containerUID = UIDObjectFactory.getDefaultFactory()
284: .readUID(input);
285: // not null UID
286: assert this.containerUID != null;
287: this.containerRef = null;
288: }
289: }
|