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 org.netbeans.modules.cnd.modelimpl.parser.CsmAST;
045: import java.util.*;
046: import org.netbeans.modules.cnd.api.model.*;
047: import antlr.collections.AST;
048: import java.io.DataInput;
049: import java.io.DataOutput;
050: import java.io.IOException;
051: import org.netbeans.modules.cnd.modelimpl.parser.generated.CPPTokenTypes;
052: import org.netbeans.modules.cnd.modelimpl.csm.core.*;
053: import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
054: import org.netbeans.modules.cnd.modelimpl.repository.RepositoryUtils;
055: import org.netbeans.modules.cnd.modelimpl.textcache.NameCache;
056: import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
057: import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
058: import org.netbeans.modules.cnd.utils.cache.CharSequenceKey;
059:
060: /**
061: * Implements CsmClass
062: * @author Vladimir Kvashin
063: */
064: public class ClassImpl extends ClassEnumBase<CsmClass> implements
065: CsmClass, CsmMember<CsmClass>, CsmTemplate {
066:
067: private final CsmDeclaration.Kind kind;
068:
069: private final List<CsmUID<CsmMember>> members = new ArrayList<CsmUID<CsmMember>>();
070:
071: private final List<CsmUID<CsmFriend>> friends = new ArrayList<CsmUID<CsmFriend>>();
072:
073: private final List<CsmInheritance> inheritances = new ArrayList<CsmInheritance>();
074:
075: private List<CsmTemplateParameter> templateParams = Collections
076: .emptyList();
077: private CharSequence templateSuffix;
078: private boolean template;
079:
080: private/*final*/int leftBracketPos;
081:
082: private class ClassAstRenderer extends AstRenderer {
083:
084: private CsmVisibility curentVisibility = CsmVisibility.PRIVATE;
085:
086: public ClassAstRenderer() {
087: super ((FileImpl) ClassImpl.this .getContainingFile());
088: }
089:
090: @Override
091: protected VariableImpl createVariable(AST offsetAst,
092: CsmFile file, CsmType type, String name,
093: boolean _static,
094: MutableDeclarationsContainer container1,
095: MutableDeclarationsContainer container2, CsmScope scope) {
096: type = TemplateUtils
097: .checkTemplateType(type, ClassImpl.this );
098: FieldImpl field = new FieldImpl(offsetAst, file, type,
099: name, ClassImpl.this , curentVisibility);
100: ClassImpl.this .addMember(field);
101: return field;
102: }
103:
104: @Override
105: public void render(AST ast) {
106: boolean rcurlyFound = false;
107: CsmTypedef[] typedefs;
108: AST child;
109: for (AST token = ast.getFirstChild(); token != null; token = token
110: .getNextSibling()) {
111: switch (token.getType()) {
112: //case CPPTokenTypes.CSM_TEMPLATE_PARMLIST:
113: case CPPTokenTypes.LITERAL_template:
114: template = true;
115: templateSuffix = '<' + TemplateUtils
116: .getClassSpecializationSuffix(token) + '>';
117: templateParams = TemplateUtils
118: .getTemplateParameters(token,
119: ClassImpl.this );
120: break;
121: case CPPTokenTypes.CSM_BASE_SPECIFIER:
122: inheritances.add(new InheritanceImpl(token,
123: getContainingFile()));
124: break;
125: // class / struct / union
126: case CPPTokenTypes.LITERAL_class:
127: break;
128: case CPPTokenTypes.LITERAL_union:
129: curentVisibility = CsmVisibility.PUBLIC;
130: break;
131: case CPPTokenTypes.LITERAL_struct:
132: curentVisibility = CsmVisibility.PUBLIC;
133: break;
134:
135: // visibility
136: case CPPTokenTypes.LITERAL_public:
137: curentVisibility = CsmVisibility.PUBLIC;
138: break;
139: case CPPTokenTypes.LITERAL_private:
140: curentVisibility = CsmVisibility.PRIVATE;
141: break;
142: case CPPTokenTypes.LITERAL_protected:
143: curentVisibility = CsmVisibility.PROTECTED;
144: break;
145:
146: // inner classes and enums
147: case CPPTokenTypes.CSM_CLASS_DECLARATION:
148: case CPPTokenTypes.CSM_TEMPLATE_CLASS_DECLARATION:
149: ClassImpl innerClass = TemplateUtils
150: .isPartialClassSpecialization(token) ? ClassImplSpecialization
151: .create(token, ClassImpl.this ,
152: getContainingFile())
153: : ClassImpl.create(token, ClassImpl.this ,
154: getContainingFile());
155: innerClass.setVisibility(curentVisibility);
156: addMember(innerClass);
157: typedefs = renderTypedef(token, innerClass,
158: ClassImpl.this );
159: if (typedefs != null && typedefs.length > 0) {
160: for (int i = 0; i < typedefs.length; i++) {
161: // It could be important to register in project before add as member...
162: ((FileImpl) getContainingFile())
163: .getProjectImpl()
164: .registerDeclaration(typedefs[i]);
165: addMember((MemberTypedef) typedefs[i]);
166: }
167: }
168: renderVariableInClassifier(token, innerClass, null,
169: null);
170: break;
171: case CPPTokenTypes.CSM_ENUM_DECLARATION:
172: EnumImpl innerEnum = EnumImpl.create(token,
173: ClassImpl.this , getContainingFile());
174: innerEnum.setVisibility(curentVisibility);
175: addMember(innerEnum);
176: renderVariableInClassifier(token, innerEnum, null,
177: null);
178: break;
179:
180: // other members
181: case CPPTokenTypes.CSM_CTOR_DEFINITION:
182: case CPPTokenTypes.CSM_CTOR_TEMPLATE_DEFINITION:
183: addMember(new ConstructorDDImpl(token,
184: ClassImpl.this , curentVisibility));
185: break;
186: case CPPTokenTypes.CSM_CTOR_DECLARATION:
187: case CPPTokenTypes.CSM_CTOR_TEMPLATE_DECLARATION:
188: addMember(new ConstructorImpl(token,
189: ClassImpl.this , curentVisibility));
190: break;
191: case CPPTokenTypes.CSM_DTOR_DEFINITION:
192: case CPPTokenTypes.CSM_DTOR_TEMPLATE_DEFINITION:
193: addMember(new DestructorDDImpl(token,
194: ClassImpl.this , curentVisibility));
195: break;
196: case CPPTokenTypes.CSM_DTOR_DECLARATION:
197: addMember(new DestructorImpl(token, ClassImpl.this ,
198: curentVisibility));
199: break;
200: case CPPTokenTypes.CSM_FIELD:
201: child = token.getFirstChild();
202: if (child != null
203: && child.getType() == CPPTokenTypes.LITERAL_friend) {
204: addFriend(new FriendClassImpl(child,
205: (FileImpl) getContainingFile(),
206: ClassImpl.this ));
207: } else {
208: if (renderVariable(token, null, null)) {
209: break;
210: }
211: typedefs = renderTypedef(token,
212: (FileImpl) getContainingFile(),
213: ClassImpl.this );
214: if (typedefs != null && typedefs.length > 0) {
215: for (int i = 0; i < typedefs.length; i++) {
216: // It could be important to register in project before add as member...
217: ((FileImpl) getContainingFile())
218: .getProjectImpl()
219: .registerDeclaration(
220: typedefs[i]);
221: addMember((MemberTypedef) typedefs[i]);
222: }
223: break;
224: }
225: if (renderBitField(token)) {
226: break;
227: }
228: }
229: break;
230: case CPPTokenTypes.CSM_FUNCTION_DECLARATION:
231: case CPPTokenTypes.CSM_FUNCTION_TEMPLATE_DECLARATION:
232: case CPPTokenTypes.CSM_USER_TYPE_CAST:
233: child = token.getFirstChild();
234: if (child != null) {
235: if (child.getType() == CPPTokenTypes.LITERAL_friend) {
236: CsmScope scope = ClassImpl.this .getScope();
237: CsmFriendFunction friend;
238: CsmFunction func;
239: if (isMemberDefinition(token)) {
240: FriendFunctionImplEx impl = new FriendFunctionImplEx(
241: token, ClassImpl.this , scope);
242: func = impl;
243: friend = impl;
244: } else {
245: FriendFunctionImpl impl = new FriendFunctionImpl(
246: token, ClassImpl.this , scope);
247: friend = impl;
248: func = impl;
249: if (scope instanceof NamespaceImpl) {
250: ((NamespaceImpl) scope)
251: .addDeclaration(func);
252: } else {
253: ((NamespaceImpl) getContainingFile()
254: .getProject()
255: .getGlobalNamespace())
256: .addDeclaration(func);
257: }
258: }
259: //((FileImpl)getContainingFile()).addDeclaration(func);
260: addFriend(friend);
261: } else {
262: addMember(new MethodImpl(token,
263: ClassImpl.this , curentVisibility));
264: }
265: }
266: break;
267: case CPPTokenTypes.CSM_FUNCTION_DEFINITION:
268: case CPPTokenTypes.CSM_FUNCTION_TEMPLATE_DEFINITION:
269: case CPPTokenTypes.CSM_USER_TYPE_CAST_DEFINITION:
270: child = token.getFirstChild();
271: if (child != null
272: && child.getType() == CPPTokenTypes.LITERAL_friend) {
273: CsmScope scope = ClassImpl.this .getScope();
274: CsmFriendFunction friend;
275: CsmFunction func;
276: if (isMemberDefinition(token)) {
277: FriendFunctionDefinitionImpl impl = new FriendFunctionDefinitionImpl(
278: token, ClassImpl.this , null);
279: func = impl;
280: friend = impl;
281: } else {
282: FriendFunctionDDImpl impl = new FriendFunctionDDImpl(
283: token, ClassImpl.this , scope);
284: friend = impl;
285: func = impl;
286: if (scope instanceof NamespaceImpl) {
287: ((NamespaceImpl) scope)
288: .addDeclaration(func);
289: } else {
290: ((NamespaceImpl) getContainingFile()
291: .getProject()
292: .getGlobalNamespace())
293: .addDeclaration(func);
294: }
295: }
296: //((FileImpl)getContainingFile()).addDeclaration(func);
297: addFriend(friend);
298: } else {
299: addMember(new MethodDDImpl(token,
300: ClassImpl.this , curentVisibility));
301: }
302: break;
303: case CPPTokenTypes.CSM_VISIBILITY_REDEF:
304: break;
305: case CPPTokenTypes.RCURLY:
306: rcurlyFound = true;
307: break;
308: case CPPTokenTypes.CSM_VARIABLE_DECLARATION:
309: //new VariableImpl(
310: break;
311: }
312: }
313: }
314:
315: private boolean renderBitField(AST token) {
316:
317: AST typeAST = token.getFirstChild();
318: if (typeAST == null
319: || (typeAST.getType() != CPPTokenTypes.CSM_TYPE_BUILTIN && typeAST
320: .getType() != CPPTokenTypes.CSM_TYPE_COMPOUND)) {
321: return false;
322: }
323:
324: AST idAST = typeAST.getNextSibling();
325: if (idAST == null || idAST.getType() != CPPTokenTypes.ID) {
326: return false;
327: }
328:
329: AST colonAST = idAST.getNextSibling();
330: if (colonAST == null
331: || colonAST.getType() != CPPTokenTypes.COLON) {
332: return false;
333: }
334:
335: CsmType type = TypeFactory.createType(typeAST,
336: getContainingFile(), null, 0);
337: FieldImpl field = new FieldImpl(token, getContainingFile(),
338: type, idAST.getText(), ClassImpl.this ,
339: curentVisibility);
340: ClassImpl.this .addMember(field);
341:
342: return true;
343: }
344:
345: @Override
346: protected CsmTypedef createTypedef(AST ast, FileImpl file,
347: CsmObject container, CsmType type, String name) {
348: return new MemberTypedef(ClassImpl.this , ast, type, name,
349: curentVisibility);
350: }
351: }
352:
353: public static class MemberTypedef extends TypedefImpl implements
354: CsmMember<CsmTypedef> {
355: private CsmVisibility visibility;
356:
357: public MemberTypedef(CsmClass containingClass, AST ast,
358: CsmType type, String name,
359: CsmVisibility curentVisibility) {
360: super (ast, containingClass.getContainingFile(),
361: containingClass, type, name);
362: visibility = curentVisibility;
363: }
364:
365: public boolean isStatic() {
366: return false;
367: }
368:
369: public CsmVisibility getVisibility() {
370: return visibility;
371: }
372:
373: public CsmClass getContainingClass() {
374: return (CsmClass) getScope();
375: }
376:
377: ////////////////////////////////////////////////////////////////////////////
378: // impl of SelfPersistent
379:
380: @Override
381: public void write(DataOutput output) throws IOException {
382: super .write(output);
383: assert this .visibility != null;
384: PersistentUtils.writeVisibility(this .visibility, output);
385: }
386:
387: public MemberTypedef(DataInput input) throws IOException {
388: super (input);
389: this .visibility = PersistentUtils.readVisibility(input);
390: assert this .visibility != null;
391: }
392: }
393:
394: // public ClassImpl(CsmDeclaration.Kind kind, String name, NamespaceImpl namespace, CsmFile file) {
395: // this(kind, name, namespace, file, null);
396: // }
397: //
398: // public ClassImpl(CsmDeclaration.Kind kind, String name, NamespaceImpl namespace, CsmFile file, CsmClass containingClass) {
399: // super(name, namespace, file, containingClass, null);
400: // leftBracketPos = 0;
401: // this.kind = CsmDeclaration.Kind.CLASS;
402: // register();
403: // }
404:
405: protected ClassImpl(AST ast, CsmFile file) {
406: // we call findId(..., true) because there might be qualified name - in the case of nested class template specializations
407: super (AstUtil.findId(ast, CPPTokenTypes.RCURLY, true), file,
408: ast);
409: kind = findKind(ast);
410: }
411:
412: @Override
413: protected void init(CsmScope scope, AST ast) {
414: super .init(scope, ast);
415: RepositoryUtils.hang(this ); // "hang" now and then "put" in "register()"
416: new ClassAstRenderer().render(ast);
417: leftBracketPos = initLeftBracketPos(ast);
418: register(scope);
419: }
420:
421: public static ClassImpl create(AST ast, CsmScope scope, CsmFile file) {
422: ClassImpl impl = new ClassImpl(ast, file);
423: impl.init(scope, ast);
424: return impl;
425: }
426:
427: public CsmDeclaration.Kind getKind() {
428: return this .kind;
429: }
430:
431: public Collection<CsmMember> getMembers() {
432: Collection<CsmMember> out;
433: synchronized (members) {
434: out = UIDCsmConverter.UIDsToDeclarations(members);
435: }
436: return out;
437: }
438:
439: public Collection<CsmFriend> getFriends() {
440: Collection<CsmFriend> out;
441: synchronized (friends) {
442: out = UIDCsmConverter.UIDsToDeclarations(friends);
443: }
444: return out;
445: }
446:
447: public List<CsmInheritance> getBaseClasses() {
448: return inheritances;
449: }
450:
451: public boolean isTemplate() {
452: return template;
453: }
454:
455: private void addMember(CsmMember member) {
456: CsmUID<CsmMember> uid = RepositoryUtils.put(member);
457: assert uid != null;
458: synchronized (members) {
459: members.add(uid);
460: }
461: }
462:
463: private void addFriend(CsmFriend friend) {
464: CsmUID<CsmFriend> uid = RepositoryUtils.put(friend);
465: assert uid != null;
466: synchronized (friends) {
467: friends.add(uid);
468: }
469: }
470:
471: private int initLeftBracketPos(AST node) {
472: AST lcurly = AstUtil
473: .findChildOfType(node, CPPTokenTypes.LCURLY);
474: return (lcurly instanceof CsmAST) ? ((CsmAST) lcurly)
475: .getOffset() : getStartOffset();
476: }
477:
478: public int getLeftBracketOffset() {
479: return leftBracketPos;
480: }
481:
482: public Collection<CsmScopeElement> getScopeElements() {
483: return (Collection) getMembers();
484: }
485:
486: @Override
487: public void dispose() {
488: _clearMembers();
489: _clearFriends();
490: super .dispose();
491: }
492:
493: private void _clearMembers() {
494: Collection<CsmMember> members2dispose = getMembers();
495: Utils.disposeAll(members2dispose);
496: synchronized (members) {
497: RepositoryUtils.remove(this .members);
498: }
499: }
500:
501: private void _clearFriends() {
502: Collection<CsmFriend> friends2dispose = getFriends();
503: Utils.disposeAll(friends2dispose);
504: synchronized (friends) {
505: RepositoryUtils.remove(this .friends);
506: }
507: }
508:
509: private CsmDeclaration.Kind findKind(AST ast) {
510: for (AST token = ast.getFirstChild(); token != null; token = token
511: .getNextSibling()) {
512: switch (token.getType()) {
513: // class / struct / union
514: case CPPTokenTypes.LITERAL_class:
515: return CsmDeclaration.Kind.CLASS;
516: case CPPTokenTypes.LITERAL_union:
517: return CsmDeclaration.Kind.UNION;
518: case CPPTokenTypes.LITERAL_struct:
519: return CsmDeclaration.Kind.STRUCT;
520: }
521: }
522: return CsmDeclaration.Kind.CLASS;
523: }
524:
525: public CharSequence getDisplayName() {
526: return isTemplate() ? CharSequenceKey.create((getName()
527: .toString() + templateSuffix)) : getName(); // NOI18N
528: }
529:
530: public List<CsmTemplateParameter> getTemplateParameters() {
531: return templateParams;
532: }
533:
534: ////////////////////////////////////////////////////////////////////////////
535: // impl of SelfPersistent
536:
537: @Override
538: public void write(DataOutput output) throws IOException {
539: super .write(output);
540: // private final CsmDeclaration.Kind kind;
541: //
542: // private final List/*<CsmMember>*/ membersOLD = new ArrayList/*<CsmMember>*/();
543: // private final List<CsmUID<CsmMember>> members = new ArrayList<CsmUID<CsmMember>>();
544: //
545: // private final List/*<CsmInheritance>*/ inheritances = new ArrayList/*<CsmInheritance>*/();
546: // private boolean template;
547: //
548: // private final int leftBracketPos;
549: assert this .kind != null;
550: writeKind(this .kind, output);
551: output.writeBoolean(this .template);
552: PersistentUtils.writeTemplateParameters(templateParams, output);
553: if (this .template) {
554: output.writeUTF(this .templateSuffix.toString());
555: }
556: output.writeInt(this .leftBracketPos);
557: UIDObjectFactory factory = UIDObjectFactory.getDefaultFactory();
558: factory.writeUIDCollection(this .members, output, true);
559: factory.writeUIDCollection(this .friends, output, true);
560: PersistentUtils.writeInheritances(this .inheritances, output);
561: }
562:
563: public ClassImpl(DataInput input) throws IOException {
564: super (input);
565: this .kind = readKind(input);
566: this .template = input.readBoolean();
567: this .templateParams = PersistentUtils
568: .readTemplateParameters(input);
569: if (this .template) {
570: this .templateSuffix = NameCache.getManager().getString(
571: input.readUTF());
572: }
573: this .leftBracketPos = input.readInt();
574: UIDObjectFactory factory = UIDObjectFactory.getDefaultFactory();
575: factory.readUIDCollection(this .members, input);
576: factory.readUIDCollection(this .friends, input);
577: PersistentUtils.readInheritances(this .inheritances, input);
578: }
579:
580: private static final int CLASS_KIND = 1;
581: private static final int UNION_KIND = 2;
582: private static final int STRUCT_KIND = 3;
583:
584: private static void writeKind(CsmDeclaration.Kind kind,
585: DataOutput output) throws IOException {
586: int kindHandler;
587: if (kind == CsmDeclaration.Kind.CLASS) {
588: kindHandler = CLASS_KIND;
589: } else if (kind == CsmDeclaration.Kind.UNION) {
590: kindHandler = UNION_KIND;
591: } else {
592: assert kind == CsmDeclaration.Kind.STRUCT;
593: kindHandler = STRUCT_KIND;
594: }
595: output.writeByte(kindHandler);
596: }
597:
598: private static CsmDeclaration.Kind readKind(DataInput input)
599: throws IOException {
600: int kindHandler = input.readByte();
601: CsmDeclaration.Kind kind;
602: switch (kindHandler) {
603: case CLASS_KIND:
604: kind = CsmDeclaration.Kind.CLASS;
605: break;
606: case UNION_KIND:
607: kind = CsmDeclaration.Kind.UNION;
608: break;
609: case STRUCT_KIND:
610: kind = CsmDeclaration.Kind.STRUCT;
611: break;
612: default:
613: throw new IllegalArgumentException("illegal handler "
614: + kindHandler); // NOI18N
615: }
616: return kind;
617: }
618:
619: }
|