/projects/netbeans-7.3/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/core/ProjectBase.java
Java | 1075 lines | 901 code | 86 blank | 88 comment | 202 complexity | a9e093800a58cfa4025e9321228aaa5b MD5 | raw file
- /*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
- *
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
- * Other names may be trademarks of their respective owners.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License. When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * Contributor(s):
- *
- * The Original Software is NetBeans. The Initial Developer of the Original
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
- * Microsystems, Inc. All Rights Reserved.
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- */
- package org.netbeans.modules.cnd.modelimpl.csm.core;
- import java.io.File;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.io.PrintWriter;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.StringTokenizer;
- import java.util.TreeMap;
- import java.util.WeakHashMap;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.atomic.AtomicBoolean;
- import java.util.concurrent.locks.ReadWriteLock;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- import java.util.logging.Level;
- import org.netbeans.modules.cnd.antlr.collections.AST;
- import org.netbeans.modules.cnd.api.model.CsmClass;
- import org.netbeans.modules.cnd.api.model.CsmClassifier;
- import org.netbeans.modules.cnd.api.model.CsmDeclaration;
- import org.netbeans.modules.cnd.api.model.CsmFile;
- import org.netbeans.modules.cnd.api.model.CsmFriend;
- import org.netbeans.modules.cnd.api.model.CsmInheritance;
- import org.netbeans.modules.cnd.api.model.CsmModelAccessor;
- import org.netbeans.modules.cnd.api.model.CsmModelState;
- import org.netbeans.modules.cnd.api.model.CsmNamespace;
- import org.netbeans.modules.cnd.api.model.CsmOffsetableDeclaration;
- import org.netbeans.modules.cnd.api.model.CsmProject;
- import org.netbeans.modules.cnd.api.model.CsmUID;
- import org.netbeans.modules.cnd.api.model.services.CsmSelect.NameAcceptor;
- import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
- import org.netbeans.modules.cnd.api.model.util.CsmTracer;
- import org.netbeans.modules.cnd.api.model.util.UIDs;
- import org.netbeans.modules.cnd.api.project.NativeFileItem;
- import org.netbeans.modules.cnd.api.project.NativeFileItem.Language;
- import org.netbeans.modules.cnd.api.project.NativeProject;
- import org.netbeans.modules.cnd.api.project.NativeProjectItemsAdapter;
- import org.netbeans.modules.cnd.api.project.NativeProjectItemsListener;
- import org.netbeans.modules.cnd.apt.structure.APTFile;
- import org.netbeans.modules.cnd.apt.support.APTDriver;
- import org.netbeans.modules.cnd.apt.support.APTFileCacheEntry;
- import org.netbeans.modules.cnd.apt.support.APTFileCacheManager;
- import org.netbeans.modules.cnd.apt.support.APTFileSearch;
- import org.netbeans.modules.cnd.apt.support.APTHandlersSupport;
- import org.netbeans.modules.cnd.apt.support.APTIncludeHandler;
- import org.netbeans.modules.cnd.apt.support.APTIncludePathStorage;
- import org.netbeans.modules.cnd.apt.support.APTMacroMap;
- import org.netbeans.modules.cnd.apt.support.APTPreprocHandler;
- import org.netbeans.modules.cnd.apt.support.APTPreprocHandler.State;
- import org.netbeans.modules.cnd.apt.support.APTSystemStorage;
- import org.netbeans.modules.cnd.apt.support.APTWalker;
- import org.netbeans.modules.cnd.apt.support.IncludeDirEntry;
- import org.netbeans.modules.cnd.apt.support.PostIncludeData;
- import org.netbeans.modules.cnd.apt.support.StartEntry;
- import org.netbeans.modules.cnd.apt.utils.APTSerializeUtils;
- import org.netbeans.modules.cnd.apt.utils.APTUtils;
- import org.netbeans.modules.cnd.debug.CndTraceFlags;
- import org.netbeans.modules.cnd.debug.DebugUtils;
- import org.netbeans.modules.cnd.indexing.api.CndTextIndex;
- import org.netbeans.modules.cnd.modelimpl.cache.impl.WeakContainer;
- import org.netbeans.modules.cnd.modelimpl.content.project.ClassifierContainer;
- import org.netbeans.modules.cnd.modelimpl.content.project.DeclarationContainerProject;
- import org.netbeans.modules.cnd.modelimpl.content.project.FileContainer;
- import org.netbeans.modules.cnd.modelimpl.content.project.FileContainer.FileEntry;
- import org.netbeans.modules.cnd.modelimpl.content.project.GraphContainer;
- import org.netbeans.modules.cnd.modelimpl.content.project.IncludedFileContainer;
- import org.netbeans.modules.cnd.modelimpl.content.project.IncludedFileContainer.Storage;
- import org.netbeans.modules.cnd.modelimpl.content.project.ProjectComponent;
- import org.netbeans.modules.cnd.modelimpl.csm.ClassEnumBase;
- import org.netbeans.modules.cnd.modelimpl.csm.ForwardClass;
- import org.netbeans.modules.cnd.modelimpl.csm.FunctionImplEx;
- import org.netbeans.modules.cnd.modelimpl.csm.NamespaceImpl;
- import org.netbeans.modules.cnd.modelimpl.debug.Diagnostic;
- import org.netbeans.modules.cnd.modelimpl.debug.DiagnosticExceptoins;
- import org.netbeans.modules.cnd.modelimpl.debug.Terminator;
- import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
- import org.netbeans.modules.cnd.modelimpl.impl.services.FileInfoQueryImpl;
- import org.netbeans.modules.cnd.modelimpl.parser.apt.APTParseFileWalker;
- import org.netbeans.modules.cnd.modelimpl.parser.apt.APTRestorePreprocStateWalker;
- import org.netbeans.modules.cnd.modelimpl.platform.ModelSupport;
- import org.netbeans.modules.cnd.modelimpl.repository.ClassifierContainerKey;
- import org.netbeans.modules.cnd.modelimpl.repository.FileContainerKey;
- import org.netbeans.modules.cnd.modelimpl.repository.GraphContainerKey;
- import org.netbeans.modules.cnd.modelimpl.repository.KeyUtilities;
- import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
- import org.netbeans.modules.cnd.modelimpl.repository.ProjectDeclarationContainerKey;
- import org.netbeans.modules.cnd.modelimpl.repository.RepositoryUtils;
- import org.netbeans.modules.cnd.modelimpl.textcache.ProjectNameCache;
- import org.netbeans.modules.cnd.modelimpl.textcache.QualifiedNameCache;
- import org.netbeans.modules.cnd.modelimpl.trace.TraceUtils;
- import org.netbeans.modules.cnd.modelimpl.uid.LazyCsmCollection;
- import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
- import org.netbeans.modules.cnd.modelimpl.uid.UIDManager;
- import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
- import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities;
- import org.netbeans.modules.cnd.repository.api.RepositoryAccessor;
- import org.netbeans.modules.cnd.repository.spi.Key;
- import org.netbeans.modules.cnd.repository.spi.Persistent;
- import org.netbeans.modules.cnd.repository.spi.RepositoryDataInput;
- import org.netbeans.modules.cnd.repository.spi.RepositoryDataOutput;
- import org.netbeans.modules.cnd.repository.support.SelfPersistent;
- import org.netbeans.modules.cnd.spi.utils.CndFileSystemProvider;
- import org.netbeans.modules.cnd.utils.CndPathUtilitities;
- import org.netbeans.modules.cnd.utils.CndUtils;
- import org.netbeans.modules.cnd.utils.FSPath;
- import org.netbeans.modules.cnd.repository.api.CacheLocation;
- import org.netbeans.modules.cnd.utils.cache.CndFileUtils;
- import org.netbeans.spi.project.CacheDirectoryProvider;
- import org.openide.filesystems.FileObject;
- import org.openide.filesystems.FileSystem;
- import org.openide.filesystems.FileUtil;
- import org.openide.util.Cancellable;
- import org.openide.util.CharSequences;
- import org.openide.util.Lookup.Provider;
- import org.openide.util.NbBundle;
- import org.openide.util.Parameters;
- /**
- * Base class for CsmProject implementation
- * @author Dmitry Ivanov
- * @author Vladimir Kvashin
- */
- public abstract class ProjectBase implements CsmProject, Persistent, SelfPersistent, CsmIdentifiable,
- CndFileSystemProvider.CndFileSystemProblemListener {
- protected ProjectBase(ModelImpl model, FileSystem fs, NativeProject platformProject, String name) {
- this(model, fs, (Object) platformProject, name, createProjectKey(fs, platformProject));
- }
- protected ProjectBase(ModelImpl model, FileSystem fs, CharSequence platformProject, String name, CacheLocation cacheLocation) {
- this(model, fs, (Object) platformProject, name, createProjectKey(fs, platformProject, cacheLocation));
- }
- /** Creates a new instance of CsmProjectImpl */
- private ProjectBase(ModelImpl model, FileSystem fs, Object platformProject, String name, Key key) {
- namespaces = new ConcurrentHashMap<CharSequence, CsmUID<CsmNamespace>>();
- this.uniqueName = getUniqueName(fs, platformProject);
- RepositoryUtils.openUnit(key);
- unitId = key.getUnitId();
- cacheLocation = RepositoryAccessor.getTranslator().getCacheLocation(unitId);
- setStatus(Status.Initial);
- this.name = ProjectNameCache.getManager().getString(name);
- this.fileSystem = fs;
- init(model, platformProject);
- sysAPTData = APTSystemStorage.getInstance();
- userPathStorage = new APTIncludePathStorage();
- declarationsSorageKey = new ProjectDeclarationContainerKey(unitId);
- weakDeclarationContainer = new WeakContainer<DeclarationContainerProject>(this, declarationsSorageKey);
- classifierStorageKey = new ClassifierContainerKey(unitId);
- weakClassifierContainer = new WeakContainer<ClassifierContainer>(this, classifierStorageKey);
- fileContainerKey = new FileContainerKey(unitId);
- weakFileContainer = new WeakContainer<FileContainer>(this, fileContainerKey);
- graphStorageKey = new GraphContainerKey(unitId);
- weakGraphContainer = new WeakContainer<GraphContainer>(this, graphStorageKey);
- includedFileContainer = new IncludedFileContainer(this);
- initFields();
- }
- /*package*/final void initFields() {
- NamespaceImpl ns = NamespaceImpl.create(this, false);
- assert ns != null;
- this.globalNamespaceUID = UIDCsmConverter.namespaceToUID(ns);
- DeclarationContainerProject declarationContainer = new DeclarationContainerProject(this);
- CndUtils.assertTrue(declarationsSorageKey.equals(declarationContainer.getKey()));
- weakDeclarationContainer.clear();
- ClassifierContainer classifierContainer = new ClassifierContainer(this);
- CndUtils.assertTrue(classifierStorageKey.equals(classifierContainer.getKey()));
- weakClassifierContainer.clear();
- FileContainer fileContainer = new FileContainer(this);
- CndUtils.assertTrue(fileContainerKey.equals(fileContainer.getKey()));
- weakFileContainer.clear();
- GraphContainer graphContainer = new GraphContainer(this);
- CndUtils.assertTrue(graphStorageKey.equals(graphContainer.getKey()));
- weakGraphContainer.clear();
- includedFileContainer.clear();
- FAKE_GLOBAL_NAMESPACE = NamespaceImpl.create(this, true);
- }
- private void init(ModelImpl model, Object platformProject) {
- this.model = model;
- assert (platformProject instanceof NativeProject) || (platformProject instanceof CharSequence);
- this.platformProject = platformProject;
- // remember in repository
- RepositoryUtils.hang(this);
- // create global namespace
- if (TraceFlags.CLOSE_AFTER_PARSE) {
- Terminator.create(this);
- }
- }
- private boolean checkConsistency(boolean restoring) {
- long time = TraceFlags.TIMING ? System.currentTimeMillis() : 0;
- if (getFileContainer() == FileContainer.empty()) {
- return false;
- }
- if (getDeclarationsSorage() == DeclarationContainerProject.empty()) {
- return false;
- }
- if (getGraph() == GraphContainer.empty()) {
- return false;
- }
- if (getGlobalNamespace() == FAKE_GLOBAL_NAMESPACE) {
- return false;
- }
- if (TraceFlags.TIMING || CndUtils.isUnitTestMode()) {
- if (TraceFlags.TIMING) {
- System.err.printf("Consistency check took %d ms\n", System.currentTimeMillis() - time);
- }
- time = System.currentTimeMillis();
- checkFileContainerConsistency(restoring);
- if (TraceFlags.TIMING) {
- System.err.printf("File Container Consistency check took %d ms\n", System.currentTimeMillis() - time);
- }
- }
- return true;
- }
- private void checkFileContainerConsistency(boolean restoring) {
- if (this.isArtificial()) {
- return;
- }
- Set<FileImpl> allFileImpls = new HashSet<FileImpl>(this.getAllFileImpls());
- Storage storageForSelf = this.includedFileContainer.getStorageForProject(this);
- if (storageForSelf != null) {
- for (Map.Entry<CharSequence, FileEntry> entry : storageForSelf.getInternalMap().entrySet()) {
- FileImpl file = getFileContainer().getFile(entry.getKey(), true);
- if (file == null || !allFileImpls.contains(file)) {
- CndUtils.assertTrueInConsole(false, "no file enty for included file ", entry);
- }
- }
- }
- for (FileImpl fileImpl : allFileImpls) {
- checkFileEntryConsistency(fileImpl, restoring);
- }
- }
- private void checkFileEntryConsistency(FileImpl fileImpl, boolean restoring) {
- CharSequence fileKey = fileImpl.getAbsolutePath();
- FileImpl.State fileState = fileImpl.getState();
- FileEntry entry = getFileContainer().getEntry(fileKey);
- if (entry != null) {
- Object lock = entry.getLock();
- synchronized (lock) {
- List<PreprocessorStatePair> fcPairs = new ArrayList<PreprocessorStatePair>(entry.getStatePairs());
- if (fcPairs.isEmpty() && fileState != FileImpl.State.INITIAL) {
- CndUtils.assertTrueInConsole(false, "no states for own file ", fileImpl);
- }
- boolean hasParsing = false;
- Boolean hasValid = fcPairs.isEmpty() ? Boolean.TRUE : null;
- // check own File Container and remember what we have found for checking own includes files
- // from includedFileContainer later
- for (PreprocessorStatePair fcPair : fcPairs) {
- if (fileState == FileImpl.State.PARSED) {
- CndUtils.assertTrueInConsole(fcPair.state.isValid(), "FC Should not contain invalid ", fcPair);
- CndUtils.assertTrueInConsole(fcPair.pcState != FilePreprocessorConditionState.PARSING, "FC Should not contain PARSING ", fcPair);
- }
- if (fcPair.pcState == FilePreprocessorConditionState.PARSING) {
- hasParsing = true;
- }
- if (hasValid == null) {
- hasValid = fcPair.state.isValid();
- }
- CndUtils.assertTrueInConsole(hasValid == fcPair.state.isValid(), "FC Should not contain " + hasValid, fcPair);
- }
- CsmUID<CsmFile> testFileUID = entry.getTestFileUID();
- FileImpl testFileImpl = (FileImpl) UIDCsmConverter.UIDtoFile(testFileUID);
- if (!testFileImpl.equals(fileImpl)) {
- CndUtils.assertTrueInConsole(false, "different files: " + fileImpl, testFileImpl);
- }
- // check if input file was included by 'this' project
- FileEntry includedFileEntry = this.includedFileContainer.getIncludedFileEntry(lock, this, fileKey);
- if (includedFileEntry != null) {
- // it was included => check in which states it was included from 'this' project
- List<PreprocessorStatePair> inclPairs = new ArrayList<PreprocessorStatePair>(includedFileEntry.getStatePairs());
- if (inclPairs.isEmpty()) {
- CndUtils.assertTrueInConsole(false, "no included states for included file ", fileImpl);
- } else {
- for (PreprocessorStatePair inclPair : inclPairs) {
- if (fileState == FileImpl.State.PARSED) {
- CndUtils.assertTrueInConsole(inclPair.state.isValid(), "Should not contain invalid ", inclPair);
- CndUtils.assertTrueInConsole(inclPair.pcState != FilePreprocessorConditionState.PARSING, "Should not contain PARSING ", inclPair);
- }
- // check that any own include files are contributing in own FC container the same way
- List<PreprocessorStatePair> statesToKeep = new ArrayList<PreprocessorStatePair>(4);
- AtomicBoolean newStateFound = new AtomicBoolean();
- ComparisonResult resultPP;
- resultPP = fillStatesToKeepBasedOnPPState(inclPair.state, fcPairs, statesToKeep, newStateFound);
- if (inclPair.state.isValid()) {
- if (resultPP != ComparisonResult.KEEP_WITH_OTHERS) {
- CndUtils.assertTrueInConsole(false, "Should not contribute [" + restoring + "," + hasParsing + "] " + newStateFound + " " + resultPP + " pair into File Container (state based) " + inclPair + "vs.\n", fcPairs);
- }
- } else {
- CndUtils.assertTrueInConsole(resultPP == ComparisonResult.DISCARD && !hasValid, "Should not contribute invalid [" + restoring + "," + hasParsing + "] " + newStateFound + " " + resultPP + " pair into File Container (state based) " + inclPair + "vs.\n", fcPairs);
- }
- // check that any own include files are contributing has not worse PC state in own FC container
- ComparisonResult resultPC = fillStatesToKeepBasedOnPCState(inclPair.pcState, fcPairs, statesToKeep);
- if (resultPC != ComparisonResult.DISCARD) {
- CndUtils.assertTrueInConsole(inclPair.pcState == FilePreprocessorConditionState.PARSING && hasParsing, "Should not contribute [" + restoring + "," + hasParsing + "] " + newStateFound + " " + resultPC + " pair into File Container (PCState based) " + inclPair, fcPairs);
- }
- }
- }
- }
- }
- } else {
- CndUtils.assertTrueInConsole(false, "no entry for ", fileKey);
- }
- }
- private void setStatus(Status newStatus) {
- //System.err.printf("CHANGING STATUS %s -> %s for %s (%s)\n", status, newStatus, name, getClass().getName());
- status = newStatus;
- }
- protected static void cleanRepository(FileSystem fs, NativeProject platformProject, boolean articicial) {
- Key key = createProjectKey(fs, platformProject);
- RepositoryUtils.closeUnit(key, null, true);
- }
- protected static void cleanRepository(FileSystem fs, CharSequence platformProject, boolean articicial, CacheLocation cacheLocation) {
- Key key = createProjectKey(fs, platformProject, cacheLocation);
- RepositoryUtils.closeUnit(key, null, true);
- }
- private static Key createProjectKey(FileSystem fs, NativeProject platfProj) {
- return KeyUtilities.createProjectKey(getUniqueName(fs, platfProj), ProjectBase.getCacheLocation(platfProj));
- }
- private static Key createProjectKey(FileSystem fs, CharSequence platfProj, CacheLocation cacheLocation) {
- return KeyUtilities.createProjectKey(getUniqueName(fs, platfProj), cacheLocation);
- }
- protected static ProjectBase readInstance(ModelImpl model, FileSystem fs, NativeProject platformProject, String name) {
- return readInstance(model, createProjectKey(fs, platformProject), platformProject, name);
- }
- protected static ProjectBase readInstance(ModelImpl model, FileSystem fs, CharSequence platformProject, String name, CacheLocation cacheLocation) {
- ProjectBase instance = readInstance(model, createProjectKey(fs, platformProject, cacheLocation), platformProject, name);
- return instance;
- }
- private static ProjectBase readInstance(ModelImpl model, Key key, Object platformProject, String name) {
- long time = 0;
- if (TraceFlags.TIMING) {
- System.err.printf("Project %s: instantiating...\n", name);
- time = System.currentTimeMillis();
- }
- assert TraceFlags.PERSISTENT_REPOSITORY;
- RepositoryUtils.openUnit(key);
- Persistent o = RepositoryUtils.get(key);
- if (o != null) {
- assert o instanceof ProjectBase;
- ProjectBase impl = (ProjectBase) o;
- CharSequence aName = ProjectNameCache.getManager().getString(name);
- if (!impl.name.equals(aName)) {
- impl.setName(aName);
- }
- impl.init(model, platformProject);
- if (TraceFlags.TIMING) {
- time = System.currentTimeMillis() - time;
- System.err.printf("Project %s: loaded. %d ms\n", name, time);
- }
- UIDManager.instance().clearProjectCache(key);
- if (impl.checkConsistency(true)) {
- return impl;
- }
- }
- return null;
- }
- @Override
- public final CsmNamespace getGlobalNamespace() {
- return _getGlobalNamespace();
- }
- @Override
- public final CharSequence getName() {
- return name;
- }
- protected final void setName(CharSequence name) {
- this.name = name;
- }
- /**
- * Returns a string that uniquely identifies this project.
- * One should never rely on this name structure,
- * just use it as in unique identifier
- */
- public final CharSequence getUniqueName() {
- return uniqueName;
- }
- public static CharSequence getUniqueName(NativeProject platformProject) {
- return getUniqueName(platformProject.getFileSystem(), platformProject);
- }
- public final CacheLocation getCacheLocation() {
- return cacheLocation;
- }
- public static CacheLocation getCacheLocation(NativeProject project) {
- assert project != null;
- Provider lp = project.getProject();
- if (lp != null) {
- CacheDirectoryProvider loc = lp.getLookup().lookup(CacheDirectoryProvider.class);
- if (loc != null) {
- try {
- FileObject cacheDir = loc.getCacheDirectory();
- if (cacheDir != null) {
- File cacheDirFile = FileUtil.toFile(cacheDir);
- if (cacheDirFile != null) {
- return new CacheLocation(new File(cacheDirFile, "cnd/model")); //NOI18N
- }
- }
- } catch (IOException ex) {
- ex.printStackTrace(System.err);
- }
- }
- }
- return CacheLocation.DEFAULT;
- }
- @Override
- public String getDisplayName() {
- if (CndFileUtils.isLocalFileSystem(fileSystem)) {
- return name.toString();
- } else {
- return NbBundle.getMessage(getClass(), "ProjectDisplayName", name, fileSystem.getDisplayName());
- }
- }
- @Override
- public String getHtmlDisplayName() {
- if (CndFileUtils.isLocalFileSystem(fileSystem)) {
- return name.toString();
- } else {
- return NbBundle.getMessage(getClass(), "ProjectHtmlDisplayName", name, fileSystem.getDisplayName());
- }
- }
- public static CharSequence getUniqueName(FileSystem fs, Object platformProject) {
- Parameters.notNull("FileSystem", fs); //NOI18N
- String postfix = CndFileUtils.isLocalFileSystem(fs) ? "" : fs.getDisplayName();
- String result;
- if (platformProject instanceof NativeProject) {
- result = ((NativeProject) platformProject).getProjectRoot() + "/N/" + postfix; // NOI18N
- } else if (platformProject instanceof CharSequence) {
- result = ((CharSequence)platformProject).toString() + "/L/" + postfix; // NOI18N
- } else if (platformProject == null) {
- throw new IllegalArgumentException("Incorrect platform project: null"); // NOI18N
- } else {
- throw new IllegalArgumentException("Incorrect platform project class: " + platformProject.getClass()); // NOI18N
- }
- return ProjectNameCache.getManager().getString(result);
- }
-
- /** Gets an object, which represents correspondent IDE project */
- @Override
- public final Object getPlatformProject() {
- assert (platformProject == null) || (platformProject instanceof NativeProject) || (platformProject instanceof CharSequence);
- return platformProject;
- }
- /** Gets an object, which represents correspondent IDE project */
- protected final void setPlatformProject(CharSequence platformProject) {
- setPlatformProjectImpl(platformProject);
- }
- protected final void setPlatformProject(NativeProject platformProject) {
- setPlatformProjectImpl(platformProject);
- }
- private void setPlatformProjectImpl(Object platformProject) {
- assert (platformProject == null) || (platformProject instanceof NativeProject) || (platformProject instanceof CharSequence);
- CndUtils.assertTrue(this.platformProject == null);
- CndUtils.assertNotNull(platformProject, "Passing null project for ", this);
- this.platformProject = platformProject;
- checkUniqueNameConsistency();
- }
-
- private void checkUniqueNameConsistency() {
- if (CndUtils.isDebugMode()) {
- CharSequence expectedUniqueName = getUniqueName(fileSystem, platformProject);
- CharSequence defactoUniqueName = this.uniqueName;
- if (!defactoUniqueName.equals(expectedUniqueName)) {
- CndUtils.assertTrue(false,
- "Existing project unique name differ: " + defactoUniqueName + " - expected " + expectedUniqueName + //NOI18N
- " Cache location " + cacheLocation); //NOI18N
- }
- }
- }
- /** Finds namespace by its qualified name */
- public final CsmNamespace findNamespace(CharSequence qualifiedName, boolean findInLibraries) {
- CsmNamespace result = findNamespace(qualifiedName);
- if (result == null && findInLibraries) {
- for (Iterator<CsmProject> it = getLibraries().iterator(); it.hasNext();) {
- CsmProject lib = it.next();
- result = lib.findNamespace(qualifiedName);
- if (result != null) {
- break;
- }
- }
- }
- return result;
- }
- /** Finds namespace by its qualified name */
- @Override
- public final CsmNamespace findNamespace(CharSequence qualifiedName) {
- CsmNamespace nsp = _getNamespace(qualifiedName);
- return nsp;
- }
- private static String getNestedNamespaceQualifiedName(CharSequence name, NamespaceImpl parent, boolean createForEmptyNames) {
- StringBuilder sb = new StringBuilder(name);
- if (parent != null) {
- if (name.length() == 0 && createForEmptyNames) {
- sb.append(parent.getNameForUnnamedElement());
- }
- if (!parent.isGlobal()) {
- sb.insert(0, "::"); // NOI18N
- sb.insert(0, parent.getQualifiedName());
- }
- }
- return sb.toString();
- }
- public final NamespaceImpl findNamespaceCreateIfNeeded(NamespaceImpl parent, CharSequence name) {
- synchronized (namespaceLock) {
- String qualifiedName = ProjectBase.getNestedNamespaceQualifiedName(name, parent, true);
- NamespaceImpl nsp = _getNamespace(qualifiedName);
- if (nsp == null) {
- nsp = NamespaceImpl.create(this, parent, name.toString(), qualifiedName);
- }
- return nsp;
- }
- }
- public final void registerNamespace(NamespaceImpl namespace) {
- _registerNamespace(namespace);
- }
- public final void unregisterNamesace(NamespaceImpl namespace) {
- _unregisterNamespace(namespace);
- }
- public final CsmClassifier findClassifier(CharSequence qualifiedName, boolean findInLibraries) {
- CsmClassifier result = findClassifier(qualifiedName);
- if (result == null && findInLibraries) {
- for (Iterator<CsmProject> it = getLibraries().iterator(); it.hasNext();) {
- CsmProject lib = it.next();
- result = lib.findClassifier(qualifiedName);
- if (result != null) {
- break;
- }
- }
- }
- return result;
- }
- @Override
- public final CsmClassifier findClassifier(CharSequence qualifiedName) {
- CsmClassifier result = getClassifierSorage().getClassifier(qualifiedName);
- return result;
- }
- @Override
- public final Collection<CsmClassifier> findClassifiers(CharSequence qualifiedName) {
- CsmClassifier result = getClassifierSorage().getClassifier(qualifiedName);
- Collection<CsmClassifier> out = new ArrayList<CsmClassifier>();
- //Collection<CsmClassifier> out = new LazyCsmCollection<CsmClassifier, CsmClassifier>(new ArrayList<CsmUID<CsmClassifier>>(), TraceFlags.SAFE_UID_ACCESS);
- if (result != null) {
- if (CsmKindUtilities.isBuiltIn(result)) {
- return Collections.<CsmClassifier>singletonList(result);
- }
- CharSequence[] allClassifiersUniqueNames = Utils.getAllClassifiersUniqueNames(result.getUniqueName());
- Collection<CsmClassifier> fwds = new ArrayList<CsmClassifier>(1);
- for (CharSequence curUniqueName : allClassifiersUniqueNames) {
- Collection<? extends CsmDeclaration> decls = this.findDeclarations(curUniqueName);
- @SuppressWarnings("unchecked")
- Collection<CsmClassifier> classifiers = (Collection<CsmClassifier>) decls;
- for (CsmClassifier csmClassifier : classifiers) {
- if (ForwardClass.isForwardClass(csmClassifier)) {
- fwds.add(csmClassifier);
- } else {
- out.add(csmClassifier);
- }
- }
- }
- // All forwards move at the end
- out.addAll(fwds);
- }
- return out;
- }
- @Override
- public final Collection<CsmInheritance> findInheritances(CharSequence name) {
- return getClassifierSorage().getInheritances(name);
- }
- @Override
- public final CsmDeclaration findDeclaration(CharSequence uniqueName) {
- return getDeclarationsSorage().getDeclaration(uniqueName);
- }
- @Override
- public final Collection<CsmOffsetableDeclaration> findDeclarations(CharSequence uniqueName) {
- return getDeclarationsSorage().findDeclarations(uniqueName);
- }
- public final Collection<CsmOffsetableDeclaration> findDeclarationsByPrefix(String uniquNamePrefix) {
- // To improve performance use char(255) instead real Character.MAX_VALUE
- char maxChar = 255; //Character.MAX_VALUE;
- return getDeclarationsSorage().getDeclarationsRange(uniquNamePrefix, uniquNamePrefix + maxChar); // NOI18N
- }
- public final Collection<CsmFriend> findFriendDeclarations(CsmOffsetableDeclaration decl) {
- return getDeclarationsSorage().findFriends(decl);
- }
- public final boolean registerDeclaration(CsmOffsetableDeclaration decl) {
- if (!Utils.canRegisterDeclaration(decl)) {
- if (TraceFlags.TRACE_REGISTRATION) {
- traceRegistration("not registered decl " + decl + " UID " + UIDs.get(decl)); //NOI18N
- }
- return false;
- }
- if (CsmKindUtilities.isClass(decl) || CsmKindUtilities.isEnum(decl)) {
- ClassEnumBase<?> cls = (ClassEnumBase<?>) decl;
- CharSequence qname = cls.getQualifiedName();
- synchronized (classifierReplaceLock) {
- CsmClassifier old = getClassifierSorage().getClassifier(qname);
- if (old != null) {
- // don't register if the new one is weaker
- if (cls.shouldBeReplaced(old)) {
- if (TraceFlags.TRACE_REGISTRATION) {
- traceRegistration("not registered decl " + decl + " UID " + UIDs.get(decl)); //NOI18N
- }
- return false;
- }
- // remove the old one if the new one is stronger
- if ((old instanceof ClassEnumBase<?>) && ((ClassEnumBase<?>) old).shouldBeReplaced(cls)) {
- if (TraceFlags.TRACE_REGISTRATION) {
- System.err.println("disposing old decl " + old + " UID " + UIDs.get(decl)); //NOI18N
- }
- ((ClassEnumBase<?>) old).dispose();
- }
- }
- getDeclarationsSorage().putDeclaration(decl);
- getClassifierSorage().putClassifier((CsmClassifier) decl);
- }
- } else if (CsmKindUtilities.isTypedef(decl)) { // isClassifier(decl) or isTypedef(decl) ??
- getDeclarationsSorage().putDeclaration(decl);
- getClassifierSorage().putClassifier((CsmClassifier) decl);
- } else {
- // only classes, enums and typedefs are registered as classifiers;
- // even if you implement CsmClassifier, this doesn't mean you atomatically get there ;)
- getDeclarationsSorage().putDeclaration(decl);
- }
- if (TraceFlags.TRACE_REGISTRATION) {
- System.err.println("registered " + decl + " UID " + UIDs.get(decl)); //NOI18N
- }
- return true;
- }
- public final void unregisterDeclaration(CsmOffsetableDeclaration decl) {
- if (TraceFlags.TRACE_REGISTRATION) {
- traceRegistration("unregistered " + decl + " UID " + UIDs.get(decl)); //NOI18N
- }
- if (decl instanceof CsmClassifier) {
- getClassifierSorage().removeClassifier(decl);
- }
- getDeclarationsSorage().removeDeclaration(decl);
- }
- private static void traceRegistration(String text) {
- assert TraceFlags.TRACE_REGISTRATION : "TraceFlags.TRACE_REGISTRATION should be checked *before* call !"; //NOI18N
- System.err.printf("registration: %s\n", text);
- }
- @Override
- public final void waitParse() {
- boolean insideParser = ParserThreadManager.instance().isParserThread();
- if (insideParser) {
- new Throwable("project.waitParse should NEVER be called in parser thread !!!").printStackTrace(System.err); // NOI18N
- }
- if (insideParser) {
- return;
- }
- ensureFilesCreated();
- ensureChangedFilesEnqueued();
- model.waitModelTasks();
- waitParseImpl();
- }
- private void waitParseImpl() {
- synchronized (waitParseLock) {
- while (ParserQueue.instance().hasPendingProjectRelatedWork(this, null)) {
- try {
- //FIXUP - timeout is a workaround for #146436 hang on running unit tests
- waitParseLock.wait(10000);
- } catch (InterruptedException ex) {
- // do nothing
- }
- }
- }
- }
- protected void ensureChangedFilesEnqueued() {
- }
- /**
- * @param skipFile if null => check all files, otherwise skip checking
- * this file
- *
- */
- protected boolean hasChangedFiles(CsmFile skipFile) {
- return false;
- }
- protected boolean hasEditedFiles() {
- return false;
- }
- private Set<FileSystem> getIncludesFileSystems(NativeProject nativeProject) {
- Set<FileSystem> fileSystems = new HashSet<FileSystem>();
- for (FSPath fsPath : nativeProject.getSystemIncludePaths()) {
- fileSystems.add(fsPath.getFileSystem());
- }
- return fileSystems;
- }
-
- @Override
- public void problemOccurred(FSPath fsPath) {
- synchronized (fileSystemProblemsLock) {
- hasFileSystemProblems = true;
- }
- }
- @Override
- public void recovered(FileSystem fileSystem) {
- boolean prev;
- synchronized (fileSystemProblemsLock) {
- prev = hasFileSystemProblems;
- hasFileSystemProblems = false;
- }
- if (prev) {
- ModelImpl.instance().scheduleReparse(Collections.<CsmProject>singleton(this));
- }
- }
- public final void enableProjectListeners(boolean enable) {
- synchronized (projectListenerLock) {
- if (projectListener != null) {
- projectListener.enableListening(enable);
- }
- }
- }
- protected final void registerProjectListeners() {
- synchronized (projectListenerLock) {
- if (platformProject instanceof NativeProject) {
- if (projectListener == null) {
- projectListener = new NativeProjectListenerImpl(getModel(), (NativeProject) platformProject, this);
- }
- NativeProject nativeProject = (NativeProject) platformProject;
- nativeProject.addProjectItemsListener(projectListener);
- for (FileSystem fs : getIncludesFileSystems(nativeProject)) {
- CndFileSystemProvider.addFileSystemProblemListener(this, fs);
- }
- }
- }
- }
- protected final void unregisterProjectListeners() {
- synchronized (projectListenerLock) {
- if (projectListener != null) {
- if (platformProject instanceof NativeProject) {
- NativeProject nativeProject = (NativeProject) platformProject;
- nativeProject.removeProjectItemsListener(projectListener);
- for (FileSystem fs : getIncludesFileSystems(nativeProject)) {
- CndFileSystemProvider.removeFileSystemProblemListener(this, fs);
- }
- }
- projectListener = null;
- }
- }
- }
- /*package*/ final void scheduleReparse() {
- ensureFilesCreated();
- DeepReparsingUtils.reparseOnEdit(this.getAllFileImpls(), this, true);
- }
- private final Object fileCreateLock = new Object();
-
- protected void ensureFilesCreated() {
- if (status == Status.Ready) {
- return;
- }
- boolean notify = false;
- try {
- synchronized (fileCreateLock) {
- if (status == Status.Initial || status == Status.Restored) {
- try {
- setStatus((status == Status.Initial) ? Status.AddingFiles : Status.Validating);
- long time = 0;
- if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
- System.err.println("suspend queue");
- ParserQueue.instance().suspend();
- if (TraceFlags.TIMING) {
- time = System.currentTimeMillis();
- }
- }
- ParserQueue.instance().onStartAddingProjectFiles(this);
- notify = true;
- registerProjectListeners();
- NativeProject nativeProject = ModelSupport.getNativeProject(platformProject);
- if (nativeProject != null) {
- try {
- ParserQueue.instance().suspend();
- createProjectFilesIfNeed(nativeProject);
- } finally {
- ParserQueue.instance().resume();
- }
- }
- if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
- if (TraceFlags.TIMING) {
- time = System.currentTimeMillis() - time;
- System.err.println("getting files from project system + put in queue took " + time + "ms");
- }
- System.err.println("sleep for " + TraceFlags.SUSPEND_PARSE_TIME + "sec before resuming queue");
- sleep(TraceFlags.SUSPEND_PARSE_TIME * 1000);
- }
- } finally {
- if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
- System.err.println("woke up after sleep");
- ParserQueue.instance().resume();
- }
- setStatus(Status.Ready);
- }
- }
- }
- } finally {
- if (notify) {
- ParserQueue.instance().onEndAddingProjectFiles(this);
- }
- }
- }
-
- private void sleep(int millisec) {
- try {
- Thread.sleep(millisec);
- } catch (InterruptedException ex) {
- // do nothing
- }
- }
- private void createProjectFilesIfNeed(NativeProject nativeProject) {
- if (TraceFlags.TIMING) {
- System.err.printf("\n\nGetting files from project system for %s...\n", getName());
- }
- if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
- try {
- System.err.println("sleep for " + TraceFlags.SUSPEND_PARSE_TIME + "sec before getting files from project");
- Thread.sleep(TraceFlags.SUSPEND_PARSE_TIME * 1000);
- System.err.println("woke up after sleep");
- } catch (InterruptedException ex) {
- // do nothing
- }
- }
- long time = System.currentTimeMillis();
- final Set<NativeFileItem> removedFileItems = Collections.synchronizedSet(new HashSet<NativeFileItem>());
- final Set<NativeFileItem> readOnlyRemovedFilesSet = Collections.unmodifiableSet(removedFileItems);
- NativeProjectItemsListener projectItemListener = new NativeProjectItemsAdapter() {
- @Override
- public void filesRemoved(List<NativeFileItem> fileItems) {
- removedFileItems.addAll(fileItems);
- }
- @Override
- public void filesPropertiesChanged(List<NativeFileItem> fileItems) {
- for (NativeFileItem item : fileItems) {
- if (item.isExcluded()) {
- removedFileItems.add(item);
- }
- }
- }
-
- };
- nativeProject.addProjectItemsListener(projectItemListener);
- List<NativeFileItem> sources = new ArrayList<NativeFileItem>();
- List<NativeFileItem> headers = new ArrayList<NativeFileItem>();
- for (NativeFileItem item : nativeProject.getAllFiles()) {
- if (!item.isExcluded()) {
- switch (item.getLanguage()) {
- case C:
- case CPP:
- case FORTRAN:
- sources.add(item);
- break;
- case C_HEADER:
- headers.add(item);
- break;
- default:
- break;
- }
- } else {
- switch (item.getLanguage()) {
- case C:
- case CPP:
- case FORTRAN:
- removedFileItems.add(item);
- break;
- default:
- break;
- }
- }
- }
- if (TraceFlags.TIMING) {
- time = System.currentTimeMillis() - time;
- System.err.printf("Getting files from project system took %d ms for %s\n", time, getName());
- System.err.printf("FILES COUNT for %s:\nSource files:\t%d\nHeader files:\t%d\nTotal files:\t%d\n",
- getName(), sources.size(), headers.size(), sources.size() + headers.size());
- time = System.currentTimeMillis();
- }
- if (TraceFlags.SUSPEND_PARSE_TIME != 0) {
- try {
- System.err.println("sleep for " + TraceFlags.SUSPEND_PARSE_TIME + "sec after getting files from project");
- Thread.sleep(TraceFlags.SUSPEND_PARSE_TIME * 1000);
- System.err.println("woke up after sleep");
- } catch (InterruptedException ex) {
- // do nothing
- }
- }
- if (TraceFlags.DUMP_PROJECT_ON_OPEN) {
- ModelSupport.dumpNativeProject(nativeProject);
- }
- try {
- disposeLock.readLock().lock();
- if (TraceFlags.TIMING) {
- time = System.currentTimeMillis() - time;
- System.err.printf("Waited on disposeLock: %d ms for %s\n", time, getName());
- time = System.currentTimeMillis();
- }
- if (isDisposing()) {
- if (TraceFlags.TRACE_MODEL_STATE) {
- System.err.printf("filling parser queue interrupted for %s\n", getName());
- }
- return;
- }
- ProjectSettingsValidator validator = null;
- if (status == Status.Validating) {
- validator = new ProjectSettingsValidator(this);
- validator.restoreSettings();
- }
- if (status == Status.Validating && RepositoryUtils.getRepositoryErrorCount(this) > 0){
- System.err.println("Clean index for project \""+getUniqueName()+"\" because index was corrupted (was "+RepositoryUtils.getRepositoryErrorCount(this)+" errors)."); // NOI18N
- validator = null;
- reopenUnit();
- }
- getProjectRoots().fixFolder(nativeProject.getProjectRoot());
- for (String root : nativeProject.getSourceRoots()) {
- getProjectRoots().fixFolder(root);
- }
- getProjectRoots().addSources(sources);
- getProjectRoots().addSources(headers);
- getProjectRoots().addSources(removedFileItems);
- checkConsistency(false);
- CreateFilesWorker worker = new CreateFilesWorker(this, readOnlyRemovedFilesSet, validator);
- worker.createProjectFilesIfNeed(sources, true);
- if (status != Status.Validating || RepositoryUtils.getRepositoryErrorCount(this) == 0){
- worker.createProjectFilesIfNeed(headers, false);
- }
- if (status == Status.Validating && RepositoryUtils.getRepositoryErrorCount(this) > 0){
- if (!TraceFlags.DEBUG_BROKEN_REPOSITORY) {
- System.err.println("Clean index for project \""+getUniqueName()+"\" because index was corrupted (was "+RepositoryUtils.getRepositoryErrorCount(this)+" errors)."); // NOI18N
- }
- reopenUnit();
- // reset worker to create files without validator
- validator = null;
- worker = new CreateFilesWorker(this, readOnlyRemovedFilesSet, null);
- worker.createProjectFilesIfNeed(sources, true);
- worker.createProjectFilesIfNeed(headers, false);
- }
- worker.checkLibraries();
- checkConsistency(validator != null);
- worker.finishProjectFilesCreation();
- checkConsistency(false);
- } finally {
- disposeLock.readLock().unlock();
- if (TraceFlags.TIMING) {
- time = System.currentTimeMillis() - time;
- System.err.printf("FILLING PARSER QUEUE took %d ms for %s\n", time, getName());
- }
- }
- nativeProject.removeProjectItemsListener(projectItemListener);
- // in fact if visitor used for parsing => visitor will parse all included files
- // recursively starting from current source file
- // so, when we visit headers, they should not be reparsed if already were parsed
- }
- private void reopenUnit() {
- setStatus(Status.Initial);
- ParserQueue.insta