0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.cnd.modelimpl.csm.core;
0043:
0044: import java.io.DataInput;
0045: import java.io.DataOutput;
0046: import java.io.File;
0047: import java.io.IOException;
0048: import java.util.*;
0049: import java.util.concurrent.ConcurrentHashMap;
0050: import java.util.concurrent.locks.ReadWriteLock;
0051: import java.util.concurrent.locks.ReentrantReadWriteLock;
0052:
0053: import org.netbeans.modules.cnd.api.model.*;
0054: import org.netbeans.modules.cnd.api.model.util.CsmTracer;
0055: import org.netbeans.modules.cnd.api.project.NativeFileItem;
0056: import org.netbeans.modules.cnd.api.project.NativeFileItem.Language;
0057: import org.netbeans.modules.cnd.api.project.NativeProject;
0058: import org.netbeans.modules.cnd.api.project.NativeProjectItemsListener;
0059: import org.netbeans.modules.cnd.apt.debug.DebugUtils;
0060: import org.netbeans.modules.cnd.apt.support.StartEntry;
0061: import org.netbeans.modules.cnd.apt.support.APTHandlersSupport;
0062: import org.netbeans.modules.cnd.apt.support.APTSystemStorage;
0063: import org.netbeans.modules.cnd.apt.structure.APTFile;
0064: import org.netbeans.modules.cnd.apt.support.APTDriver;
0065: import org.netbeans.modules.cnd.apt.support.APTIncludeHandler;
0066: import org.netbeans.modules.cnd.apt.support.APTMacroMap;
0067: import org.netbeans.modules.cnd.apt.support.APTPreprocHandler;
0068: import org.netbeans.modules.cnd.apt.support.APTWalker;
0069: import org.netbeans.modules.cnd.modelimpl.cache.CacheManager;
0070: import org.netbeans.modules.cnd.modelimpl.debug.Terminator;
0071: import org.netbeans.modules.cnd.modelimpl.debug.Diagnostic;
0072: import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
0073:
0074: import org.netbeans.modules.cnd.modelimpl.platform.*;
0075: import org.netbeans.modules.cnd.modelimpl.csm.*;
0076: import org.netbeans.modules.cnd.modelimpl.debug.DiagnosticExceptoins;
0077: import org.netbeans.modules.cnd.modelimpl.parser.apt.APTParseFileWalker;
0078: import org.netbeans.modules.cnd.modelimpl.parser.apt.APTRestorePreprocStateWalker;
0079: import org.netbeans.modules.cnd.modelimpl.repository.KeyUtilities;
0080: import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
0081: import org.netbeans.modules.cnd.modelimpl.textcache.ProjectNameCache;
0082: import org.netbeans.modules.cnd.modelimpl.textcache.QualifiedNameCache;
0083: import org.netbeans.modules.cnd.modelimpl.repository.RepositoryUtils;
0084: import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
0085: import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
0086: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities;
0087: import org.netbeans.modules.cnd.repository.spi.Key;
0088: import org.netbeans.modules.cnd.repository.spi.Persistent;
0089: import org.netbeans.modules.cnd.repository.support.SelfPersistent;
0090: import org.netbeans.modules.cnd.utils.cache.CharSequenceKey;
0091: import org.openide.util.Cancellable;
0092:
0093: /**
0094: * Base class for CsmProject implementation
0095: * @author Dmitry Ivanov
0096: * @author Vladimir Kvashin
0097: */
0098: public abstract class ProjectBase implements CsmProject, Persistent,
0099: SelfPersistent {
0100:
0101: private transient boolean needParseOrphan;
0102:
0103: /** Creates a new instance of CsmProjectImpl */
0104: protected ProjectBase(ModelImpl model, Object platformProject,
0105: String name) {
0106: setStatus(Status.Initial);
0107: this .name = ProjectNameCache.getManager().getString(name);
0108: init(model, platformProject);
0109: NamespaceImpl ns = new NamespaceImpl(this );
0110: assert ns != null;
0111: this .globalNamespaceUID = UIDCsmConverter.namespaceToUID(ns);
0112: declarationsSorageKey = new DeclarationContainer(this ).getKey();
0113: fileContainerKey = new FileContainer(this ).getKey();
0114: graphStorageKey = new GraphContainer(this ).getKey();
0115: }
0116:
0117: private void init(ModelImpl model, Object platformProject) {
0118: this .model = model;
0119: this .platformProject = platformProject;
0120: // remember in repository
0121: RepositoryUtils.hang(this );
0122: // create global namespace
0123:
0124: if (TraceFlags.CLOSE_AFTER_PARSE) {
0125: Terminator.create(this );
0126: }
0127: needParseOrphan = ModelSupport.needParseOrphan(platformProject);
0128: }
0129:
0130: private void setStatus(Status newStatus) {
0131: //System.err.printf("CHANGING STATUS %s -> %s for %s (%s)\n", status, newStatus, name, getClass().getName());
0132: status = newStatus;
0133: }
0134:
0135: protected static void cleanRepository(Object platformProject,
0136: boolean articicial) {
0137: Key key = KeyUtilities.createProjectKey(getUniqueName(
0138: platformProject).toString());
0139: RepositoryUtils.closeUnit(key, null, true);
0140: }
0141:
0142: public static ProjectBase readInstance(ModelImpl model,
0143: Object platformProject, String name) {
0144:
0145: long time = 0;
0146: if (TraceFlags.TIMING) {
0147: System.err.printf("Project %s: instantiating...\n", name);
0148: time = System.currentTimeMillis();
0149: }
0150:
0151: assert TraceFlags.PERSISTENT_REPOSITORY;
0152: Key key = KeyUtilities.createProjectKey(getUniqueName(
0153: platformProject).toString());
0154: RepositoryUtils.openUnit(key);
0155: Persistent o = RepositoryUtils.get(key);
0156: if (o != null) {
0157: assert o instanceof ProjectBase;
0158: ProjectBase impl = (ProjectBase) o;
0159: if (!impl.name.equals(name)) {
0160: impl.setName(name);
0161: }
0162: impl.init(model, platformProject);
0163: if (TraceFlags.TIMING) {
0164: time = System.currentTimeMillis() - time;
0165: System.err.printf("Project %s: loaded. %d ms\n", name,
0166: time);
0167: }
0168:
0169: return impl;
0170: }
0171: return null;
0172: }
0173:
0174: public CsmNamespace getGlobalNamespace() {
0175: return _getGlobalNamespace();
0176: }
0177:
0178: public CharSequence getName() {
0179: return name;
0180: }
0181:
0182: protected void setName(String name) {
0183: this .name = name;
0184: }
0185:
0186: /**
0187: * Returns a string that uniquely identifies this project.
0188: * One should never rely on this name structure,
0189: * just use it as in unique identifier
0190: */
0191: public CharSequence getUniqueName() {
0192: if (this .uniqueName == null) {
0193: this .uniqueName = getUniqueName(getPlatformProject());
0194: }
0195: return this .uniqueName;
0196: }
0197:
0198: public static CharSequence getUniqueName(Object platformProject) {
0199: String result;
0200: if (platformProject instanceof NativeProject) {
0201: result = ((NativeProject) platformProject).getProjectRoot() + 'N';
0202: } else if (platformProject instanceof String) {
0203: result = (String) platformProject + 'L';
0204: } else if (platformProject == null) {
0205: throw new IllegalArgumentException(
0206: "Incorrect platform project: null"); // NOI18N
0207: } else {
0208: throw new IllegalArgumentException(
0209: "Incorrect platform project class: "
0210: + platformProject.getClass()); // NOI18N
0211: }
0212: return ProjectNameCache.getManager().getString(result);
0213: }
0214:
0215: /** Gets an object, which represents correspondent IDE project */
0216: public Object getPlatformProject() {
0217: return platformProject;
0218: }
0219:
0220: /** Gets an object, which represents correspondent IDE project */
0221: protected void setPlatformProject(Object platformProject) {
0222: this .platformProject = platformProject;
0223: this .uniqueName = null;
0224: }
0225:
0226: /** Finds namespace by its qualified name */
0227: public CsmNamespace findNamespace(String qualifiedName,
0228: boolean findInLibraries) {
0229: CsmNamespace result = findNamespace(qualifiedName);
0230: if (result == null && findInLibraries) {
0231: for (Iterator it = getLibraries().iterator(); it.hasNext();) {
0232: CsmProject lib = (CsmProject) it.next();
0233: result = lib.findNamespace(qualifiedName);
0234: if (result != null) {
0235: break;
0236: }
0237: }
0238: }
0239: return result;
0240: }
0241:
0242: /** Finds namespace by its qualified name */
0243: public CsmNamespace findNamespace(CharSequence qualifiedName) {
0244: CsmNamespace nsp = _getNamespace(qualifiedName);
0245: return nsp;
0246: }
0247:
0248: public NamespaceImpl findNamespaceCreateIfNeeded(
0249: NamespaceImpl parent, CharSequence name) {
0250: String qualifiedName = Utils.getNestedNamespaceQualifiedName(
0251: name, parent, true);
0252: NamespaceImpl nsp = _getNamespace(qualifiedName);
0253: if (nsp == null) {
0254: synchronized (namespaceLock) {
0255: nsp = _getNamespace(qualifiedName);
0256: if (nsp == null) {
0257: nsp = new NamespaceImpl(this , parent, name
0258: .toString(), qualifiedName);
0259: }
0260: }
0261: }
0262: return nsp;
0263: }
0264:
0265: public void registerNamespace(NamespaceImpl namespace) {
0266: _registerNamespace(namespace);
0267: }
0268:
0269: public void unregisterNamesace(NamespaceImpl namespace) {
0270: _unregisterNamespace(namespace);
0271: }
0272:
0273: public CsmClassifier findClassifier(CharSequence qualifiedName,
0274: boolean findInLibraries) {
0275: CsmClassifier result = findClassifier(qualifiedName);
0276: if (result == null && findInLibraries) {
0277: for (Iterator it = getLibraries().iterator(); it.hasNext();) {
0278: CsmProject lib = (CsmProject) it.next();
0279: result = lib.findClassifier(qualifiedName);
0280: if (result != null) {
0281: break;
0282: }
0283: }
0284: }
0285: return result;
0286: }
0287:
0288: public CsmClassifier findClassifier(CharSequence qualifiedName) {
0289: CsmClassifier result = classifierContainer
0290: .getClassifier(qualifiedName);
0291: return result;
0292: }
0293:
0294: public CsmDeclaration findDeclaration(CharSequence uniqueName) {
0295: return getDeclarationsSorage().getDeclaration(uniqueName);
0296: }
0297:
0298: public Collection<CsmOffsetableDeclaration> findDeclarations(
0299: CharSequence uniqueName) {
0300: return getDeclarationsSorage().findDeclarations(uniqueName);
0301: }
0302:
0303: public Collection<CsmOffsetableDeclaration> findDeclarationsByPrefix(
0304: String prefix) {
0305: return getDeclarationsSorage().getDeclarationsRange(prefix,
0306: prefix + "z"); // NOI18N
0307: }
0308:
0309: public Collection<CsmFriend> findFriendDeclarations(
0310: CsmOffsetableDeclaration decl) {
0311: return getDeclarationsSorage().findFriends(decl);
0312: }
0313:
0314: public static boolean isCppFile(CsmFile file) {
0315: return (file instanceof FileImpl)
0316: && ((FileImpl) file).isCppFile();
0317: }
0318:
0319: // public void registerClassifier(ClassEnumBase ce) {
0320: // classifiers.put(ce.getNestedNamespaceQualifiedName(), ce);
0321: // registerDeclaration(ce);
0322: // }
0323:
0324: public static boolean canRegisterDeclaration(CsmDeclaration decl) {
0325: // WAS: don't put unnamed declarations
0326: assert decl != null;
0327: assert decl.getName() != null;
0328: if (decl.getName().length() == 0) {
0329: return false;
0330: }
0331: CsmScope scope = decl.getScope();
0332: if (scope instanceof CsmCompoundClassifier) {
0333: return canRegisterDeclaration((CsmCompoundClassifier) scope);
0334: }
0335: return true;
0336: }
0337:
0338: public void registerDeclaration(CsmOffsetableDeclaration decl) {
0339:
0340: if (!ProjectBase.canRegisterDeclaration(decl)) {
0341: if (TraceFlags.TRACE_REGISTRATION) {
0342: System.err.println("not registered decl " + decl
0343: + " UID " + decl.getUID()); //NOI18N
0344: }
0345:
0346: return;
0347: }
0348: if (TraceFlags.CHECK_DECLARATIONS) {
0349: CsmDeclaration old = getDeclarationsSorage()
0350: .getDeclaration(decl.getUniqueName());
0351: if (old != null && old != decl) {
0352: System.err
0353: .println("\n\nRegistering different declaration with the same name:"
0354: + decl.getUniqueName());
0355: System.err.print("WAS:");
0356: new CsmTracer().dumpModel(old);
0357: System.err.print("\nNOW:");
0358: new CsmTracer().dumpModel(decl);
0359: }
0360: }
0361: getDeclarationsSorage().putDeclaration(decl);
0362:
0363: if (decl instanceof CsmClassifier) {
0364: CharSequence qn = decl.getQualifiedName();
0365: if (!classifierContainer
0366: .putClassifier((CsmClassifier) decl)
0367: && TraceFlags.CHECK_DECLARATIONS) {
0368: CsmClassifier old = classifierContainer
0369: .getClassifier(qn);
0370: if (old != null && old != decl) {
0371: System.err
0372: .println("\n\nRegistering different classifier with the same name:"
0373: + qn);
0374: System.err.print("ALREADY EXISTS:");
0375: new CsmTracer().dumpModel(old);
0376: System.err.print("\nFAILED TO ADD:");
0377: new CsmTracer().dumpModel(decl);
0378: }
0379: }
0380: }
0381: if (TraceFlags.TRACE_REGISTRATION) {
0382: System.err.println("registered " + decl + " UID "
0383: + decl.getUID()); //NOI18N
0384: }
0385:
0386: }
0387:
0388: public void unregisterDeclaration(CsmDeclaration decl) {
0389: if (TraceFlags.TRACE_REGISTRATION) {
0390: System.err.println("unregistered " + decl + " UID "
0391: + decl.getUID()); //NOI18N
0392: }
0393: if (decl instanceof CsmClassifier) {
0394: classifierContainer.removeClassifier(decl);
0395: }
0396: getDeclarationsSorage().removeDeclaration(decl);
0397: }
0398:
0399: public void waitParse() {
0400: boolean insideParser = ParserThreadManager.instance()
0401: .isParserThread();
0402: if (insideParser) {
0403: new Throwable(
0404: "project.waitParse should NEVER be called in parser thread !!!")
0405: .printStackTrace(System.err); // NOI18N
0406: }
0407: if (insideParser) {
0408: return;
0409: }
0410: ensureFilesCreated();
0411: ensureChangedFilesEnqueued();
0412: waitParseImpl();
0413: }
0414:
0415: private void waitParseImpl() {
0416: synchronized (waitParseLock) {
0417: while (ParserQueue.instance().hasFiles(this , null)) {
0418: try {
0419: waitParseLock.wait();
0420: } catch (InterruptedException ex) {
0421: // do nothing
0422: }
0423: }
0424: }
0425: }
0426:
0427: protected void ensureChangedFilesEnqueued() {
0428: }
0429:
0430: /**
0431: * @param skipFile if null => check all files, otherwise skip checking
0432: * this file
0433: *
0434: */
0435: protected boolean hasChangedFiles(CsmFile skipFile) {
0436: return false;
0437: }
0438:
0439: public boolean acceptNativeItem(NativeFileItem item) {
0440: NativeFileItem.Language language = item.getLanguage();
0441: return (language == NativeFileItem.Language.C
0442: || language == NativeFileItem.Language.CPP || language == NativeFileItem.Language.C_HEADER)
0443: && !item.isExcluded();
0444: }
0445:
0446: protected synchronized void ensureFilesCreated() {
0447: if (status == Status.Initial || status == Status.Restored) {
0448: try {
0449: setStatus((status == Status.Initial) ? Status.AddingFiles
0450: : Status.Validating);
0451: long time = 0;
0452: if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
0453: System.err.println("suspend queue");
0454: ParserQueue.instance().suspend();
0455: if (TraceFlags.TIMING) {
0456: time = System.currentTimeMillis();
0457: }
0458: }
0459: ParserQueue.instance().onStartAddingProjectFiles(this );
0460: getModel().registerProjectListeners(this ,
0461: platformProject);
0462: NativeProject nativeProject = ModelSupport
0463: .getNativeProject(platformProject);
0464: if (nativeProject != null) {
0465: try {
0466: ParserQueue.instance().suspend();
0467: createProjectFilesIfNeed(nativeProject);
0468: } finally {
0469: ParserQueue.instance().resume();
0470: }
0471: }
0472: if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
0473: if (TraceFlags.TIMING) {
0474: time = System.currentTimeMillis() - time;
0475: System.err
0476: .println("getting files from project system + put in queue took "
0477: + time + "ms");
0478: }
0479: try {
0480: System.err.println("sleep for "
0481: + TraceFlags.SUSPEND_PARSE_TIME
0482: + "sec before resuming queue");
0483: Thread
0484: .sleep(TraceFlags.SUSPEND_PARSE_TIME * 1000);
0485: System.err.println("woke up after sleep");
0486: } catch (InterruptedException ex) {
0487: // do nothing
0488: }
0489: ParserQueue.instance().resume();
0490: }
0491: ParserQueue.instance().onEndAddingProjectFiles(this );
0492: } finally {
0493: setStatus(Status.Ready);
0494: }
0495: }
0496: }
0497:
0498: private void createProjectFilesIfNeed(NativeProject nativeProject) {
0499:
0500: if (TraceFlags.TIMING) {
0501: System.err
0502: .printf(
0503: "\n\nGetting files from project system for %s...\n",
0504: getName());
0505: }
0506: if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
0507: try {
0508: System.err.println("sleep for "
0509: + TraceFlags.SUSPEND_PARSE_TIME
0510: + "sec before getting files from project");
0511: Thread.sleep(TraceFlags.SUSPEND_PARSE_TIME * 1000);
0512: System.err.println("woke up after sleep");
0513: } catch (InterruptedException ex) {
0514: // do nothing
0515: }
0516: }
0517: long time = System.currentTimeMillis();
0518: final Set<NativeFileItem> removedFiles = Collections
0519: .synchronizedSet(new HashSet<NativeFileItem>());
0520: NativeProjectItemsListener projectItemListener = new NativeProjectItemsListener() {
0521: public void fileAdded(NativeFileItem fileItem) {
0522: }
0523:
0524: public void filesAdded(List<NativeFileItem> fileItems) {
0525: }
0526:
0527: public void fileRemoved(NativeFileItem fileItem) {
0528: removedFiles.add(fileItem);
0529: }
0530:
0531: public void filesRemoved(List<NativeFileItem> fileItems) {
0532: removedFiles.addAll(fileItems);
0533: }
0534:
0535: public void fileRenamed(String oldPath,
0536: NativeFileItem newFileIetm) {
0537: }
0538:
0539: public void filePropertiesChanged(NativeFileItem fileItem) {
0540: }
0541:
0542: public void filesPropertiesChanged(
0543: List<NativeFileItem> fileItems) {
0544: }
0545:
0546: public void filesPropertiesChanged() {
0547: }
0548:
0549: public void projectDeleted(NativeProject nativeProject) {
0550: }
0551: };
0552: nativeProject.addProjectItemsListener(projectItemListener);
0553: List<NativeFileItem> sources = new ArrayList<NativeFileItem>();
0554: List<NativeFileItem> headers = new ArrayList<NativeFileItem>();
0555: List<NativeFileItem> excluded = new ArrayList<NativeFileItem>();
0556: for (NativeFileItem item : nativeProject.getAllFiles()) {
0557: if (!item.isExcluded()) {
0558: switch (item.getLanguage()) {
0559: case C:
0560: case CPP:
0561: sources.add(item);
0562: break;
0563: case C_HEADER:
0564: headers.add(item);
0565: break;
0566: default:
0567: break;
0568: }
0569: } else {
0570: switch (item.getLanguage()) {
0571: case C:
0572: case CPP:
0573: case C_HEADER:
0574: excluded.add(item);
0575: break;
0576: default:
0577: break;
0578: }
0579: }
0580: }
0581:
0582: if (TraceFlags.TIMING) {
0583: time = System.currentTimeMillis() - time;
0584: System.err
0585: .printf(
0586: "Getting files from project system took %d ms for %s\n",
0587: time, getName());
0588: System.err
0589: .printf(
0590: "FILES COUNT for %s:\nSource files:\t%d\nHeader files:\t%d\nTotal files:\t%d\n",
0591: getName(), sources.size(), headers.size(),
0592: sources.size() + headers.size());
0593: time = System.currentTimeMillis();
0594: }
0595: if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
0596: try {
0597: System.err.println("sleep for "
0598: + TraceFlags.SUSPEND_PARSE_TIME
0599: + "sec after getting files from project");
0600: Thread.sleep(TraceFlags.SUSPEND_PARSE_TIME * 1000);
0601: System.err.println("woke up after sleep");
0602: } catch (InterruptedException ex) {
0603: // do nothing
0604: }
0605: }
0606: if (TraceFlags.DUMP_PROJECT_ON_OPEN) {
0607: ModelSupport.dumpNativeProject(nativeProject);
0608: }
0609:
0610: try {
0611: disposeLock.readLock().lock();
0612:
0613: if (TraceFlags.TIMING) {
0614: time = System.currentTimeMillis() - time;
0615: System.err.printf(
0616: "Waited on disposeLock: %d ms for %s\n", time,
0617: getName());
0618: time = System.currentTimeMillis();
0619: }
0620:
0621: if (disposing) {
0622: if (TraceFlags.TRACE_MODEL_STATE)
0623: System.err
0624: .printf(
0625: "filling parser queue interrupted for %s\n",
0626: getName());
0627: return;
0628: }
0629:
0630: ProjectSettingsValidator validator = null;
0631: if (status == Status.Validating) {
0632: validator = new ProjectSettingsValidator(this );
0633: validator.restoreSettings();
0634: }
0635: projectRoots.fixFolder(nativeProject.getProjectRoot());
0636: for (String root : nativeProject.getSourceRoots()) {
0637: projectRoots.fixFolder(root);
0638: }
0639: projectRoots.addSources(sources);
0640: projectRoots.addSources(headers);
0641: projectRoots.addSources(excluded);
0642: createProjectFilesIfNeed(sources, true, removedFiles,
0643: validator);
0644: createProjectFilesIfNeed(headers, false, removedFiles,
0645: validator);
0646:
0647: } finally {
0648: disposeLock.readLock().unlock();
0649: if (TraceFlags.TIMING) {
0650: time = System.currentTimeMillis() - time;
0651: System.err.printf(
0652: "FILLING PARSER QUEUE took %d ms for %s\n",
0653: time, getName());
0654: }
0655: }
0656: nativeProject.removeProjectItemsListener(projectItemListener);
0657: // in fact if visitor used for parsing => visitor will parse all included files
0658: // recursively starting from current source file
0659: // so, when we visit headers, they should not be reparsed if already were parsed
0660: }
0661:
0662: private void createProjectFilesIfNeed(List<NativeFileItem> items,
0663: boolean sources, Set<NativeFileItem> removedFiles,
0664: ProjectSettingsValidator validator) {
0665:
0666: for (NativeFileItem nativeFileItem : items) {
0667: if (disposing) {
0668: if (TraceFlags.TRACE_MODEL_STATE)
0669: System.err
0670: .printf(
0671: "filling parser queue interrupted for %s\n",
0672: getName());
0673: return;
0674: }
0675: if (removedFiles.contains(nativeFileItem)) {
0676: continue;
0677: }
0678: assert (nativeFileItem.getFile() != null) : "native file item must have valid File object";
0679: if (TraceFlags.DEBUG)
0680: ModelSupport.trace(nativeFileItem);
0681: try {
0682: createIfNeed(nativeFileItem, sources, validator);
0683: } catch (Exception ex) {
0684: DiagnosticExceptoins.register(ex);
0685: }
0686: }
0687: }
0688:
0689: /**
0690: * Creates FileImpl instance for the given file item if it hasn/t yet been created.
0691: * Is called when initializing the project or new file is added to project.
0692: * Isn't intended to be used in #included file processing.
0693: */
0694: protected void createIfNeed(NativeFileItem nativeFile,
0695: boolean isSourceFile, ProjectSettingsValidator validator) {
0696:
0697: assert (nativeFile != null && nativeFile.getFile() != null);
0698: if (!acceptNativeItem(nativeFile)) {
0699: return;
0700: }
0701: File file = nativeFile.getFile();
0702: APTPreprocHandler preprocHandler = createPreprocHandler(nativeFile);
0703: assert preprocHandler != null;
0704: int fileType = isSourceFile ? getFileType(nativeFile)
0705: : FileImpl.HEADER_FILE;
0706:
0707: FileAndHandler fileAndHandler = createOrFindFileImpl(
0708: ModelSupport.getFileBuffer(file), nativeFile, fileType);
0709:
0710: if (fileAndHandler.preprocHandler == null) {
0711: fileAndHandler.preprocHandler = createPreprocHandler(nativeFile);
0712: }
0713: if (isSourceFile || needParseOrphan) {
0714: ParserQueue.instance().addLast(fileAndHandler.fileImpl,
0715: fileAndHandler.preprocHandler.getState());
0716: }
0717:
0718: if (validator != null) {
0719: if (fileAndHandler.fileImpl.validate()) {
0720: if (validator.arePropertiesChanged(nativeFile)) {
0721: if (TraceFlags.TRACE_VALIDATION)
0722: System.err
0723: .printf(
0724: "Validation: %s properties are changed \n",
0725: nativeFile.getFile()
0726: .getAbsolutePath());
0727: DeepReparsingUtils.reparseOnPropertyChanged(
0728: nativeFile, this );
0729: }
0730: // clients should listen for ProjectLoaded instead
0731: // else if( fileAndHandler.fileImpl.isParsed() ) {
0732: // //ProgressSupport.instance().fireFileParsingStarted(fileAndHandler.fileImpl);
0733: // ProgressSupport.instance().fireFileParsingFinished(fileAndHandler.fileImpl);
0734: // }
0735: } else {
0736: if (TraceFlags.TRACE_VALIDATION)
0737: System.err.printf(
0738: "Validation: file %s is changed\n",
0739: nativeFile.getFile().getAbsolutePath());
0740: DeepReparsingUtils.reparseOnEdit(
0741: fileAndHandler.fileImpl, this , true);
0742: }
0743: }
0744: }
0745:
0746: /**
0747: * Is called after project is added to model
0748: * and all listeners are notified
0749: */
0750: public final void onAddedToModel() {
0751: final boolean isRestored = status == Status.Restored;
0752: //System.err.printf("onAddedToModel isRestored=%b status=%s for %s (%s) \n", isRestored, status, name, getClass().getName());
0753: if (status == Status.Initial || status == Status.Restored) {
0754: Runnable r = new Runnable() {
0755: public void run() {
0756: onAddedToModelImpl(isRestored);
0757: synchronized (initializationTaskLock) {
0758: initializationTask = null;
0759: }
0760: };
0761: };
0762: String text = (status == Status.Initial) ? "Filling parser queue for "
0763: : "Validating files for "; // NOI18N
0764: synchronized (initializationTaskLock) {
0765: initializationTask = ModelImpl.instance()
0766: .enqueueModelTask(r, text + getName());
0767: }
0768: }
0769: }
0770:
0771: protected Status getStatus() {
0772: return status;
0773: }
0774:
0775: protected void onAddedToModelImpl(boolean isRestored) {
0776:
0777: if (disposing) {
0778: return;
0779: }
0780:
0781: try {
0782: disposeLock.readLock().lock();
0783: if (disposing) {
0784: return;
0785: }
0786:
0787: ensureFilesCreated();
0788: if (disposing) {
0789: return;
0790: }
0791:
0792: ensureChangedFilesEnqueued();
0793: if (disposing) {
0794: return;
0795: }
0796: Notificator.instance().flush();
0797: } finally {
0798: disposeLock.readLock().unlock();
0799: }
0800:
0801: if (isRestored) {
0802: ProgressSupport.instance().fireProjectLoaded(
0803: ProjectBase.this );
0804: }
0805:
0806: try {
0807: disposeLock.readLock().lock();
0808: if (isRestored && !disposing) {
0809: // FIXUP for #109105 fix the reason instead!
0810: try {
0811: // TODO: refactor this - remove waiting here!
0812: // It was introduced in version 1.2.2.27.2.94.4.41
0813: // when validation was introduced
0814: waitParseImpl();
0815: checkForRemoved();
0816: } catch (Exception e) {
0817: DiagnosticExceptoins.register(e);
0818: }
0819: }
0820: if (disposing) {
0821: return;
0822: }
0823: Notificator.instance().flush();
0824: } finally {
0825: disposeLock.readLock().unlock();
0826: }
0827: }
0828:
0829: /**
0830: * For the project that is restored from persistence,
0831: * is called when 1-st time parsed.
0832: * Cheks whether there are files in code model, that are removed from the project system
0833: */
0834: private void checkForRemoved() {
0835:
0836: NativeProject nativeProject = (platformProject instanceof NativeProject) ? (NativeProject) platformProject
0837: : null;
0838:
0839: // we might just ask NativeProject to find file,
0840: // but it's too ineffective; so we have to create a set of project files paths
0841: Set<String> projectFiles = null;
0842: if (nativeProject != null) {
0843: projectFiles = new HashSet<String>();
0844: for (NativeFileItem item : nativeProject.getAllFiles()) {
0845: if (!item.isExcluded()) {
0846: switch (item.getLanguage()) {
0847: case C:
0848: case CPP:
0849: case C_HEADER:
0850: projectFiles.add(item.getFile()
0851: .getAbsolutePath());
0852: //this would be a workaround for #116706 Code assistance do not recognize changes in file
0853: //projectFiles.add(item.getFile().getCanonicalPath());
0854: break;
0855: default:
0856: break;
0857: }
0858: }
0859: }
0860: }
0861:
0862: Set<FileImpl> candidates = new HashSet<FileImpl>();
0863: Set<FileImpl> removedPhysically = new HashSet<FileImpl>();
0864: for (FileImpl file : getAllFileImpls()) {
0865: if (!file.getFile().exists()) {
0866: removedPhysically.add(file);
0867: } else if (projectFiles != null) { // they might be null for library
0868: if (!projectFiles.contains(file.getAbsolutePath())) {
0869: candidates.add(file);
0870: }
0871: }
0872: }
0873: for (FileImpl file : removedPhysically) {
0874: if (TraceFlags.TRACE_VALIDATION)
0875: System.err
0876: .printf(
0877: "Validation: removing (physically deleted) %s\n",
0878: file.getAbsolutePath()); //NOI18N
0879: onFileRemoved(file);
0880: }
0881: for (FileImpl file : candidates) {
0882: boolean remove = true;
0883: Set<CsmFile> parents = getGraphStorage().getParentFiles(
0884: file);
0885: for (CsmFile parent : parents) {
0886: if (!candidates.contains(parent)) {
0887: remove = false;
0888: break;
0889: }
0890: }
0891: if (remove) {
0892: if (TraceFlags.TRACE_VALIDATION)
0893: System.err
0894: .printf(
0895: "Validation: removing (removed from project) %s\n",
0896: file.getAbsolutePath()); //NOI18N
0897: onFileRemoved(file);
0898: }
0899: }
0900: }
0901:
0902: protected APTPreprocHandler createEmptyPreprocHandler(File file) {
0903: StartEntry startEntry = new StartEntry(FileContainer
0904: .getFileKey(file, true), RepositoryUtils
0905: .UIDtoKey(getUID()));
0906: return APTHandlersSupport.createEmptyPreprocHandler(startEntry);
0907: }
0908:
0909: protected APTPreprocHandler createPreprocHandler(
0910: NativeFileItem nativeFile) {
0911: assert (nativeFile != null);
0912: APTMacroMap macroMap = getMacroMap(nativeFile);
0913: APTIncludeHandler inclHandler = getIncludeHandler(nativeFile);
0914: APTPreprocHandler preprocHandler = APTHandlersSupport
0915: .createPreprocHandler(macroMap, inclHandler,
0916: isSourceFile(nativeFile));
0917: return preprocHandler;
0918: }
0919:
0920: private APTIncludeHandler getIncludeHandler(
0921: NativeFileItem nativeFile) {
0922: if (!isSourceFile(nativeFile)) {
0923: nativeFile = DefaultFileItem.toDefault(nativeFile);
0924: }
0925: List<String> userIncludePaths = nativeFile
0926: .getUserIncludePaths();
0927: List<String> sysIncludePaths = nativeFile
0928: .getSystemIncludePaths();
0929: sysIncludePaths = sysAPTData.getIncludes(sysIncludePaths
0930: .toString(), sysIncludePaths);
0931: StartEntry startEntry = new StartEntry(FileContainer
0932: .getFileKey(nativeFile.getFile(), true),
0933: RepositoryUtils.UIDtoKey(getUID()));
0934: return APTHandlersSupport.createIncludeHandler(startEntry,
0935: sysIncludePaths, userIncludePaths);
0936: }
0937:
0938: private APTMacroMap getMacroMap(NativeFileItem nativeFile) {
0939: if (!isSourceFile(nativeFile)) {
0940: nativeFile = DefaultFileItem.toDefault(nativeFile);
0941: }
0942: List<String> userMacros = nativeFile.getUserMacroDefinitions();
0943: List<String> sysMacros = nativeFile.getSystemMacroDefinitions();
0944: APTMacroMap map = APTHandlersSupport.createMacroMap(
0945: getSysMacroMap(sysMacros), userMacros);
0946: return map;
0947: }
0948:
0949: protected boolean isSourceFile(NativeFileItem nativeFile) {
0950: int type = getFileType(nativeFile);
0951: return type == FileImpl.SOURCE_CPP_FILE
0952: || type == FileImpl.SOURCE_C_FILE
0953: || type == FileImpl.SOURCE_FILE;
0954: //return nativeFile.getSystemIncludePaths().size()>0;
0955: }
0956:
0957: protected static int getFileType(NativeFileItem nativeFile) {
0958: switch (nativeFile.getLanguage()) {
0959: case C:
0960: return FileImpl.SOURCE_C_FILE;
0961: case CPP:
0962: return FileImpl.SOURCE_CPP_FILE;
0963: case C_HEADER:
0964: return FileImpl.HEADER_FILE;
0965: default:
0966: return FileImpl.UNDEFINED_FILE;
0967: }
0968: }
0969:
0970: private APTMacroMap getSysMacroMap(List<String> sysMacros) {
0971: //TODO: it's faster to use sysAPTData.getMacroMap(configID, sysMacros);
0972: // but we need this ID to get somehow... how?
0973: APTMacroMap map = sysAPTData.getMacroMap(sysMacros.toString(),
0974: sysMacros);
0975: return map;
0976: }
0977:
0978: public final APTPreprocHandler getPreprocHandler(File file) {
0979: APTPreprocHandler preprocHandler = createEmptyPreprocHandler(file);
0980: APTPreprocHandler.State state = getPreprocState(file);
0981: if (state != null) {
0982: if (state.isCleaned()) {
0983: return restorePreprocHandler(file, preprocHandler,
0984: state);
0985: } else {
0986: if (TRACE_PP_STATE_OUT)
0987: System.err.println("copying state for " + file);
0988: preprocHandler.setState(state);
0989: return preprocHandler;
0990: }
0991: }
0992: if (TRACE_PP_STATE_OUT)
0993: System.err.printf(
0994: "null state for %s, returning default one", file);
0995: return preprocHandler;
0996: }
0997:
0998: public final APTPreprocHandler.State getPreprocState(
0999: FileImpl fileImpl) {
1000: APTPreprocHandler.State state = null;
1001: FileContainer fc = getFileContainer();
1002: if (fc != null) {
1003: File file = fileImpl.getBuffer().getFile();
1004: state = fc.getPreprocState(file);
1005: }
1006: return state;
1007: }
1008:
1009: /**
1010: * This method for testing purpose only. Used from TraceModel
1011: */
1012: public CsmFile testAPTParseFile(NativeFileItem item) {
1013: APTPreprocHandler preprocHandler = this
1014: .createPreprocHandler(item);
1015: return findFile(item.getFile(), getFileType(item),
1016: preprocHandler, true, preprocHandler.getState(), item);
1017: }
1018:
1019: /**
1020: * This method must be called only under stateLock,
1021: * to get state lock use
1022: * Object stateLock = getFileContainer().getLock(file);
1023: */
1024: protected final void putPreprocState(File file,
1025: APTPreprocHandler.State state) {
1026: if (state != null && !state.isCleaned()) {
1027: state = APTHandlersSupport.createCleanPreprocState(state);
1028: }
1029: getFileContainer().putPreprocState(file, state);
1030: }
1031:
1032: protected final APTPreprocHandler.State setChangedFileState(
1033: NativeFileItem nativeFile) {
1034: APTPreprocHandler.State state;
1035: state = createPreprocHandler(nativeFile).getState();
1036: File file = nativeFile.getFile();
1037: Object stateLock = getFileContainer().getLock(file);
1038: synchronized (stateLock) {
1039: getFileContainer().invalidatePreprocState(file);
1040: putPreprocState(file, state);
1041: }
1042: return state;
1043: }
1044:
1045: protected APTPreprocHandler.State getPreprocState(File file) {
1046: return getFileContainer().getPreprocState(file);
1047: }
1048:
1049: protected void invalidatePreprocState(File file) {
1050: Object stateLock = getFileContainer().getLock(file);
1051: synchronized (stateLock) {
1052: getFileContainer().invalidatePreprocState(file);
1053: }
1054: }
1055:
1056: public void invalidateFiles() {
1057: getFileContainer().clearState();
1058: for (Iterator it = getLibraries().iterator(); it.hasNext();) {
1059: ProjectBase lib = (ProjectBase) it.next();
1060: lib.invalidateFiles();
1061: }
1062: }
1063:
1064: /**
1065: * called to inform that file was #included from another file with specific preprocHandler
1066: *
1067: * @param file included file path
1068: * @param preprocHandler preprocHandler with which the file is including
1069: * @param mode of walker forced onFileIncluded for #include directive
1070: * @return true if it's first time of file including
1071: * false if file was included before
1072: */
1073: public final FileImpl onFileIncluded(ProjectBase base, String file,
1074: APTPreprocHandler preprocHandler, int mode)
1075: throws IOException {
1076: try {
1077: disposeLock.readLock().lock();
1078: if (disposing) {
1079: return null;
1080: }
1081: FileImpl csmFile = findFile(new File(file),
1082: FileImpl.HEADER_FILE, preprocHandler, false, null,
1083: null);
1084:
1085: APTFile aptLight = getAPTLight(csmFile);
1086:
1087: if (csmFile != null && aptLight != null) {
1088: csmFile.initGuardIfNeeded(preprocHandler, aptLight);
1089: }
1090:
1091: APTPreprocHandler.State state = updateFileStateIfNeeded(
1092: csmFile, preprocHandler);
1093:
1094: // gather macro map from all includes
1095: if (aptLight != null) {
1096: APTParseFileWalker walker = new APTParseFileWalker(
1097: base, aptLight, csmFile, preprocHandler);
1098: walker.visit();
1099: }
1100:
1101: if (state != null && !isDisposing() && !base.isDisposing()) {
1102: scheduleIncludedFileParsing(csmFile, state);
1103: }
1104: return csmFile;
1105: } finally {
1106: disposeLock.readLock().unlock();
1107: }
1108: }
1109:
1110: // protected boolean needScheduleParsing(FileImpl file, APTPreprocHandler preprocHandler) {
1111: // APTPreprocHandler.State curState = (APTPreprocHandler.State) filesHandlers.get(file);
1112: // if (curState != null && !curState.isStateCorrect() && preprocHandler != null && preprocHandler.isStateCorrect()) {
1113: // return true;
1114: // }
1115: // return !file.isParsingOrParsed() || !TraceFlags.APT_CHECK_GET_STATE ;
1116: // }
1117:
1118: protected APTPreprocHandler.State updateFileStateIfNeeded(
1119: FileImpl csmFile, APTPreprocHandler preprocHandler) {
1120: APTPreprocHandler.State state = null;
1121: File file = csmFile.getBuffer().getFile();
1122: Object stateLock = getFileContainer().getLock(file);
1123: synchronized (stateLock) {
1124: if (csmFile.isNeedReparse(getPreprocState(file),
1125: preprocHandler)) {
1126: state = preprocHandler.getState();
1127: putPreprocState(file, state);
1128: // invalidate file
1129: csmFile.stateChanged(true);
1130: }
1131: }
1132: return state;
1133: }
1134:
1135: public ProjectBase findFileProject(CharSequence absPath) {
1136: // check own files
1137: // Wait while files are created. Otherwise project file will be recognized as library file.
1138: ensureFilesCreated();
1139: File file = new File(absPath.toString());
1140: if (getFile(file) != null) {
1141: return this ;
1142: } else {
1143: // else check in libs
1144: for (CsmProject prj : getLibraries()) {
1145: // Wait while files are created. Otherwise project file will be recognized as library file.
1146: ((ProjectBase) prj).ensureFilesCreated();
1147: if (((ProjectBase) prj).getFile(file) != null) {
1148: return (ProjectBase) prj;
1149: }
1150: }
1151: }
1152: return null;
1153: }
1154:
1155: public boolean isMySource(String includePath) {
1156: return projectRoots.isMySource(includePath);
1157: }
1158:
1159: public abstract void onFileAdded(NativeFileItem nativeFile);
1160:
1161: public abstract void onFileAdded(List<NativeFileItem> items);
1162:
1163: //public abstract void onFileRemoved(NativeFileItem nativeFile);
1164: public abstract void onFileRemoved(FileImpl fileImpl);
1165:
1166: public abstract void onFileRemoved(List<NativeFileItem> items);
1167:
1168: public abstract void onFilePropertyChanged(NativeFileItem nativeFile);
1169:
1170: public abstract void onFilePropertyChanged(
1171: List<NativeFileItem> items);
1172:
1173: protected abstract void scheduleIncludedFileParsing(
1174: FileImpl csmFile, APTPreprocHandler.State state);
1175:
1176: public abstract NativeFileItem getNativeFileItem(
1177: CsmUID<CsmFile> file);
1178:
1179: protected abstract void putNativeFileItem(CsmUID<CsmFile> file,
1180: NativeFileItem nativeFileItem);
1181:
1182: protected abstract void removeNativeFileItem(CsmUID<CsmFile> file);
1183:
1184: protected abstract void clearNativeFileContainer();
1185:
1186: public void onFileRemoved(File nativeFile) {
1187: onFileRemoved(getFile(nativeFile));
1188: }
1189:
1190: public CsmFile findFile(CharSequence absolutePath) {
1191: File file = new File(absolutePath.toString());
1192: APTPreprocHandler preprocHandler = null;
1193: if (getPreprocState(file) == null) {
1194: NativeFileItem nativeFile = null;
1195: // Try to find native file
1196: if (getPlatformProject() instanceof NativeProject) {
1197: NativeProject prj = (NativeProject) getPlatformProject();
1198: if (prj != null) {
1199: nativeFile = prj.findFileItem(file);
1200: if (nativeFile == null) {
1201: // if not belong to NB project => not our file
1202: return null;
1203: // nativeFile = new DefaultFileItem(prj, absolutePath);
1204: }
1205: if (!acceptNativeItem(nativeFile)) {
1206: return null;
1207: }
1208: preprocHandler = createPreprocHandler(nativeFile);
1209: }
1210: }
1211: if (preprocHandler != null) {
1212: return findFile(file, FileImpl.UNDEFINED_FILE,
1213: preprocHandler, true,
1214: preprocHandler.getState(), nativeFile);
1215: }
1216: }
1217: // if getPreprocState(file) isn't null, the file alreasy exists, so we may not pass nativeFile
1218: return findFile(file, FileImpl.UNDEFINED_FILE, preprocHandler,
1219: true, null, null);
1220: }
1221:
1222: protected FileImpl findFile(File file, int fileType,
1223: APTPreprocHandler preprocHandler,
1224: boolean scheduleParseIfNeed,
1225: APTPreprocHandler.State initial,
1226: NativeFileItem nativeFileItem) {
1227:
1228: FileImpl impl = getFile(file);
1229: if (impl == null) {
1230: synchronized (getFileContainer()) {
1231: impl = getFile(file);
1232: if (impl == null) {
1233: preprocHandler = (preprocHandler == null) ? getPreprocHandler(file)
1234: : preprocHandler;
1235: impl = new FileImpl(ModelSupport
1236: .getFileBuffer(file), this , fileType,
1237: nativeFileItem);
1238: if (nativeFileItem != null) {
1239: putNativeFileItem(impl.getUID(), nativeFileItem);
1240: }
1241: putFile(file, impl, initial);
1242: // NB: parse only after putting into a map
1243: if (scheduleParseIfNeed) {
1244: APTPreprocHandler.State ppState = preprocHandler == null ? null
1245: : preprocHandler.getState();
1246: ParserQueue.instance().addLast(impl, ppState);
1247: }
1248: }
1249: }
1250: }
1251: if (fileType == FileImpl.SOURCE_FILE && !impl.isSourceFile()) {
1252: impl.setSourceFile();
1253: } else if (fileType == FileImpl.HEADER_FILE
1254: && !impl.isHeaderFile()) {
1255: impl.setHeaderFile();
1256: }
1257: Object stateLock = getFileContainer().getLock(file);
1258: synchronized (stateLock) {
1259: if (initial != null && getPreprocState(file) == null) {
1260: putPreprocState(file, initial);
1261: }
1262: }
1263: return impl;
1264: }
1265:
1266: // protected FileImpl createOrFindFileImpl(final NativeFileItem nativeFile) {
1267: // File file = nativeFile.getFile();
1268: // assert file != null;
1269: // return createOrFindFileImpl(ModelSupport.instance().getFileBuffer(file), nativeFile);
1270: // }
1271:
1272: protected FileImpl createOrFindFileImpl(final FileBuffer buf,
1273: final NativeFileItem nativeFile) {
1274: return createOrFindFileImpl(buf, nativeFile,
1275: getFileType(nativeFile)).fileImpl;
1276: }
1277:
1278: private static class FileAndHandler {
1279: public FileAndHandler(FileImpl fileImpl,
1280: APTPreprocHandler preprocHandler) {
1281: this .fileImpl = fileImpl;
1282: this .preprocHandler = preprocHandler;
1283: }
1284:
1285: public FileImpl fileImpl;
1286: public APTPreprocHandler preprocHandler;
1287: }
1288:
1289: private FileAndHandler createOrFindFileImpl(final FileBuffer buf,
1290: final NativeFileItem nativeFile, int fileType) {
1291: APTPreprocHandler preprocHandler = null;
1292: File file = buf.getFile();
1293: FileImpl impl = getFile(file);
1294: if (impl == null) {
1295: synchronized (getFileContainer()) {
1296: impl = getFile(file);
1297: if (impl == null) {
1298: preprocHandler = createPreprocHandler(nativeFile);
1299: assert preprocHandler != null;
1300: impl = new FileImpl(buf, this , fileType, nativeFile);
1301: putFile(file, impl, preprocHandler.getState());
1302: } else {
1303: putNativeFileItem(impl.getUID(), nativeFile);
1304: }
1305: }
1306: } else {
1307: putNativeFileItem(impl.getUID(), nativeFile);
1308: }
1309: return new FileAndHandler(impl, preprocHandler);
1310: }
1311:
1312: public FileImpl getFile(File file) {
1313: return getFileContainer().getFile(file);
1314: }
1315:
1316: protected void removeFile(File file) {
1317: getFileContainer().removeFile(file);
1318: }
1319:
1320: protected void putFile(File file, FileImpl impl,
1321: APTPreprocHandler.State state) {
1322: if (state != null && !state.isCleaned()) {
1323: state = APTHandlersSupport.createCleanPreprocState(state);
1324: }
1325: getFileContainer().putFile(file, impl, state);
1326: }
1327:
1328: protected Collection<Key> getLibrariesKeys() {
1329: List<Key> res = new ArrayList<Key>();
1330: if (platformProject instanceof NativeProject) {
1331: for (NativeProject nativeLib : ((NativeProject) platformProject)
1332: .getDependences()) {
1333: final Key key = KeyUtilities
1334: .createProjectKey(getUniqueName(nativeLib)
1335: .toString());
1336: if (key != null) {
1337: res.add(key);
1338: }
1339: }
1340: }
1341: // Last dependent project is common library.
1342: //final Key lib = KeyUtilities.createProjectKey("/usr/include"); // NOI18N
1343: //if (lib != null) {
1344: // res.add(lib);
1345: //}
1346: if (!isArtificial()) {
1347: for (CsmUID<CsmProject> library : LibraryManager
1348: .getInstance().getLirariesKeys(getUID())) {
1349: res.add(RepositoryUtils.UIDtoKey(library));
1350: }
1351: }
1352: return res;
1353: }
1354:
1355: public Collection<CsmProject> getLibraries() {
1356: List<CsmProject> res = new ArrayList<CsmProject>();
1357: if (platformProject instanceof NativeProject) {
1358: for (NativeProject nativeLib : ((NativeProject) platformProject)
1359: .getDependences()) {
1360: CsmProject prj = model.findProject(nativeLib);
1361: if (prj != null) {
1362: res.add(prj);
1363: }
1364: }
1365: }
1366: // Last dependent project is common library.
1367: //ProjectBase lib = getModel().getLibrary("/usr/include"); // NOI18N
1368: //if (lib != null) {
1369: // res.add(lib);
1370: //}
1371: if (!isArtificial()) {
1372: for (LibProjectImpl library : LibraryManager.getInstance()
1373: .getLiraries((ProjectImpl) this )) {
1374: res.add(library);
1375: }
1376: }
1377: return res;
1378: }
1379:
1380: public List<ProjectBase> getDependentProjects() {
1381: List<ProjectBase> res = new ArrayList<ProjectBase>();
1382: for (CsmProject prj : model.projects()) {
1383: if (prj instanceof ProjectBase) {
1384: if (prj.getLibraries().contains(this )) {
1385: res.add((ProjectBase) prj);
1386: }
1387: }
1388: }
1389: return res;
1390: }
1391:
1392: /**
1393: * Creates a dummy ClassImpl for uresolved name, stores in map
1394: * @param nameTokens name
1395: * @param file file that contains unresolved name (used for the purpose of statictics)
1396: * @param name offset that contains unresolved name (used for the purpose of statictics)
1397: */
1398: public CsmClass getDummyForUnresolved(CharSequence[] nameTokens,
1399: CsmFile file, int offset) {
1400: if (Diagnostic.needStatistics())
1401: Diagnostic.onUnresolvedError(nameTokens, file, offset);
1402: return getUnresolved().getDummyForUnresolved(nameTokens);
1403: }
1404:
1405: /**
1406: * Creates a dummy ClassImpl for uresolved name, stores in map.
1407: * Should be used only when restoring from persistence:
1408: * in contrary to getDummyForUnresolved(String[] nameTokens, CsmFile file, int offset),
1409: * it does not gather statistics!
1410: * @param nameTokens name
1411: */
1412: public CsmClass getDummyForUnresolved(String name) {
1413: return getUnresolved().getDummyForUnresolved(name);
1414: }
1415:
1416: public CsmNamespace getUnresolvedNamespace() {
1417: return getUnresolved().getUnresolvedNamespace();
1418: }
1419:
1420: public CsmFile getUnresolvedFile() {
1421: return getUnresolved().getUnresolvedFile();
1422: }
1423:
1424: private Unresolved getUnresolved() {
1425: // we don't sinc here since this isn't important enough:
1426: // at worst a map with one or two dummies will be thrown away
1427: if (unresolved == null) {
1428: unresolved = new Unresolved(this );
1429: }
1430: return unresolved;
1431: }
1432:
1433: public boolean isValid() {
1434: return platformProject != null && !disposing;
1435: }
1436:
1437: public void setDisposed() {
1438: disposing = true;
1439: synchronized (initializationTaskLock) {
1440: if (initializationTask != null) {
1441: initializationTask.cancel();
1442: initializationTask = null;
1443: }
1444: }
1445: ParserQueue.instance().removeAll(this );
1446: }
1447:
1448: public boolean isDisposing() {
1449: return disposing;
1450: }
1451:
1452: public void dispose(final boolean cleanPersistent) {
1453:
1454: long time = 0;
1455: if (TraceFlags.TIMING) {
1456: System.err.printf("\n\nProject %s: disposing...\n", name);
1457: time = System.currentTimeMillis();
1458: }
1459:
1460: // just in case it wasn't called before (it's inexpensive)
1461: setDisposed();
1462:
1463: try {
1464:
1465: disposeLock.writeLock().lock();
1466:
1467: ProjectSettingsValidator validator = new ProjectSettingsValidator(
1468: this );
1469: validator.storeSettings();
1470: RepositoryUtils.closeUnit(getUID(), getRequiredUnits(),
1471: cleanPersistent);
1472:
1473: platformProject = null;
1474: unresolved = null;
1475: uid = null;
1476: } finally {
1477: disposeLock.writeLock().unlock();
1478: }
1479:
1480: if (TraceFlags.TIMING) {
1481: time = System.currentTimeMillis() - time;
1482: System.err.printf("Project %s: disposing took %d ms\n",
1483: name, time);
1484: }
1485: }
1486:
1487: protected Set<String> getRequiredUnits() {
1488: Set<String> requiredUnits = new HashSet<String>();
1489: for (Key dependent : this .getLibrariesKeys()) {
1490: requiredUnits.add(dependent.getUnit().toString());
1491: }
1492: return requiredUnits;
1493: }
1494:
1495: private void disposeFiles() {
1496: List<FileImpl> list;
1497: // synchronized (fileContainer) {
1498: list = getFileContainer().getFileImpls();
1499: getFileContainer().clear();
1500: // }
1501: for (FileImpl file : list) {
1502: file.onProjectDispose();
1503: if (TraceFlags.USE_AST_CACHE) {
1504: CacheManager.getInstance().invalidate(file);
1505: } else {
1506: APTDriver.getInstance().invalidateAPT(file.getBuffer());
1507: }
1508: }
1509: clearNativeFileContainer();
1510: }
1511:
1512: private NamespaceImpl _getGlobalNamespace() {
1513: NamespaceImpl ns = (NamespaceImpl) UIDCsmConverter
1514: .UIDtoNamespace(globalNamespaceUID);
1515: assert ns != null : "Failed to get global namespace by key "
1516: + globalNamespaceUID;
1517: return ns;
1518: }
1519:
1520: private NamespaceImpl _getNamespace(CharSequence key) {
1521: key = CharSequenceKey.create(key);
1522: CsmUID<CsmNamespace> nsUID = namespaces.get(key);
1523: NamespaceImpl ns = (NamespaceImpl) UIDCsmConverter
1524: .UIDtoNamespace(nsUID);
1525: return ns;
1526: }
1527:
1528: private void _registerNamespace(NamespaceImpl ns) {
1529: assert (ns != null);
1530: CharSequence key = ns.getQualifiedName();
1531: assert (key != null && !(key instanceof String));
1532: CsmUID<CsmNamespace> nsUID = RepositoryUtils.put(ns);
1533: assert nsUID != null;
1534: namespaces.put(key, nsUID);
1535: }
1536:
1537: private void _unregisterNamespace(NamespaceImpl ns) {
1538: assert (ns != null);
1539: assert !ns.isGlobal();
1540: CharSequence key = ns.getQualifiedName();
1541: assert (key != null && !(key instanceof String));
1542: CsmUID<CsmNamespace> nsUID = namespaces.remove(key);
1543: assert nsUID != null;
1544: RepositoryUtils.remove(nsUID);
1545: }
1546:
1547: protected ModelImpl getModel() {
1548: return model;
1549: }
1550:
1551: public void onFileEditStart(FileBuffer buf,
1552: NativeFileItem nativeFile) {
1553: }
1554:
1555: public void onFileEditEnd(FileBuffer buf, NativeFileItem nativeFile) {
1556: }
1557:
1558: private CsmUID<CsmProject> uid = null;
1559:
1560: public final CsmUID<CsmProject> getUID() { // final because called from constructor
1561: if (uid == null) {
1562: uid = UIDUtilities.createProjectUID(this );
1563: }
1564: return uid;
1565: }
1566:
1567: public boolean isStable(CsmFile skipFile) {
1568: if (status == Status.Ready && !disposing) {
1569: return !ParserQueue.instance().hasFiles(this ,
1570: (FileImpl) skipFile);
1571: }
1572: return false;
1573: }
1574:
1575: public void onParseFinish() {
1576: synchronized (waitParseLock) {
1577: waitParseLock.notifyAll();
1578: }
1579: // it's ok to move the entire sycle into synchronized block,
1580: // because from inter-session persistence point of view,
1581: // if we don't fix fakes, we'll later consider that files are ok,
1582: // which is incorrect if there are some fakes
1583: try {
1584: disposeLock.readLock().lock();
1585:
1586: if (!disposing) {
1587: for (Iterator it = getAllFiles().iterator(); it
1588: .hasNext();) {
1589: FileImpl file = (FileImpl) it.next();
1590: file.fixFakeRegistrations();
1591: }
1592: }
1593: } finally {
1594: disposeLock.readLock().unlock();
1595: ProjectComponent.setStable(declarationsSorageKey);
1596: ProjectComponent.setStable(fileContainerKey);
1597: ProjectComponent.setStable(graphStorageKey);
1598: }
1599: }
1600:
1601: /**
1602: * CsmProject implementation
1603: */
1604: public Collection<CsmFile> getAllFiles() {
1605: return (Collection<CsmFile>) getFileContainer().getFiles();
1606: }
1607:
1608: /**
1609: * We'd better name this getFiles();
1610: * but unfortunately there already is such method,
1611: * and it is used intensively
1612: */
1613: public Collection<FileImpl> getAllFileImpls() {
1614: return getFileContainer().getFileImpls();
1615: }
1616:
1617: public Collection<CsmFile> getSourceFiles() {
1618: List<CsmFile> res = new ArrayList<CsmFile>();
1619: for (FileImpl file : getAllFileImpls()) {
1620: if (file.isSourceFile()) {
1621: res.add(file);
1622: }
1623: }
1624: return res;
1625: }
1626:
1627: public Collection<CsmFile> getHeaderFiles() {
1628: List<CsmFile> res = new ArrayList<CsmFile>();
1629: for (FileImpl file : getAllFileImpls()) {
1630: //if (file.isHeaderFile()) {
1631: if (!file.isSourceFile()) {
1632: res.add(file);
1633: }
1634: }
1635: return res;
1636: }
1637:
1638: public long getMemoryUsageEstimation() {
1639: //TODO: replace with some smart algorythm
1640: return getFileContainer().getSize();
1641: }
1642:
1643: @Override
1644: public String toString() {
1645: return getName().toString() + ' ' + getClass().getName() + " @"
1646: + hashCode(); // NOI18N
1647: }
1648:
1649: /**
1650: * Just a struct for the getStartEntryInfo return valie:
1651: * if java allowed passing pointers by reference, we won't create this...
1652: */
1653: private static class /*struct*/StartEntryInfo {
1654:
1655: public final APTPreprocHandler preprocHandler;
1656: public final ProjectBase startProject;
1657: public final FileImpl csmFile;
1658:
1659: public StartEntryInfo(APTPreprocHandler preprocHandler,
1660: ProjectBase startProject, FileImpl csmFile) {
1661: this .preprocHandler = preprocHandler;
1662: this .startProject = startProject;
1663: this .csmFile = csmFile;
1664: }
1665:
1666: }
1667:
1668: private StartEntryInfo getStartEntryInfo(
1669: APTPreprocHandler preprocHandler,
1670: APTPreprocHandler.State state) {
1671: StartEntry startEntry = APTHandlersSupport
1672: .extractStartEntry(state);
1673: ProjectBase startProject = getStartProject(startEntry);
1674: FileImpl csmFile = startProject == null ? null : startProject
1675: .getFile(new File(startEntry.getStartFile()));
1676: if (csmFile != null) {
1677: NativeFileItem nativeFile = csmFile.getNativeFileItem();
1678: if (nativeFile != null) {
1679: preprocHandler = startProject
1680: .createPreprocHandler(nativeFile);
1681: }
1682: }
1683: return new StartEntryInfo(preprocHandler, startProject, csmFile);
1684: }
1685:
1686: private APTPreprocHandler restorePreprocHandler(
1687: File interestedFile, APTPreprocHandler preprocHandler,
1688: APTPreprocHandler.State state) {
1689: assert state != null;
1690: assert state.isCleaned();
1691: // walk through include stack to restore preproc information
1692: List<APTIncludeHandler.IncludeInfo> reverseInclStack = APTHandlersSupport
1693: .extractIncludeStack(state);
1694: assert (reverseInclStack != null);
1695: if (reverseInclStack.isEmpty()) {
1696: if (TRACE_PP_STATE_OUT)
1697: System.err
1698: .println("stack is empty; return default for "
1699: + interestedFile);
1700: return getStartEntryInfo(preprocHandler, state).preprocHandler;
1701: } else {
1702: if (TRACE_PP_STATE_OUT)
1703: System.err.println("restoring for " + interestedFile);
1704: // we need to reverse includes stack
1705: assert (!reverseInclStack.isEmpty()) : "state of stack is "
1706: + reverseInclStack;
1707: Stack<APTIncludeHandler.IncludeInfo> inclStack = reverse(reverseInclStack);
1708: StartEntryInfo sei = getStartEntryInfo(preprocHandler,
1709: state);
1710: FileImpl csmFile = sei.csmFile;
1711: ProjectBase startProject = sei.startProject;
1712: preprocHandler = sei.preprocHandler;
1713:
1714: APTFile aptLight = null;
1715: try {
1716: aptLight = csmFile == null ? null
1717: : getAPTLight(csmFile);
1718: } catch (IOException ex) {
1719: System.err
1720: .println("can't restore preprocessor state for "
1721: + interestedFile + //NOI18N
1722: "\nreason: " + ex.getMessage());//NOI18N
1723: DiagnosticExceptoins.register(ex);
1724: }
1725: boolean ppStateRestored = false;
1726: if (aptLight != null) {
1727: // for testing remember restored file
1728: long time = REMEMBER_RESTORED ? System
1729: .currentTimeMillis() : 0;
1730: int stackSize = inclStack.size();
1731: APTWalker walker = new APTRestorePreprocStateWalker(
1732: startProject, aptLight, csmFile,
1733: preprocHandler, inclStack, FileContainer
1734: .getFileKey(interestedFile, false));
1735: walker.visit();
1736: if (preprocHandler.isValid()) {
1737: if (REMEMBER_RESTORED) {
1738: if (testRestoredFiles == null) {
1739: testRestoredFiles = new ArrayList<String>();
1740: }
1741: FileImpl interestedFileImpl = getFile(interestedFile);
1742: assert interestedFileImpl != null;
1743: String msg = interestedFile.getAbsolutePath()
1744: + " ["
1745: + (interestedFileImpl.isHeaderFile() ? "H"
1746: : interestedFileImpl
1747: .isSourceFile() ? "S"
1748: : "U") + "]"; // NOI18N
1749: time = System.currentTimeMillis() - time;
1750: msg = msg + " within " + time + "ms"
1751: + " stack " + stackSize + " elems"; // NOI18N
1752: System.err.println("#"
1753: + testRestoredFiles.size()
1754: + " restored: " + msg); // NOI18N
1755: testRestoredFiles.add(msg);
1756: }
1757: if (TRACE_PP_STATE_OUT) {
1758: System.err.println("after restoring "
1759: + preprocHandler); // NOI18N
1760: }
1761: ppStateRestored = true;
1762: }
1763: }
1764: if (!ppStateRestored) {
1765: // need to recover from the problem, when start file is invalid or absent
1766: // try to find project who can create default handler with correct
1767: // compiler settings
1768: // preferences is start project
1769: if (startProject == null) {
1770: // otherwise use the project owner
1771: startProject = this ;
1772: }
1773: preprocHandler = startProject
1774: .createDefaultPreprocHandler(interestedFile);
1775: // remember
1776: // TODO: file container should accept all without checks
1777: // otherwise state will not be replaced
1778: // synchronized (getFileContainer().getLock(interestedFile)) {
1779: // if (state.equals(getPreprocState(interestedFile))) {
1780: // APTPreprocHandler.State recoveredState = preprocHandler.getState();
1781: // assert !recoveredState.isCompileContext();
1782: // putPreprocState(interestedFile, recoveredState);
1783: // }
1784: // }
1785: }
1786: return preprocHandler;
1787: }
1788: }
1789:
1790: /*
1791: private APTPreprocHandler restorePreprocHandler(File interestedFile, APTPreprocHandler preprocHandler, APTPreprocHandler.State state) {
1792: assert state != null;
1793: assert state.isCleaned();
1794: // walk through include stack to restore preproc information
1795: List<APTIncludeHandler.IncludeInfo> reverseInclStack = APTHandlersSupport.extractIncludeStack(state);
1796: assert (reverseInclStack != null);
1797: if (reverseInclStack.isEmpty()) {
1798: if (TRACE_PP_STATE_OUT) System.err.println("stack is empty; return default for " + interestedFile);
1799: return getStartEntryInfo(preprocHandler, state).preprocHandler;
1800: } else {
1801: if (TRACE_PP_STATE_OUT) System.err.println("restoring for " + interestedFile);
1802: // we need to reverse includes stack
1803: assert (!reverseInclStack.isEmpty()) : "state of stack is " + reverseInclStack;
1804: StartEntryInfo sei = getStartEntryInfo(preprocHandler, state);
1805: FileImpl csmFile = sei.csmFile;
1806: ProjectBase startProject = sei.startProject;
1807: preprocHandler = sei.preprocHandler;
1808:
1809: ProjectBase prevProject = startProject;
1810: // for testing remember restored file
1811: long time = REMEMBER_RESTORED ? System.currentTimeMillis() : 0;
1812: boolean ppStateRestored = false;
1813: for (int i = 0; i < reverseInclStack.size() && !ppStateRestored; i++) {
1814: Stack<APTIncludeHandler.IncludeInfo> inclStack = reverse(reverseInclStack);
1815: if (i > 0) {
1816: System.err.println("need to try smaller stack");
1817: sei = getStartEntryInfo(preprocHandler, state);
1818: preprocHandler = sei.preprocHandler;
1819: for (int j = i; j > 0; j--) {
1820: inclStack.pop();
1821: }
1822: String includedPath = inclStack.peek().getIncludedPath();
1823: File startFile = new File(includedPath);
1824: csmFile = null;
1825: if (prevProject != null) {
1826: startProject = LibraryManager.getInstance().searchInProjectFiles(prevProject, startFile);
1827: csmFile = startProject == null ? null : startProject.getFile(startFile);
1828: }
1829: if (csmFile == null) {
1830: CsmFile foundCsmFile = CsmModelAccessor.getModel().findFile(includedPath);
1831: if (foundCsmFile instanceof FileImpl) {
1832: csmFile = (FileImpl)foundCsmFile;
1833: }
1834: }
1835: if (csmFile != null) {
1836: prevProject = csmFile.getProjectImpl();
1837: }
1838: }
1839: APTFile aptLight = null;
1840: try {
1841: aptLight = csmFile == null ? null : getAPTLight(csmFile);
1842: } catch (IOException ex) {
1843: System.err.println("can't restore preprocessor state for " + interestedFile + //NOI18N
1844: "\nreason: " + ex.getMessage());//NOI18N
1845: }
1846: if (aptLight != null) {
1847: int stackSize = inclStack.size();
1848: APTWalker walker = new APTRestorePreprocStateWalker(startProject, aptLight, csmFile, preprocHandler, inclStack, FileContainer.getFileKey(interestedFile, false));
1849: walker.visit();
1850: if (preprocHandler.isValid()) {
1851: if (REMEMBER_RESTORED) {
1852: if (testRestoredFiles == null) {
1853: testRestoredFiles = new ArrayList<String>();
1854: }
1855: FileImpl interestedFileImpl = getFile(interestedFile);
1856: assert interestedFileImpl != null;
1857: String msg = interestedFile.getAbsolutePath() + " [" + (interestedFileImpl.isHeaderFile() ? "H" : interestedFileImpl.isSourceFile() ? "S" : "U") + "]"; // NOI18N
1858: time = System.currentTimeMillis() - time;
1859: msg = msg + " within " + time + "ms" + " stack " + stackSize + " elems" + " orininal size was " + reverseInclStack.size(); // NOI18N
1860: System.err.println("#" + testRestoredFiles.size() + " restored: " + msg); // NOI18N
1861: testRestoredFiles.add(msg);
1862: }
1863: if (TRACE_PP_STATE_OUT) {
1864: System.err.println("after restoring " + preprocHandler); // NOI18N
1865: }
1866: ppStateRestored = true;
1867: }
1868: }
1869: }
1870: if (!ppStateRestored) {
1871: // need to recover from the problem, when start file is invalid or absent
1872: // try to find project who can create default handler with correct
1873: // compiler settings
1874: // preferences is start project
1875: if (startProject == null) {
1876: // otherwise use the project owner
1877: startProject = this;
1878: }
1879: preprocHandler = startProject.createDefaultPreprocHandler(interestedFile);
1880: // remember
1881: // TODO: file container should accept all without checks
1882: // otherwise state will not be replaced
1883: // synchronized (getFileContainer().getLock(interestedFile)) {
1884: // if (state.equals(getPreprocState(interestedFile))) {
1885: // APTPreprocHandler.State recoveredState = preprocHandler.getState();
1886: // assert !recoveredState.isCompileContext();
1887: // putPreprocState(interestedFile, recoveredState);
1888: // }
1889: // }
1890: }
1891: return preprocHandler;
1892: }
1893: }
1894: */
1895:
1896: private NativeProject findNativeProjectHolder(
1897: Set<ProjectBase> visited) {
1898: visited.add(this );
1899: NativeProject nativeProject = ModelSupport
1900: .getNativeProject(getPlatformProject());
1901: if (nativeProject == null) {
1902: // try to find dependent projects and ask them
1903: List<ProjectBase> deps = this .getDependentProjects();
1904: for (ProjectBase dependentPrj : deps) {
1905: if (!visited.contains(dependentPrj)) {
1906: nativeProject = dependentPrj
1907: .findNativeProjectHolder(visited);
1908: if (nativeProject != null) {
1909: // found
1910: break;
1911: }
1912: }
1913: }
1914: }
1915: return nativeProject;
1916: }
1917:
1918: private APTPreprocHandler createDefaultPreprocHandler(
1919: File interestedFile) {
1920: NativeProject nativeProject = findNativeProjectHolder(new HashSet(
1921: 10));
1922: APTPreprocHandler out = null;
1923: if (nativeProject != null) {
1924: // we have own native project to get settings from
1925: NativeFileItem item = new DefaultFileItem(nativeProject,
1926: interestedFile.getAbsolutePath());
1927: out = createPreprocHandler(item);
1928: } else {
1929: out = createEmptyPreprocHandler(interestedFile);
1930: }
1931: assert out != null : "failed creating default ppState for "
1932: + interestedFile;
1933: return out;
1934: }
1935:
1936: private static <T> Stack<T> reverse(List<T> original) {
1937: Stack<T> reverse = new Stack<T>();
1938: for (int i = original.size() - 1; i >= 0; i--) {
1939: T inclInfo = original.get(i);
1940: reverse.push(inclInfo);
1941: }
1942: return reverse;
1943: }
1944:
1945: public static NativeFileItem getCompiledFileItem(FileImpl fileImpl) {
1946: NativeFileItem out = null;
1947: ProjectBase filePrj = fileImpl.getProjectImpl();
1948: if (filePrj != null) {
1949: APTPreprocHandler.State state = filePrj
1950: .getPreprocState(fileImpl);
1951: FileImpl startFile = getStartFile(state);
1952: out = startFile != null ? startFile.getNativeFileItem()
1953: : null;
1954: }
1955: return out;
1956: }
1957:
1958: public static FileImpl getStartFile(
1959: final APTPreprocHandler.State state) {
1960: StartEntry startEntry = APTHandlersSupport
1961: .extractStartEntry(state);
1962: ProjectBase startProject = getStartProject(startEntry);
1963: FileImpl csmFile = startProject == null ? null : startProject
1964: .getFile(new File(startEntry.getStartFile()));
1965: return csmFile;
1966: }
1967:
1968: public static ProjectBase getStartProject(
1969: final APTPreprocHandler.State state) {
1970: return getStartProject(APTHandlersSupport
1971: .extractStartEntry(state));
1972: }
1973:
1974: public static ProjectBase getStartProject(StartEntry startEntry) {
1975: Key key = startEntry.getStartFileProject();
1976: ProjectBase prj = (ProjectBase) RepositoryUtils.get(key);
1977: return prj;
1978: }
1979:
1980: public APTFile getAPTLight(CsmFile csmFile) throws IOException {
1981: APTFile aptLight = null;
1982: if (TraceFlags.USE_AST_CACHE) {
1983: aptLight = CacheManager.getInstance().findAPTLight(csmFile);
1984: } else {
1985: aptLight = APTDriver.getInstance().findAPTLight(
1986: ((FileImpl) csmFile).getBuffer());
1987: }
1988: return aptLight;
1989: }
1990:
1991: public GraphContainer getGraph() {
1992: return getGraphStorage();
1993: }
1994:
1995: protected final static class DefaultFileItem implements
1996: NativeFileItem {
1997:
1998: private NativeProject project;
1999: private String absolutePath;
2000:
2001: public DefaultFileItem(NativeProject project,
2002: String absolutePath) {
2003: this .project = project;
2004: this .absolutePath = absolutePath;
2005: }
2006:
2007: public DefaultFileItem(NativeFileItem nativeFile) {
2008: this .project = nativeFile.getNativeProject();
2009: this .absolutePath = nativeFile.getFile().getAbsolutePath();
2010: }
2011:
2012: public static NativeFileItem toDefault(NativeFileItem nativeFile) {
2013: // if not already fake
2014: if (!(nativeFile instanceof DefaultFileItem)) {
2015: nativeFile = new DefaultFileItem(nativeFile);
2016: }
2017: return nativeFile;
2018: }
2019:
2020: public List<String> getUserMacroDefinitions() {
2021: if (project != null) {
2022: return project.getUserMacroDefinitions();
2023: }
2024: return Collections.<String> emptyList();
2025: }
2026:
2027: public List<String> getUserIncludePaths() {
2028: if (project != null) {
2029: return project.getUserIncludePaths();
2030: }
2031: return Collections.<String> emptyList();
2032: }
2033:
2034: public List<String> getSystemMacroDefinitions() {
2035: if (project != null) {
2036: return project.getSystemMacroDefinitions();
2037: }
2038: return Collections.<String> emptyList();
2039: }
2040:
2041: public List<String> getSystemIncludePaths() {
2042: if (project != null) {
2043: return project.getSystemIncludePaths();
2044: }
2045: return Collections.<String> emptyList();
2046: }
2047:
2048: public NativeProject getNativeProject() {
2049: return project;
2050: }
2051:
2052: public File getFile() {
2053: return new File(absolutePath);
2054: }
2055:
2056: public Language getLanguage() {
2057: return NativeFileItem.Language.C_HEADER;
2058: }
2059:
2060: public LanguageFlavor getLanguageFlavor() {
2061: return NativeFileItem.LanguageFlavor.GENERIC;
2062: }
2063:
2064: public boolean isExcluded() {
2065: return false;
2066: }
2067: }
2068:
2069: /**
2070: * Represent the project status.
2071: *
2072: * Concerns only initial stage of project lifecycle:
2073: * allows to distingwish just newly-created project,
2074: * the phase when files are being added to project (and to parser queue)
2075: * and the phase when all files are already added.
2076: *
2077: * It isn't worth tracking further stages (stable/unstable)
2078: * since it's error prone (it's better to ask, say, parser queue
2079: * whether it contains files that belong to this projec or not)
2080: */
2081: protected static enum Status {
2082: Initial, Restored, AddingFiles, Validating, Ready;
2083: }
2084:
2085: private transient Status status;
2086:
2087: /** The task that is run in a request processor during project initialization */
2088: private Cancellable initializationTask;
2089:
2090: /** The lock under which the initializationTask is set */
2091: private Object initializationTaskLock = new Object();
2092:
2093: private Object waitParseLock = new Object();
2094:
2095: private ModelImpl model;
2096: private Unresolved unresolved;
2097: private CharSequence name;
2098:
2099: private final CsmUID<CsmNamespace> globalNamespaceUID;
2100:
2101: private Object platformProject;
2102:
2103: /**
2104: * Some notes concerning disposing and disposeLock fields.
2105: *
2106: * The purpose is not to perform some actions
2107: * (such as adding new files, continuing initialization, etc)
2108: * when the project is going to be disposed.
2109: *
2110: * The disposing field is changed only once,
2111: * from false to true (in setDispose() method)
2112: *
2113: * When it is changed to true, no lock is aquired, BUT:
2114: * it is guaranteed that events take place in the following order:
2115: * 1) disposing is set to true
2116: * 2) the disposeLock.writeLock() is locked after that
2117: * and remains locked during the entire project closure.
2118: *
2119: * Clients who need to check this, are obliged to
2120: * act in the following sequence:
2121: * 1) require disposeLock.readLock()
2122: * 2) check that the disposing field is still false
2123: * 3) keep disposeLock.readLock() locked
2124: * while performing critical actions
2125: * (the actions that should not be done
2126: * when the project is being disposed)
2127: *
2128: */
2129: private boolean disposing;
2130: private ReadWriteLock disposeLock = new ReentrantReadWriteLock();
2131:
2132: private CharSequence uniqueName = null; // lazy initialized
2133:
2134: private Map<CharSequence, CsmUID<CsmNamespace>> namespaces = new ConcurrentHashMap<CharSequence, CsmUID<CsmNamespace>>();
2135:
2136: private ClassifierContainer classifierContainer = new ClassifierContainer();
2137:
2138: // collection of sharable system macros and system includes
2139: private APTSystemStorage sysAPTData = APTSystemStorage.getDefault();
2140:
2141: private Object namespaceLock = new String(
2142: "namespaceLock in Projectbase " + hashCode()); // NOI18N
2143:
2144: private Key declarationsSorageKey;
2145: private Key fileContainerKey;
2146: private Key graphStorageKey;
2147:
2148: protected final SourceRootContainer projectRoots = new SourceRootContainer();
2149:
2150: //private NamespaceImpl fakeNamespace;
2151:
2152: // test variables.
2153: private static final boolean TRACE_PP_STATE_OUT = DebugUtils
2154: .getBoolean("cnd.dump.preproc.state", false);
2155: private static final boolean REMEMBER_RESTORED = TraceFlags.CLEAN_MACROS_AFTER_PARSE
2156: && (DebugUtils.getBoolean("cnd.remember.restored", false) || TRACE_PP_STATE_OUT);
2157: public static final int GATHERING_MACROS = 0;
2158: public static final int GATHERING_TOKENS = 1;
2159:
2160: ////////////////////////////////////////////////////////////////////////////
2161: /**
2162: * for tests only
2163: */
2164: public static List testGetRestoredFiles() {
2165: return testRestoredFiles;
2166: }
2167:
2168: private static List<String> testRestoredFiles = null;
2169:
2170: ////////////////////////////////////////////////////////////////////////////
2171:
2172: ////////////////////////////////////////////////////////////////////////////
2173: // impl of persistent
2174:
2175: public void write(DataOutput aStream) throws IOException {
2176: assert aStream != null;
2177: UIDObjectFactory aFactory = UIDObjectFactory
2178: .getDefaultFactory();
2179: assert aFactory != null;
2180: assert this .name != null;
2181: aStream.writeUTF(this .name.toString());
2182: aStream.writeUTF(RepositoryUtils.getUnitName(getUID())
2183: .toString());
2184: aFactory.writeUID(this .globalNamespaceUID, aStream);
2185: aFactory.writeStringToUIDMap(this .namespaces, aStream, false);
2186: classifierContainer.write(aStream);
2187:
2188: ProjectComponent.writeKey(fileContainerKey, aStream);
2189: ProjectComponent.writeKey(declarationsSorageKey, aStream);
2190: ProjectComponent.writeKey(graphStorageKey, aStream);
2191:
2192: PersistentUtils.writeUTF(this .uniqueName, aStream);
2193: }
2194:
2195: protected ProjectBase(DataInput aStream) throws IOException {
2196:
2197: setStatus(Status.Restored);
2198:
2199: assert aStream != null;
2200: UIDObjectFactory aFactory = UIDObjectFactory
2201: .getDefaultFactory();
2202: assert aFactory != null : "default UID factory can not be bull";
2203:
2204: this .name = ProjectNameCache.getManager().getString(
2205: aStream.readUTF());
2206: assert this .name != null : "project name can not be null";
2207:
2208: String unitName = aStream.readUTF();
2209:
2210: this .globalNamespaceUID = aFactory.readUID(aStream);
2211: assert globalNamespaceUID != null : "globalNamespaceUID can not be null";
2212:
2213: aFactory.readStringToUIDMap(this .namespaces, aStream,
2214: QualifiedNameCache.getManager());
2215: this .classifierContainer = new ClassifierContainer(aStream);
2216:
2217: fileContainerKey = ProjectComponent.readKey(aStream);
2218: assert fileContainerKey != null : "fileContainerKey can not be null";
2219:
2220: declarationsSorageKey = ProjectComponent.readKey(aStream);
2221: assert declarationsSorageKey != null : "declarationsSorageKey can not be null";
2222:
2223: graphStorageKey = ProjectComponent.readKey(aStream);
2224: assert graphStorageKey != null : "graphStorageKey can not be null";
2225:
2226: this .uniqueName = PersistentUtils.readUTF(aStream);
2227: assert uniqueName != null : "uniqueName can not be null";
2228: this .uniqueName = ProjectNameCache.getManager().getString(
2229: this .uniqueName);
2230:
2231: this .model = (ModelImpl) CsmModelAccessor.getModel();
2232: }
2233:
2234: DeclarationContainer getDeclarationsSorage() {
2235: return (DeclarationContainer) RepositoryUtils
2236: .get(declarationsSorageKey);
2237: }
2238:
2239: FileContainer getFileContainer() {
2240: FileContainer fc = (FileContainer) RepositoryUtils
2241: .get(fileContainerKey);
2242: assert fc != null : "Failed to get FileContainer by key "
2243: + fileContainerKey;
2244: return fc;
2245: }
2246:
2247: public GraphContainer getGraphStorage() {
2248: GraphContainer gc = (GraphContainer) RepositoryUtils
2249: .get(graphStorageKey);
2250: assert gc != null : "Failed to get GraphContainer by key "
2251: + graphStorageKey;
2252: return gc;
2253: }
2254: }
|