PageRenderTime 21ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/netbeans-7.3/cnd.model.services/src/org/netbeans/modules/cnd/api/model/services/CsmFileReferences.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 369 lines | 251 code | 23 blank | 95 comment | 77 complexity | 56332454c0ffeb800be02a3be95e9f18 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.modules.cnd.api.model.services;
  45. import java.util.Collection;
  46. import java.util.Map;
  47. import java.util.Set;
  48. import org.netbeans.cnd.api.lexer.CppTokenId;
  49. import org.netbeans.modules.cnd.api.model.CsmClass;
  50. import org.netbeans.modules.cnd.api.model.CsmClassifier;
  51. import org.netbeans.modules.cnd.api.model.CsmFunction;
  52. import org.netbeans.modules.cnd.api.model.CsmFunctionDefinition;
  53. import org.netbeans.modules.cnd.api.model.CsmInheritance;
  54. import org.netbeans.modules.cnd.api.model.CsmInstantiation;
  55. import org.netbeans.modules.cnd.api.model.CsmMember;
  56. import org.netbeans.modules.cnd.api.model.CsmObject;
  57. import org.netbeans.modules.cnd.api.model.CsmScope;
  58. import org.netbeans.modules.cnd.api.model.CsmScopeElement;
  59. import org.netbeans.modules.cnd.api.model.CsmSpecializationParameter;
  60. import org.netbeans.modules.cnd.api.model.CsmTemplateParameter;
  61. import org.netbeans.modules.cnd.api.model.CsmType;
  62. import org.netbeans.modules.cnd.api.model.CsmTypeBasedSpecializationParameter;
  63. import org.netbeans.modules.cnd.api.model.CsmTypedef;
  64. import org.netbeans.modules.cnd.api.model.CsmVariable;
  65. import org.netbeans.modules.cnd.api.model.CsmVariableDefinition;
  66. import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
  67. import org.netbeans.modules.cnd.api.model.xref.CsmReference;
  68. import org.netbeans.modules.cnd.api.model.xref.CsmReferenceKind;
  69. import org.netbeans.modules.cnd.api.model.xref.CsmTemplateBasedReferencedObject;
  70. import org.netbeans.modules.cnd.modelutil.AntiLoop;
  71. import org.netbeans.modules.cnd.utils.CndUtils;
  72. import org.openide.util.Lookup;
  73. /**
  74. * Provides a list of CsmReferences of the identifiers in the CsmFile
  75. *
  76. * @author Sergey Grinev
  77. */
  78. public abstract class CsmFileReferences {
  79. /**
  80. * Provides visiting of the identifiers of the CsmFile
  81. */
  82. public abstract void accept(CsmScope csmScope, Visitor visitor);
  83. /**
  84. * Provides visiting of the identifiers of the CsmFile and point prefered
  85. * kinds of references
  86. */
  87. public abstract void accept(CsmScope csmScope, Visitor visitor, Set<CsmReferenceKind> preferedKinds);
  88. public abstract void visit(Collection<CsmReference> refs, ReferenceVisitor visitor);
  89. /**
  90. * A dummy resolver that do nothing.
  91. */
  92. private static final CsmFileReferences EMPTY = new Empty();
  93. /** default instance */
  94. private static CsmFileReferences DEFAULT;
  95. protected CsmFileReferences() {
  96. }
  97. /** Static method to obtain the CsmFileReferences implementation.
  98. * @return the resolver
  99. */
  100. public static CsmFileReferences getDefault() {
  101. /*no need for sync synchronized access*/
  102. if (DEFAULT != null) {
  103. return DEFAULT;
  104. }
  105. DEFAULT = Lookup.getDefault().lookup(CsmFileReferences.class);
  106. return DEFAULT == null ? EMPTY : DEFAULT;
  107. }
  108. //
  109. // Implementation of the default query
  110. //
  111. private static final class Empty extends CsmFileReferences {
  112. Empty() {
  113. }
  114. @Override
  115. public void accept(CsmScope csmScope, Visitor visitor) {
  116. // do nothing
  117. }
  118. @Override
  119. public void accept(CsmScope csmScope, Visitor visitor, Set<CsmReferenceKind> kinds) {
  120. // do nothing
  121. }
  122. @Override
  123. public void visit(Collection<CsmReference> refs, ReferenceVisitor visitor) {
  124. // do nothing
  125. }
  126. }
  127. /**
  128. * visitor inteface
  129. */
  130. public interface Visitor {
  131. /**
  132. * This method is invoked for every matching reference in the file.
  133. *
  134. * @param context reference with its lexical context
  135. */
  136. void visit(CsmReferenceContext context);
  137. }
  138. public interface ReferenceVisitor {
  139. /**
  140. * This method is invoked for every matching reference in the file.
  141. *
  142. * @param context reference with its lexical context
  143. */
  144. void visit(CsmReference ref);
  145. }
  146. /**
  147. * Determines whether reference is dereferenced template parameter
  148. */
  149. public static boolean isTemplateBased(CsmReferenceContext context) {
  150. if (2 <= context.size() && isDereference(context.getToken())) {
  151. CsmReference ref = context.getReference(context.size() - 2);
  152. if (ref != null) {
  153. if (getDefault().isThis(ref)) {
  154. return hasTemplateBasedAncestors(findContextClass(context), new AntiLoop());
  155. }
  156. CsmObject refObj = ref.getReferencedObject();
  157. if (isTemplateParameterInvolved(refObj)) {
  158. return true;
  159. } else {
  160. return hasTemplateBasedAncestors(getType(refObj), new AntiLoop());
  161. }
  162. }
  163. } else {
  164. // it isn't a dereference - check current context
  165. return hasTemplateBasedAncestors(findContextClass(context), new AntiLoop());
  166. }
  167. return false;
  168. }
  169. private static CsmType getType(CsmObject obj) {
  170. if (CsmKindUtilities.isFunction(obj)) {
  171. return ((CsmFunction)obj).getReturnType();
  172. } else if (CsmKindUtilities.isVariable(obj)) {
  173. return ((CsmVariable)obj).getType();
  174. } else if(CsmKindUtilities.isTypedef(obj)) {
  175. return ((CsmTypedef) obj).getType();
  176. }
  177. return null;
  178. }
  179. private static CsmClass findContextClass(CsmReferenceContext context) {
  180. CsmObject owner = context.getReference().getOwner();
  181. while (CsmKindUtilities.isScopeElement(owner)) {
  182. if (CsmKindUtilities.isClass(owner)) {
  183. return (CsmClass) owner;
  184. } else if (CsmKindUtilities.isClassMember(owner)) {
  185. return ((CsmMember) owner).getContainingClass();
  186. } else if (CsmKindUtilities.isFunctionDefinition(owner)) {
  187. CsmFunction decl = ((CsmFunctionDefinition) owner).getDeclaration();
  188. if (CsmKindUtilities.isClassMember(decl)) {
  189. return ((CsmMember) decl).getContainingClass();
  190. }
  191. } else if (CsmKindUtilities.isVariableDefinition(owner)) {
  192. CsmVariable decl = ((CsmVariableDefinition) owner).getDeclaration();
  193. if (CsmKindUtilities.isClassMember(decl)) {
  194. return ((CsmMember) decl).getContainingClass();
  195. }
  196. }
  197. owner = ((CsmScopeElement) owner).getScope();
  198. }
  199. return null;
  200. }
  201. public static boolean hasTemplateBasedAncestors(CsmType type) {
  202. return hasTemplateBasedAncestors(type, new AntiLoop());
  203. }
  204. private static boolean hasTemplateBasedAncestors(CsmType type, AntiLoop handledClasses) {
  205. if( type != null) {
  206. CsmClassifier cls = type.getClassifier();
  207. if (CsmKindUtilities.isClass(cls)) {
  208. return hasTemplateBasedAncestors((CsmClass) cls, handledClasses);
  209. }
  210. }
  211. return false;
  212. }
  213. private static boolean hasTemplateBasedAncestors(CsmClass cls, AntiLoop handledClasses) {
  214. if (cls != null) {
  215. if (handledClasses.contains(cls)) {
  216. return false;
  217. }
  218. handledClasses.add(cls);
  219. if (isActualInstantiation(cls)) {
  220. return false; // like my_class<int, char>
  221. }
  222. for (CsmInheritance inh : cls.getBaseClasses()) {
  223. if (inh.getAncestorType().isTemplateBased()) {
  224. return true;
  225. }
  226. CsmClassifier classifier = inh.getClassifier();
  227. if (classifier instanceof CsmClass) { // paranoia
  228. if (hasTemplateBasedAncestors((CsmClass) classifier, handledClasses)) {
  229. return true;
  230. }
  231. }
  232. }
  233. }
  234. return false;
  235. }
  236. /**
  237. * Determines whether it is indeed instantiation -
  238. * not a specialization, not a part of the template itself, etc.
  239. * @return true
  240. */
  241. private static boolean isActualInstantiation(CsmClass cls) {
  242. if (CsmKindUtilities.isInstantiation(cls)) {
  243. CsmInstantiation instantiation = (CsmInstantiation) cls;
  244. Map<CsmTemplateParameter, CsmSpecializationParameter> mapping = instantiation.getMapping();
  245. for (CsmSpecializationParameter param : mapping.values()) {
  246. if (CsmKindUtilities.isTypeBasedSpecalizationParameter(param)) {
  247. if (((CsmTypeBasedSpecializationParameter) param).isTemplateBased()) {
  248. return false;
  249. }
  250. }
  251. }
  252. return true;
  253. }
  254. return false;
  255. }
  256. /**
  257. * Determines whether reference is dereferenced macro or
  258. * if it's in macro arguments
  259. */
  260. public static boolean isMacroBased(CsmReferenceContext context) {
  261. if (2 <= context.size() && isDereference(context.getToken())) {
  262. CsmReference ref = context.getReference(context.size() - 2);
  263. if (ref != null) {
  264. if (CsmKindUtilities.isMacro(ref.getReferencedObject())) {
  265. return true;
  266. }
  267. }
  268. }
  269. for (int i = context.size() - 1; 0 < i; --i) {
  270. if (context.getToken(i) == CppTokenId.LPAREN) {
  271. CsmReference ref = context.getReference(i - 1);
  272. if (ref != null && CsmKindUtilities.isMacro(ref.getReferencedObject())) {
  273. return true;
  274. }
  275. }
  276. }
  277. return false;
  278. }
  279. public static boolean isBuiltInBased(CsmReference ref) {
  280. CharSequence txt = null;
  281. if (ref != null) {
  282. txt = ref.getText();
  283. }
  284. if (txt != null && txt.length() > 0) {
  285. String strTxt = txt.toString();
  286. if (strTxt.equals("__func__")) { // NOI18N
  287. return true;
  288. } else if (strTxt.startsWith("__builtin_")) { // NOI18N
  289. return true;
  290. }
  291. }
  292. return false;
  293. }
  294. public static boolean isAfterUnresolved(CsmReferenceContext context) {
  295. if (2 <= context.size() && isDereference(context.getToken())) {
  296. CsmReference ref = context.getReference(context.size() - 2);
  297. if (ref != null && !getDefault().isThis(ref)) {
  298. final CsmObject referencedObject = ref.getReferencedObject();
  299. if (referencedObject == null ||
  300. referencedObject instanceof CsmTemplateBasedReferencedObject) {
  301. return true;
  302. }
  303. }
  304. }
  305. return false;
  306. }
  307. public static boolean isTemplateParameterInvolved(CsmObject obj) {
  308. if (CsmKindUtilities.isTemplateParameter(obj)) {
  309. return true;
  310. }
  311. CsmType type = getType(obj);
  312. return (type == null) ? false : type.isTemplateBased();
  313. }
  314. public static boolean isDereference(CppTokenId token) {
  315. if (token == null) {
  316. return false;
  317. }
  318. switch (token) {
  319. case DOT:
  320. case DOTMBR:
  321. case ARROW:
  322. case ARROWMBR:
  323. case SCOPE:
  324. return true;
  325. default:
  326. return false;
  327. }
  328. }
  329. public static boolean isBracket(CppTokenId token) {
  330. if (token == null) {
  331. return false;
  332. }
  333. switch (token) {
  334. case LBRACE:
  335. case LBRACKET:
  336. case LPAREN:
  337. case LT:
  338. return true;
  339. default:
  340. return false;
  341. }
  342. }
  343. protected boolean isThis(CsmReference ref) {
  344. return ref != null && "this".equals(ref.getText()); //NOI18N
  345. }
  346. }