PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/content/project/ClassifierContainer.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 413 lines | 315 code | 29 blank | 69 comment | 68 complexity | d6050d22eb63dba79a9125e2dbf3f00e 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.modelimpl.content.project;
  45. import java.io.IOException;
  46. import java.util.ArrayList;
  47. import java.util.Collection;
  48. import java.util.Collections;
  49. import java.util.HashMap;
  50. import java.util.HashSet;
  51. import java.util.Map;
  52. import java.util.Set;
  53. import java.util.TreeMap;
  54. import java.util.concurrent.locks.ReadWriteLock;
  55. import java.util.concurrent.locks.ReentrantReadWriteLock;
  56. import org.netbeans.modules.cnd.api.model.CsmClass;
  57. import org.netbeans.modules.cnd.api.model.CsmClassifier;
  58. import org.netbeans.modules.cnd.api.model.CsmDeclaration;
  59. import org.netbeans.modules.cnd.api.model.CsmDeclaration.Kind;
  60. import org.netbeans.modules.cnd.api.model.CsmInheritance;
  61. import org.netbeans.modules.cnd.api.model.CsmNamespace;
  62. import org.netbeans.modules.cnd.api.model.CsmScope;
  63. import org.netbeans.modules.cnd.api.model.CsmUID;
  64. import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
  65. import org.netbeans.modules.cnd.api.model.util.UIDs;
  66. import org.netbeans.modules.cnd.modelimpl.csm.TypeImpl;
  67. import org.netbeans.modules.cnd.modelimpl.csm.core.OffsetableDeclarationBase;
  68. import org.netbeans.modules.cnd.modelimpl.csm.core.ProjectBase;
  69. import org.netbeans.modules.cnd.modelimpl.repository.ClassifierContainerKey;
  70. import org.netbeans.modules.cnd.modelimpl.textcache.NameCache;
  71. import org.netbeans.modules.cnd.modelimpl.textcache.QualifiedNameCache;
  72. import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
  73. import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
  74. import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities;
  75. import org.netbeans.modules.cnd.repository.spi.Persistent;
  76. import org.netbeans.modules.cnd.repository.spi.RepositoryDataInput;
  77. import org.netbeans.modules.cnd.repository.spi.RepositoryDataOutput;
  78. import org.netbeans.modules.cnd.repository.support.SelfPersistent;
  79. import org.netbeans.modules.cnd.utils.cache.CharSequenceUtils;
  80. import org.openide.util.CharSequences;
  81. /**
  82. * Storage for project classifiers. Class was extracted from ProjectBase.
  83. * @author Alexander Simon
  84. */
  85. public class ClassifierContainer extends ProjectComponent implements Persistent, SelfPersistent {
  86. private final Map<CharSequence, CsmUID<CsmClassifier>> classifiers;
  87. // storage for classifiers defined as inner classfiers in C structures
  88. private final Map<CharSequence, CsmUID<CsmClassifier>> shortClassifiers;
  89. private final Map<CharSequence, CsmUID<CsmClassifier>> typedefs;
  90. private final Map<CharSequence, Set<CsmUID<CsmInheritance>>> inheritances;
  91. private final ReadWriteLock declarationsLock = new ReentrantReadWriteLock();
  92. // empty stub
  93. private static final ClassifierContainer EMPTY = new ClassifierContainer() {
  94. @Override
  95. public boolean putClassifier(CsmClassifier decl) {
  96. return false;
  97. }
  98. @Override
  99. public void put() {
  100. }
  101. };
  102. public static ClassifierContainer empty() {
  103. return EMPTY;
  104. }
  105. /** Creates a new instance of ClassifierContainer */
  106. public ClassifierContainer(ProjectBase project) {
  107. super(new ClassifierContainerKey(project.getUnitId()));
  108. classifiers = new HashMap<CharSequence, CsmUID<CsmClassifier>>();
  109. shortClassifiers = new HashMap<CharSequence, CsmUID<CsmClassifier>>();
  110. typedefs = new HashMap<CharSequence, CsmUID<CsmClassifier>>();
  111. inheritances = new HashMap<CharSequence, Set<CsmUID<CsmInheritance>>>();
  112. put();
  113. }
  114. public ClassifierContainer(RepositoryDataInput input) throws IOException {
  115. super(input);
  116. int collSize = input.readInt();
  117. classifiers = new HashMap<CharSequence, CsmUID<CsmClassifier>>(collSize);
  118. UIDObjectFactory.getDefaultFactory().readStringToUIDMap(this.classifiers, input, QualifiedNameCache.getManager(), collSize);
  119. collSize = input.readInt();
  120. shortClassifiers = new HashMap<CharSequence, CsmUID<CsmClassifier>>(collSize);
  121. UIDObjectFactory.getDefaultFactory().readStringToUIDMap(this.shortClassifiers, input, QualifiedNameCache.getManager(), collSize);
  122. collSize = input.readInt();
  123. typedefs = new HashMap<CharSequence, CsmUID<CsmClassifier>>(collSize);
  124. UIDObjectFactory.getDefaultFactory().readStringToUIDMap(this.typedefs, input, QualifiedNameCache.getManager(), collSize);
  125. collSize = input.readInt();
  126. inheritances = new HashMap<CharSequence, Set<CsmUID<CsmInheritance>>>();
  127. UIDObjectFactory.getDefaultFactory().readStringToUIDMapSet(this.inheritances, input, NameCache.getManager(), collSize);
  128. }
  129. // only for EMPTY static field
  130. private ClassifierContainer() {
  131. super((org.netbeans.modules.cnd.repository.spi.Key) null);
  132. classifiers = new HashMap<CharSequence, CsmUID<CsmClassifier>>();
  133. shortClassifiers = new HashMap<CharSequence, CsmUID<CsmClassifier>>();
  134. typedefs = new HashMap<CharSequence, CsmUID<CsmClassifier>>();
  135. inheritances = new HashMap<CharSequence, Set<CsmUID<CsmInheritance>>>();
  136. }
  137. public CsmClassifier getClassifier(CharSequence qualifiedName) {
  138. CsmClassifier result;
  139. CsmUID<CsmClassifier> uid;
  140. qualifiedName = CharSequences.create(qualifiedName);
  141. try {
  142. declarationsLock.readLock().lock();
  143. uid = classifiers.get(qualifiedName);
  144. if (uid == null) {
  145. uid = shortClassifiers.get(qualifiedName);
  146. }
  147. if (uid == null) {
  148. uid = typedefs.get(qualifiedName);
  149. }
  150. } finally {
  151. declarationsLock.readLock().unlock();
  152. }
  153. result = UIDCsmConverter.UIDtoDeclaration(uid);
  154. return result;
  155. }
  156. public Collection<CsmInheritance> getInheritances(CharSequence name){
  157. Collection<CsmUID<CsmInheritance>> inh;
  158. name = CharSequences.create(name);
  159. try {
  160. declarationsLock.readLock().lock();
  161. inh = inheritances.get(name);
  162. if (inh != null) {
  163. inh = new ArrayList<CsmUID<CsmInheritance>>(inh);
  164. } else {
  165. return Collections.<CsmInheritance>emptyList();
  166. }
  167. } finally {
  168. declarationsLock.readLock().unlock();
  169. }
  170. return UIDCsmConverter.<CsmInheritance>UIDsToInheritances(inh);
  171. }
  172. // for unit teast
  173. public Map<CharSequence, CsmClassifier> getTestClassifiers(){
  174. return convertTestMap(classifiers);
  175. }
  176. // for unit teast
  177. public Map<CharSequence, CsmClassifier> getTestShortClassifiers() {
  178. return convertTestMap(shortClassifiers);
  179. }
  180. // for unit teast
  181. public Map<CharSequence, CsmClassifier> getTestTypedefs(){
  182. return convertTestMap(typedefs);
  183. }
  184. private Map<CharSequence, CsmClassifier> convertTestMap(Map<CharSequence, CsmUID<CsmClassifier>> map) {
  185. Map<CharSequence, CsmClassifier> res = new TreeMap<CharSequence, CsmClassifier>();
  186. try {
  187. declarationsLock.readLock().lock();
  188. for (Map.Entry<CharSequence, CsmUID<CsmClassifier>> entry : map.entrySet()) {
  189. res.put(entry.getKey(), UIDCsmConverter.UIDtoDeclaration(entry.getValue()));
  190. }
  191. } finally {
  192. declarationsLock.readLock().unlock();
  193. }
  194. return res;
  195. }
  196. public boolean putClassifier(CsmClassifier decl) {
  197. boolean changed;
  198. CsmUID<CsmClassifier> uid = UIDCsmConverter.declarationToUID(decl);
  199. Map<CharSequence, CsmUID<CsmClassifier>> map;
  200. Map<CharSequence, CsmUID<CsmClassifier>> shortNamesMap;
  201. if (isTypedef(decl)) {
  202. map = typedefs;
  203. shortNamesMap = null;
  204. } else {
  205. map = classifiers;
  206. shortNamesMap = shortClassifiers;
  207. if (CsmKindUtilities.isClass(decl)) {
  208. CsmClass cls = (CsmClass) decl;
  209. Collection<CsmInheritance> base = cls.getBaseClasses();
  210. if (!base.isEmpty()) {
  211. try {
  212. declarationsLock.writeLock().lock();
  213. for(CsmInheritance inh : base) {
  214. CharSequence id = inheritanceName(inh);
  215. Set<CsmUID<CsmInheritance>> set = inheritances.get(id);
  216. if (set == null) {
  217. set = new HashSet<CsmUID<CsmInheritance>>();
  218. inheritances.put(id, set);
  219. }
  220. set.add(UIDCsmConverter.inheritanceToUID(inh));
  221. }
  222. } finally {
  223. declarationsLock.writeLock().unlock();
  224. }
  225. }
  226. }
  227. }
  228. CharSequence qn = decl.getQualifiedName();
  229. changed = putClassifier(map, qn, uid);
  230. // Special case for nested structs in C
  231. if (shortNamesMap != null) {
  232. // See Bug 144535 - wrong error highlighting for inner structure
  233. CharSequence qn2 = getQualifiedNameWithoutScopeStructNameForC(decl);
  234. if (qn2 != null && qn.length() != qn2.length()) {
  235. // TODO: think about multiple objects per name in classifier as well
  236. changed |= putClassifier(shortNamesMap, qn2, uid);
  237. }
  238. }
  239. if (changed) {
  240. put();
  241. }
  242. return changed;
  243. }
  244. private CharSequence inheritanceName(CsmInheritance inh) {
  245. CharSequence id;
  246. if (inh instanceof TypeImpl) {
  247. id = ((TypeImpl) inh.getAncestorType()).getOwnText();
  248. } else {
  249. id = inh.getAncestorType().getClassifierText();
  250. }
  251. int i = CharSequenceUtils.lastIndexOf(id, "::"); //NOI18N
  252. if (i >= 0) {
  253. id = id.subSequence(i+2, id.length());
  254. }
  255. return NameCache.getManager().getString(id);
  256. }
  257. private boolean putClassifier(Map<CharSequence, CsmUID<CsmClassifier>> map, CharSequence qn, CsmUID<CsmClassifier> uid) {
  258. boolean changed = false;
  259. try {
  260. declarationsLock.writeLock().lock();
  261. CsmUID<CsmClassifier> old = map.get(qn);
  262. if (old == null || (!UIDUtilities.isForwardClass(uid) && UIDUtilities.isForwardClass(old))) {
  263. assert uid != null;
  264. map.put(qn, uid);
  265. assert (UIDCsmConverter.UIDtoDeclaration(uid) != null);
  266. changed = true;
  267. }
  268. } finally {
  269. declarationsLock.writeLock().unlock();
  270. }
  271. return changed;
  272. }
  273. public void removeClassifier(CsmDeclaration decl) {
  274. Map<CharSequence, CsmUID<CsmClassifier>> map;
  275. Map<CharSequence, CsmUID<CsmClassifier>> shortNamesMap;
  276. CsmUID<?> uid = UIDs.get(decl);
  277. if (isTypedef(decl)) {
  278. map = typedefs;
  279. shortNamesMap = null;
  280. } else {
  281. map = classifiers;
  282. shortNamesMap = shortClassifiers;
  283. if (CsmKindUtilities.isClass(decl)) {
  284. CsmClass cls = (CsmClass) decl;
  285. Collection<CsmInheritance> base = cls.getBaseClasses();
  286. if (!base.isEmpty()) {
  287. try {
  288. declarationsLock.writeLock().lock();
  289. for(CsmInheritance inh : base) {
  290. CharSequence id = inheritanceName(inh);
  291. Set<CsmUID<CsmInheritance>> set = inheritances.get(id);
  292. if (set != null) {
  293. set.remove(UIDCsmConverter.inheritanceToUID(inh));
  294. }
  295. }
  296. } finally {
  297. declarationsLock.writeLock().unlock();
  298. }
  299. }
  300. }
  301. }
  302. CharSequence qn = decl.getQualifiedName();
  303. boolean changed = removeClassifier(map, qn, uid);
  304. // Special case for nested structs in C
  305. if (shortNamesMap != null) {
  306. // See Bug 144535 - wrong error highlighting for inner structure
  307. CharSequence qn2 = getQualifiedNameWithoutScopeStructNameForC(decl);
  308. if (qn2 != null && qn.length() != qn2.length()) {
  309. // TODO: think about multiple objects per name in classifier as well
  310. changed |= removeClassifier(shortNamesMap, qn2, uid);
  311. }
  312. }
  313. if (changed) {
  314. put();
  315. }
  316. }
  317. private boolean removeClassifier(Map<CharSequence, CsmUID<CsmClassifier>> map, CharSequence qn, CsmUID<?> uid) {
  318. CsmUID<CsmClassifier> removed;
  319. try {
  320. declarationsLock.writeLock().lock();
  321. removed = map.get(qn);
  322. if (removed != null && removed.equals(uid)) {
  323. map.remove(qn);
  324. } else {
  325. removed = null;
  326. }
  327. } finally {
  328. declarationsLock.writeLock().unlock();
  329. }
  330. assert (removed == null) || (UIDCsmConverter.UIDtoCsmObject(removed) != null) : " no object for UID " + removed;
  331. return removed != null;
  332. }
  333. //public void clearClassifiers() {
  334. // classifiers.clear();
  335. // typedefs.clear();
  336. //}
  337. private CharSequence getQualifiedNameWithoutScopeStructNameForC(CsmDeclaration decl) {
  338. // #192897 - unstable LiteSQL accuracy test
  339. // skip not C env
  340. Kind kind = decl.getKind();
  341. if ((kind != CsmDeclaration.Kind.STRUCT && kind != CsmDeclaration.Kind.UNION) || CsmKindUtilities.isTemplate(decl)) {
  342. // not valid in C env
  343. return null;
  344. }
  345. CharSequence qualifiedNamePostfix;
  346. if(decl instanceof OffsetableDeclarationBase) {
  347. qualifiedNamePostfix = ((OffsetableDeclarationBase)decl).getQualifiedNamePostfix();
  348. } else {
  349. qualifiedNamePostfix = decl.getName();
  350. }
  351. CsmScope scope = decl.getScope();
  352. while (CsmKindUtilities.isClass(scope)) {
  353. CsmClass cls = (CsmClass) scope;
  354. kind = cls.getKind();
  355. if ((kind != CsmDeclaration.Kind.STRUCT && kind != CsmDeclaration.Kind.UNION) || CsmKindUtilities.isTemplate(decl)) {
  356. // not valid in C env
  357. return null;
  358. }
  359. scope = cls.getScope();
  360. }
  361. if (CsmKindUtilities.isNamespace(scope) && !((CsmNamespace)scope).isGlobal()) {
  362. // not valid in C env
  363. return null;
  364. }
  365. CharSequence qualifiedName = QualifiedNameCache.getManager().getString(qualifiedNamePostfix);
  366. return qualifiedName;
  367. }
  368. private boolean isTypedef(CsmDeclaration decl){
  369. return CsmKindUtilities.isTypedef(decl);
  370. }
  371. @Override
  372. public void write(RepositoryDataOutput output) throws IOException {
  373. super.write(output);
  374. try {
  375. declarationsLock.readLock().lock();
  376. UIDObjectFactory.getDefaultFactory().writeStringToUIDMap(this.classifiers, output, false);
  377. UIDObjectFactory.getDefaultFactory().writeStringToUIDMap(this.shortClassifiers, output, false);
  378. UIDObjectFactory.getDefaultFactory().writeStringToUIDMap(this.typedefs, output, false);
  379. UIDObjectFactory.getDefaultFactory().writeStringToUIDMapSet(this.inheritances, output);
  380. } finally {
  381. declarationsLock.readLock().unlock();
  382. }
  383. }
  384. }