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 java.util.*;
045: import java.util.List;
046:
047: import org.netbeans.modules.cnd.api.model.*;
048: import org.netbeans.modules.cnd.api.model.CsmFunction.OperatorKind;
049: import org.netbeans.modules.cnd.api.model.deep.CsmCompoundStatement;
050: import antlr.collections.AST;
051: import java.io.DataInput;
052: import java.io.DataOutput;
053: import java.io.IOException;
054: import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
055: import org.netbeans.modules.cnd.modelimpl.parser.generated.CPPTokenTypes;
056: import org.netbeans.modules.cnd.modelimpl.csm.core.*;
057: import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
058: import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
059: import org.netbeans.modules.cnd.modelimpl.repository.RepositoryUtils;
060: import org.netbeans.modules.cnd.modelimpl.textcache.NameCache;
061: import org.netbeans.modules.cnd.modelimpl.textcache.QualifiedNameCache;
062: import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
063: import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
064: import org.netbeans.modules.cnd.utils.cache.CharSequenceKey;
065:
066: /**
067: *
068: * @param T
069: * @author Dmitriy Ivanov, Vladimir Kvashin
070: */
071: public class FunctionImpl<T> extends OffsetableDeclarationBase<T>
072: implements CsmFunction<T>, Disposable, RawNamable, CsmTemplate {
073:
074: private static final String OPERATOR = "operator"; // NOI18N;
075:
076: private static final CharSequence NULL = CharSequenceKey
077: .create("<null>"); // NOI18N
078: private CharSequence name;
079: private final CsmType returnType;
080: private final List<CsmUID<CsmParameter>> parameters;
081: private CharSequence signature;
082:
083: // only one of scopeRef/scopeAccessor must be used
084: private/*final*/CsmScope scopeRef;// can be set in onDispose or contstructor only
085: private final CsmUID<CsmScope> scopeUID;
086:
087: private final CharSequence[] rawName;
088:
089: private List<CsmTemplateParameter> templateParams = Collections
090: .emptyList();
091:
092: private CharSequence templateSuffix;
093: protected CharSequence classTemplateSuffix;
094:
095: private static final byte FLAGS_VOID_PARMLIST = 1 << 0;
096: private static final byte FLAGS_STATIC = 1 << 1;
097: private static final byte FLAGS_CONST = 1 << 2;
098: private static final byte FLAGS_OPERATOR = 1 << 3;
099: private static final byte FLAGS_TEMPLATE = 1 << 4;
100: private byte flags;
101:
102: public FunctionImpl(AST ast, CsmFile file, CsmScope scope) {
103: this (ast, file, scope, true);
104: }
105:
106: private static final boolean CHECK_SCOPE = false;
107:
108: protected FunctionImpl(AST ast, CsmFile file, CsmScope scope,
109: boolean register) {
110:
111: super (ast, file);
112: assert !CHECK_SCOPE || (scope != null);
113:
114: name = QualifiedNameCache.getManager().getString(initName(ast));
115: rawName = AstUtil.getRawNameInChildren(ast);
116:
117: assert ast.getFirstChild() != null;
118: setStatic(ast.getFirstChild().getType() == CPPTokenTypes.LITERAL_static);
119: if (!isStatic()) {
120: for (CsmFunction fu : ((FileImpl) file)
121: .getStaticFunctionDeclarations()) {
122: if (name.equals(fu.getName())) {
123: // we don't check signature here since file-level statics
124: // is C-style construct
125: setStatic(true);
126: break;
127: }
128: }
129: }
130:
131: // change scope to file for static methods, but only to prevent
132: // registration in global namespace
133: if (isStatic() && CsmKindUtilities.isNamespace(scope)
134: && ((CsmNamespace) scope).isGlobal()) {
135: scope = file;
136: }
137:
138: // set scope, do it in constructor to have final fields
139: this .scopeUID = UIDCsmConverter.scopeToUID(scope);
140: assert (this .scopeUID != null || scope == null);
141: this .scopeRef = null;
142:
143: RepositoryUtils.hang(this ); // "hang" now and then "put" in "register()"
144:
145: boolean _const = initConst(ast);
146: setFlags(FLAGS_CONST, _const);
147: returnType = initReturnType(ast, scope);
148: initTemplate(ast);
149:
150: // set parameters, do it in constructor to have final fields
151: List<CsmParameter> params = initParameters(ast);
152: if (params == null) {
153: this .parameters = null;
154: } else {
155: this .parameters = RepositoryUtils.put(params);
156: }
157: if (params == null || params.size() == 0) {
158: setFlags(FLAGS_VOID_PARMLIST, isVoidParameter(ast));
159: } else {
160: setFlags(FLAGS_VOID_PARMLIST, false);
161: }
162: if (name == null) {
163: name = NULL; // just to avoid NPE
164: }
165: if (name.toString().startsWith(OPERATOR)
166: && (name.length() > OPERATOR.length())
167: && !Character.isJavaIdentifierPart(name.charAt(OPERATOR
168: .length()))) { // NOI18N
169: setFlags(FLAGS_OPERATOR, true);
170: }
171: if (register) {
172: registerInProject();
173: }
174: }
175:
176: private boolean hasFlags(byte mask) {
177: return (flags & mask) == mask;
178: }
179:
180: private void setFlags(byte mask, boolean value) {
181: if (value) {
182: flags |= mask;
183: } else {
184: flags &= ~mask;
185: }
186: }
187:
188: public boolean isStatic() {
189: return hasFlags(FLAGS_STATIC);
190: }
191:
192: protected void setStatic(boolean value) {
193: setFlags(FLAGS_STATIC, value);
194: }
195:
196: private AST findParameterNode(AST node) {
197: AST ast = AstUtil.findChildOfType(node,
198: CPPTokenTypes.CSM_PARMLIST);
199: if (ast != null) {
200: // for K&R-style
201: AST ast2 = AstUtil.findSiblingOfType(ast.getNextSibling(),
202: CPPTokenTypes.CSM_KR_PARMLIST);
203: if (ast2 != null) {
204: ast = ast2;
205: }
206: }
207: return ast;
208: }
209:
210: private void initTemplate(AST node) {
211: boolean _template = false, specialization = false;
212: switch (node.getType()) {
213: case CPPTokenTypes.CSM_FUNCTION_TEMPLATE_DECLARATION:
214: case CPPTokenTypes.CSM_FUNCTION_TEMPLATE_DEFINITION:
215: case CPPTokenTypes.CSM_CTOR_TEMPLATE_DECLARATION:
216: case CPPTokenTypes.CSM_CTOR_TEMPLATE_DEFINITION:
217: _template = true;
218: break;
219: case CPPTokenTypes.CSM_TEMPLATE_FUNCTION_DEFINITION_EXPLICIT_SPECIALIZATION:
220: case CPPTokenTypes.CSM_TEMPLATE_EXPLICIT_SPECIALIZATION:
221: _template = true;
222: specialization = true;
223: break;
224: }
225:
226: if (_template) {
227: AST templateNode = node.getFirstChild();
228: assert (templateNode != null && templateNode.getType() == CPPTokenTypes.LITERAL_template);
229: // 0. our grammar can't yet differ template-class's method from template-method
230: // so we need to check here if we has template-class or not
231: boolean templateClass = false;
232: AST qIdToken = AstUtil.findChildOfType(node,
233: CPPTokenTypes.CSM_QUALIFIED_ID);
234: // 1. check for definition of template class's method
235: // like template<class A> C<A>:C() {}
236: AST startTemplateSign = qIdToken != null ? AstUtil
237: .findChildOfType(qIdToken, CPPTokenTypes.LESSTHAN)
238: : null;
239: if (startTemplateSign != null) {
240: // TODO: fix parsing of inline definition of template operator <
241: // like template<class T, class P> bool operator<(T x, P y) {return x<y};
242: // workaround is next validation
243: AST endTemplateSign = null;//( startTemplateSign.getNextSibling() != null ? startTemplateSign.getNextSibling().getNextSibling() : null);
244: for (AST sibling = startTemplateSign.getNextSibling(); sibling != null; sibling = sibling
245: .getNextSibling()) {
246: if (sibling.getType() == CPPTokenTypes.GREATERTHAN) {
247: endTemplateSign = sibling;
248: break;
249: }
250: }
251: if (endTemplateSign != null) {
252: AST scopeSign = endTemplateSign.getNextSibling();
253: if (scopeSign != null
254: && scopeSign.getType() == CPPTokenTypes.SCOPE) {
255: // 2. we have template class, we need to determine, is it specialization definition or not
256: if (specialization) {
257: // we need to initialize classTemplateSuffix in this case
258: // to avoid mixing different specialization (IZ92138)
259: this .classTemplateSuffix = TemplateUtils
260: .getSpecializationSuffix(qIdToken);
261: }
262: // but there is still a chance to have template-method of template-class
263: // e.g.: template<class A> template<class B> C<A>::C(B b) {}
264: AST templateSiblingNode = templateNode
265: .getNextSibling();
266: if (templateSiblingNode != null
267: && templateSiblingNode.getType() == CPPTokenTypes.LITERAL_template) {
268: // it is template-method of template-class
269: templateNode = templateSiblingNode;
270: } else {
271: // we have no template-method at all
272: _template = false;
273: }
274: }
275: }
276: }
277:
278: if (_template) {
279: // 3. We are sure now what we have template-method,
280: // let's check is it specialization template or not
281: if (specialization) {
282: // 3a. specialization
283: if (qIdToken == null) {
284: // malformed template specification
285: templateSuffix = "<>"; //NOI18N
286: } else {
287: templateSuffix = TemplateUtils
288: .getSpecializationSuffix(qIdToken);
289: }
290: } else {
291: // 3b. no specialization, plain and simple template-method
292: StringBuilder sb = new StringBuilder();
293: TemplateUtils.addSpecializationSuffix(templateNode
294: .getFirstChild(), sb);
295: templateSuffix = '<' + sb.toString() + '>';
296: }
297: }
298: }
299: setFlags(FLAGS_TEMPLATE, _template);
300: if (_template) {
301: this .templateParams = TemplateUtils.getTemplateParameters(
302: node.getFirstChild(), this );
303: }
304: }
305:
306: protected CharSequence getScopeSuffix() {
307: return classTemplateSuffix != null ? classTemplateSuffix : "";
308: }
309:
310: protected String initName(AST node) {
311: return findFunctionName(node);
312: }
313:
314: public CharSequence getDisplayName() {
315: return isTemplate() ? CharSequenceKey.create(getName()
316: .toString()
317: + templateSuffix) : getName();
318: }
319:
320: public List<CsmTemplateParameter> getTemplateParameters() {
321: return templateParams;
322: }
323:
324: public boolean isVoidParameterList() {
325: return hasFlags(FLAGS_VOID_PARMLIST);
326: }
327:
328: private static String extractName(AST token) {
329: int type = token.getType();
330: if (type == CPPTokenTypes.ID) {
331: return token.getText();
332: } else if (type == CPPTokenTypes.CSM_QUALIFIED_ID) {
333: AST last = AstUtil.getLastChild(token);
334: if (last != null) {
335: if (last.getType() == CPPTokenTypes.ID) {
336: return last.getText();
337: } else {
338: // if( first.getType() == CPPTokenTypes.LITERAL_OPERATOR ) {
339: AST operator = AstUtil.findChildOfType(token,
340: CPPTokenTypes.LITERAL_OPERATOR);
341: if (operator != null) {
342: StringBuilder sb = new StringBuilder(operator
343: .getText());
344: sb.append(' ');
345: for (AST next = operator.getNextSibling(); next != null; next = next
346: .getNextSibling()) {
347: sb.append(next.getText());
348: }
349: return sb.toString();
350: } else {
351: AST first = token.getFirstChild();
352: if (first.getType() == CPPTokenTypes.ID) {
353: return first.getText();
354: }
355: }
356: }
357: }
358: }
359: return "";
360: }
361:
362: private static String findFunctionName(AST ast) {
363: if (CastUtils.isCast(ast)) {
364: return CastUtils.getFunctionName(ast);
365: }
366: AST token = AstUtil.findMethodName(ast);
367: if (token != null) {
368: return extractName(token);
369: }
370: return "";
371: }
372:
373: protected boolean isCStyleStatic() {
374: return isStatic() && CsmKindUtilities.isFile(getScope());
375: }
376:
377: protected void registerInProject() {
378: if (isCStyleStatic()) {
379: // do NOT register in project C-style static funcions!
380: return;
381: }
382: CsmProject project = getContainingFile().getProject();
383: if (project instanceof ProjectBase) {
384: // implicitely calls RepositoryUtils.put()
385: ((ProjectBase) project).registerDeclaration(this );
386: }
387: }
388:
389: private void unregisterInProject() {
390: CsmProject project = getContainingFile().getProject();
391: if (project instanceof ProjectBase) {
392: ((ProjectBase) project).unregisterDeclaration(this );
393: this .cleanUID();
394: }
395: }
396:
397: /** Gets this element name
398: * @return name
399: */
400: public CharSequence getName() {
401: return name;
402: }
403:
404: protected final void setName(CharSequence name) {
405: this .name = QualifiedNameCache.getManager().getString(name);
406: }
407:
408: public CharSequence getQualifiedName() {
409: CsmScope scope = getScope();
410: if ((scope instanceof CsmNamespace)
411: || (scope instanceof CsmClass)) {
412: CharSequence scopeQName = ((CsmQualifiedNamedElement) scope)
413: .getQualifiedName();
414: if (scopeQName != null && scopeQName.length() > 0) {
415: return CharSequenceKey.create(scopeQName.toString()
416: + getScopeSuffix() + "::"
417: + getQualifiedNamePostfix()); // NOI18N
418: }
419: }
420: return getName();
421: }
422:
423: public CharSequence[] getRawName() {
424: return rawName;
425: }
426:
427: @Override
428: public CharSequence getUniqueNameWithoutPrefix() {
429: return getQualifiedName().toString()
430: + (isTemplate() ? templateSuffix : "")
431: + getSignature().toString().substring(
432: getName().length());
433: }
434:
435: public Kind getKind() {
436: return CsmDeclaration.Kind.FUNCTION;
437: }
438:
439: /** Gets this function's declaration text
440: * @return declaration text
441: */
442: public String getDeclarationText() {
443: return "";
444: }
445:
446: /**
447: * Gets this function definition
448: * TODO: describe getDefiition==this ...
449: * @return definition
450: */
451: public CsmFunctionDefinition getDefinition() {
452: if (isCStyleStatic()) {
453: for (CsmDeclaration decl : getContainingFile()
454: .getDeclarations()) {
455: if (CsmKindUtilities.isFunctionDefinition(decl)) {
456: if (getName().equals(decl.getName())) {
457: CsmFunctionDefinition fun = (CsmFunctionDefinition) decl;
458: if (getSignature().equals(fun.getSignature())) {
459: return fun;
460: }
461: }
462: }
463: }
464: return null;
465: }
466: String uname = Utils
467: .getCsmDeclarationKindkey(CsmDeclaration.Kind.FUNCTION_DEFINITION)
468: + UNIQUE_NAME_SEPARATOR + getUniqueNameWithoutPrefix();
469: CsmProject prj = getContainingFile().getProject();
470: CsmFunctionDefinition def = findDefinition(prj, uname);
471: if (def == null) {
472: for (CsmProject lib : prj.getLibraries()) {
473: def = findDefinition(lib, uname);
474: if (def != null) {
475: break;
476: }
477: }
478: }
479: if (def == null && (prj instanceof ProjectBase)) {
480: for (CsmProject dependent : ((ProjectBase) prj)
481: .getDependentProjects()) {
482: def = findDefinition(dependent, uname);
483: if (def != null) {
484: break;
485: }
486: }
487: }
488: return def;
489: }
490:
491: private CsmFunctionDefinition findDefinition(CsmProject prj,
492: String uname) {
493: CsmDeclaration res = prj.findDeclaration(uname);
494: if (res instanceof CsmFunctionDefinition) {
495: return (CsmFunctionDefinition) res;
496: }
497: if (getParameters().size() == 0 && !isVoidParameterList()) {
498: CsmScope scope = getScope();
499: if (CsmKindUtilities.isNamespace(scope)
500: && ((CsmNamespace) scope).isGlobal()) {
501: if (prj instanceof ProjectBase) {
502: String from = uname.substring(0,
503: uname.indexOf('(') + 1);
504: Collection<CsmOffsetableDeclaration> decls = ((ProjectBase) prj)
505: .findDeclarationsByPrefix(from);
506: for (CsmOffsetableDeclaration decl : decls) {
507: if (!ProjectBase.isCppFile(decl
508: .getContainingFile())) {
509: return (CsmFunctionDefinition) decl;
510: }
511: }
512: }
513: }
514: }
515: return null;
516: }
517:
518: /**
519: * Returns true if this class is template, otherwise false.
520: * If isTemplate() returns true, this class is an instance of CsmTemplate
521: * @return flag indicated if function is template
522: */
523: public boolean isTemplate() {
524: return hasFlags(FLAGS_TEMPLATE);
525: }
526:
527: /**
528: * Gets this function body.
529: * The same as the following call:
530: * (getDefinition() == null) ? null : getDefinition().getBody();
531: *
532: * TODO: perhaps it isn't worth keeping duplicate to getDefinition().getBody()? (though convenient...)
533: * @return body of function
534: */
535: public CsmCompoundStatement getBody() {
536: return null;
537: }
538:
539: public boolean isInline() {
540: return false;
541: }
542:
543: // public boolean isVirtual() {
544: // return false;
545: // }
546: //
547: // public boolean isExplicit() {
548: // return false;
549: // }
550:
551: private CsmType initReturnType(AST node, CsmScope scope) {
552: CsmType ret = null;
553: AST token = getTypeToken(node);
554: if (token != null) {
555: ret = AstRenderer.renderType(token, getContainingFile());
556: }
557: if (ret == null) {
558: ret = TypeFactory.createBuiltinType("int", (AST) null, 0,
559: null/*getAst().getFirstChild()*/,
560: getContainingFile()); // NOI18N
561: }
562: return TemplateUtils.checkTemplateType(ret, scope);
563: }
564:
565: public CsmType getReturnType() {
566: return returnType;
567: }
568:
569: private static AST getTypeToken(AST node) {
570: for (AST token = node.getFirstChild(); token != null; token = token
571: .getNextSibling()) {
572: int type = token.getType();
573: switch (type) {
574: case CPPTokenTypes.CSM_TYPE_BUILTIN:
575: case CPPTokenTypes.CSM_TYPE_COMPOUND:
576: return token;
577: default:
578: if (AstRenderer.isQualifier(type)) {
579: return token;
580: }
581: }
582: }
583: return null;
584: }
585:
586: private List<CsmParameter> initParameters(AST node) {
587: AST ast = findParameterNode(node);
588: return AstRenderer.renderParameters(ast, getContainingFile(),
589: this );
590: }
591:
592: private boolean isVoidParameter(AST node) {
593: AST ast = findParameterNode(node);
594: return AstRenderer.isVoidParameter(ast);
595: }
596:
597: public Collection<CsmParameter> getParameters() {
598: return _getParameters();
599: }
600:
601: public CsmScope getScope() {
602: return _getScope();
603: }
604:
605: public CharSequence getSignature() {
606: if (signature == null) {
607: signature = QualifiedNameCache.getManager().getString(
608: createSignature());
609: }
610: return signature;
611: }
612:
613: public CsmFunction getDeclaration() {
614: return this ;
615: }
616:
617: public boolean isOperator() {
618: return hasFlags(FLAGS_OPERATOR);
619: }
620:
621: public OperatorKind getOperatorKind() {
622: OperatorKind out = OperatorKind.NONE;
623: if (isOperator()) {
624: String strName = getName().toString();
625: int start = strName.indexOf(OPERATOR);
626: assert start >= 0 : "must have word \"operator\" in name";
627: start += OPERATOR.length();
628: String signText = strName.substring(start).trim();
629: out = OperatorKind.getKindByImage(signText);
630: }
631: return out;
632: }
633:
634: public Collection<CsmScopeElement> getScopeElements() {
635: Collection<CsmScopeElement> l = new ArrayList<CsmScopeElement>();
636: l.addAll(getParameters());
637: return l;
638: }
639:
640: private String createSignature() {
641: // TODO: this fake implementation for Deimos only!
642: // we should resolve parameter types and provide
643: // kind of canonical representation here
644: StringBuilder sb = new StringBuilder(getName());
645: sb.append('(');
646: for (Iterator iter = getParameters().iterator(); iter.hasNext();) {
647: CsmParameter param = (CsmParameter) iter.next();
648: CsmType type = param.getType();
649: if (type != null) {
650: sb.append(type.getCanonicalText());
651: if (iter.hasNext()) {
652: sb.append(',');
653: }
654: } else if (param.isVarArgs()) {
655: sb.append("..."); // NOI18N
656: }
657: }
658: sb.append(')');
659: if (isConst()) {
660: sb.append(" const"); // NOI18N
661: }
662: return sb.toString();
663: }
664:
665: @Override
666: public void dispose() {
667: super .dispose();
668: onDispose();
669: CsmScope scope = _getScope();
670: if (scope instanceof MutableDeclarationsContainer) {
671: ((MutableDeclarationsContainer) scope)
672: .removeDeclaration(this );
673: }
674: this .unregisterInProject();
675: _disposeParameters();
676: }
677:
678: private void onDispose() {
679: if (TraceFlags.RESTORE_CONTAINER_FROM_UID) {
680: // restore container from it's UID
681: this .scopeRef = UIDCsmConverter.UIDtoScope(this .scopeUID);
682: assert (this .scopeRef != null || this .scopeUID == null) : "empty scope for UID "
683: + this .scopeUID;
684: }
685: }
686:
687: private static boolean initConst(AST node) {
688: boolean ret = false;
689: AST token = node.getFirstChild();
690: while (token != null
691: && token.getType() != CPPTokenTypes.CSM_QUALIFIED_ID) {
692: token = token.getNextSibling();
693: }
694: while (token != null) {
695: if (token.getType() == CPPTokenTypes.LITERAL_const) {
696: ret = true;
697: break;
698: }
699: token = token.getNextSibling();
700: }
701: return ret;
702: }
703:
704: /**
705: * isConst was originally in MethodImpl;
706: * but this methods needs internally in FunctionDefinitionImpl
707: * to create proper signature.
708: * Therefor it's moved here as a protected method.
709: */
710: protected boolean isConst() {
711: return hasFlags(FLAGS_CONST);
712: }
713:
714: private CsmScope _getScope() {
715: CsmScope scope = this .scopeRef;
716: if (scope == null) {
717: scope = UIDCsmConverter.UIDtoScope(this .scopeUID);
718: assert (scope != null || this .scopeUID == null) : "null object for UID "
719: + this .scopeUID;
720: }
721: return scope;
722: }
723:
724: private Collection _getParameters() {
725: if (this .parameters == null) {
726: return Collections.EMPTY_LIST;
727: } else {
728: Collection<CsmParameter> out = UIDCsmConverter
729: .UIDsToDeclarations(parameters);
730: return out;
731: }
732: }
733:
734: private void _disposeParameters() {
735: if (parameters != null) {
736: RepositoryUtils.remove(parameters);
737: }
738: }
739:
740: ////////////////////////////////////////////////////////////////////////////
741: // iml of SelfPersistent
742:
743: @Override
744: public void write(DataOutput output) throws IOException {
745: super .write(output);
746: assert this .name != null;
747: output.writeUTF(this .name.toString());
748: PersistentUtils.writeType(this .returnType, output);
749: UIDObjectFactory factory = UIDObjectFactory.getDefaultFactory();
750: factory.writeUIDCollection(this .parameters, output, false);
751: PersistentUtils.writeStrings(this .rawName, output);
752:
753: // not null UID
754: assert !CHECK_SCOPE || this .scopeUID != null;
755: UIDObjectFactory.getDefaultFactory().writeUID(this .scopeUID,
756: output);
757:
758: PersistentUtils.writeUTF(this .signature, output);
759: output.writeByte(flags);
760: output.writeUTF(this .getScopeSuffix().toString());
761: if (isTemplate()) {
762: output.writeUTF(this .templateSuffix.toString());
763: }
764: PersistentUtils.writeTemplateParameters(templateParams, output);
765: }
766:
767: public FunctionImpl(DataInput input) throws IOException {
768: super (input);
769: this .name = QualifiedNameCache.getManager().getString(
770: input.readUTF());
771: assert this .name != null;
772: this .returnType = PersistentUtils.readType(input);
773: UIDObjectFactory factory = UIDObjectFactory.getDefaultFactory();
774: this .parameters = factory.readUIDCollection(
775: new ArrayList<CsmUID<CsmParameter>>(), input);
776: this .rawName = PersistentUtils.readStrings(input, NameCache
777: .getManager());
778:
779: this .scopeUID = UIDObjectFactory.getDefaultFactory().readUID(
780: input);
781: // not null UID
782: assert !CHECK_SCOPE || this.scopeUID != null;
783: this.scopeRef = null;
784:
785: this.signature = PersistentUtils.readUTF(input);
786: if (this.signature != null) {
787: this.signature = QualifiedNameCache.getManager().getString(
788: this.signature);
789: }
790: this.flags = input.readByte();
791: this.classTemplateSuffix = NameCache.getManager().getString(
792: input.readUTF());
793: if (isTemplate()) {
794: this.templateSuffix = NameCache.getManager().getString(
795: input.readUTF());
796: }
797: this.templateParams = PersistentUtils
798: .readTemplateParameters(input);
799: }
800: }
|