diff options
Diffstat (limited to 'core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser')
12 files changed, 1549 insertions, 0 deletions
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java new file mode 100644 index 00000000000..90dadd6971c --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.core.browser.TypeInfo; +import org.eclipse.core.runtime.IPath; + +public class TypeCache { + + private static final int INITIAL_FILE_COUNT= 100; + private static final int INITIAL_TYPE_COUNT= INITIAL_FILE_COUNT*20; + private final Map fFileMap= new HashMap(INITIAL_FILE_COUNT); + private final Map fTypeMap= new HashMap(INITIAL_TYPE_COUNT); + private boolean fIsDirty= true; + + private static final class TypeReference { + private TypeInfo fRealInfo= null; + private Set fPaths= new HashSet(1); + + public TypeReference(TypeInfo info, IPath path) { + fRealInfo= info; + fPaths.add(path); + } + + public TypeInfo getInfo() { + return fRealInfo; + } + + public void addPath(IPath path) { + fPaths.add(path); + } + + public void removePath(IPath path) { + fPaths.remove(path); + } + + public Collection getPaths() { + return fPaths; + } + }; + + public TypeCache() { + } + + public synchronized void markAsDirty(boolean dirty) { + fIsDirty= dirty; + } + + public synchronized boolean isDirty() { + return fIsDirty; + } + + public synchronized Set getAllFiles() { + return fFileMap.keySet(); + } + + public synchronized Set getAllTypes() { + return fTypeMap.keySet(); + } + + private TypeInfo addTypeReference(TypeInfo info, IPath path) { + // we use info as a key here. the actual value found in + // the map corresponds to the 'real' TypeInfo object with + // the same hashCode + TypeReference typeRef= (TypeReference) fTypeMap.get(info); + if (typeRef == null) { + // add this type to cache + typeRef= new TypeReference(info, path); + fTypeMap.put(info, typeRef); + } else if (typeRef.getInfo() != info) { + typeRef.addPath(path); + } + return typeRef.getInfo(); + } + + private void removeTypeReference(TypeInfo info, IPath path) { + // we use info as a key here. the actual value found in + // the map corresponds to the 'real' TypeInfo object with + // the same hashCode + TypeReference typeRef= (TypeReference) fTypeMap.get(info); + if (typeRef == null) + return; + + typeRef.removePath(path); + for (Iterator i= typeRef.getPaths().iterator(); i.hasNext(); ) { + IPath p= (IPath) i.next(); + fFileMap.remove(p); + } + fTypeMap.remove(info); + } + + public synchronized void insert(IPath path, Collection types) { + Collection typeSet= (Collection) fFileMap.get(path); + if (typeSet == null) + typeSet= new ArrayList(types.size()); + for (Iterator typesIter= types.iterator(); typesIter.hasNext(); ) { + TypeInfo info= (TypeInfo)typesIter.next(); + TypeInfo newType= addTypeReference(info, path); + typeSet.add(newType); + } + fFileMap.put(path, typeSet); + } + + public synchronized boolean contains(IPath path) { + return fFileMap.containsKey(path); + } + + public synchronized void flush(IPath path) { + Collection typeSet= (Collection) fFileMap.get(path); + if (typeSet != null) { + for (Iterator typesIter= typeSet.iterator(); typesIter.hasNext(); ) { + TypeInfo info= (TypeInfo)typesIter.next(); + removeTypeReference(info, path); + } + fFileMap.remove(path); + } + fIsDirty= true; + } + + public synchronized void flush(Set paths) { + if (paths != null) { + // flush paths from cache + for (Iterator i= paths.iterator(); i.hasNext(); ) { + IPath path= (IPath) i.next(); + flush(path); + } + } + } + + public synchronized void flushAll() { + // flush the entire cache + fFileMap.clear(); + fTypeMap.clear(); + fIsDirty= true; + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java new file mode 100644 index 00000000000..395d2c30ca7 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class TypeCacheMessages { + + private static final String RESOURCE_BUNDLE= TypeCacheMessages.class.getName(); + + private static ResourceBundle fgResourceBundle; + static { + try { + fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE); + } catch (MissingResourceException x) { + fgResourceBundle = null; + } + } + + private TypeCacheMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } catch (NullPointerException e) { + return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + public static String getFormattedString(String key, String arg) { + return getFormattedString(key, new String[] { arg }); + } + + public static String getFormattedString(String key, String[] args) { + return MessageFormat.format(getString(key), args); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties new file mode 100644 index 00000000000..273052e91ae --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2004 QNX Software Systems Ltd. and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Common Public License v0.5 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/cpl-v05.html +# +# Contributors: +# QNX Software Systems - Initial API and implementation +############################################################################### + +TypeCacherJob.jobName=TypeCache +TypeCacherJob.taskName=Updating Type Info... diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java new file mode 100644 index 00000000000..2e1dd094915 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.browser.AllTypesCache.IWorkingCopyProvider; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.search.ICSearchConstants; +import org.eclipse.cdt.core.search.ICSearchScope; +import org.eclipse.cdt.internal.core.browser.util.DelegatedProgressMonitor; +import org.eclipse.cdt.internal.core.model.CModelManager; +import org.eclipse.cdt.internal.core.search.CWorkspaceScope; +import org.eclipse.cdt.internal.core.search.PatternSearchJob; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; + + +/** + * Background job for filling the type cache. + * @see org.eclipse.core.runtime.jobs.Job + * @since 3.0 + */ +public class TypeCacherJob extends Job { + + /** + * An "identity rule" that forces jobs to be queued. + * @see org.eclipse.core.runtime.jobs.ISchedulingRule + * @since 3.0 + */ + final static ISchedulingRule MUTEX_RULE= new ISchedulingRule() { + public boolean contains(ISchedulingRule rule) { + return rule == this; + } + public boolean isConflicting(ISchedulingRule rule) { + return rule == this; + } + }; + + /** + * Constant identifying the job family identifier for the background job. + * @see IJobManager#join(Object, IProgressMonitor) + * @since 3.0 + */ + private static final Object FAMILY= new Object(); + + private DelegatedProgressMonitor fProgressMonitor; + private Set fSearchPaths= new HashSet(50); + private TypeCache fTypeCache; + private IWorkingCopyProvider fWorkingCopyProvider; + + public TypeCacherJob(TypeCache cache, IWorkingCopyProvider provider) { + super(TypeCacheMessages.getString("TypeCacherJob.jobName")); //$NON-NLS-1$ + setPriority(BUILD); + setSystem(true); + //setRule(MUTEX_RULE); + fTypeCache= cache; + fWorkingCopyProvider= provider; + } + + /* (non-Javadoc) + * @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object) + */ + public boolean belongsTo(Object family) { + return family == FAMILY; + } + + public void setSearchPaths(Set paths) { + fSearchPaths.clear(); + if (paths != null) + fSearchPaths.addAll(paths); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor) + */ + public IStatus run(IProgressMonitor monitor) { + fProgressMonitor= new DelegatedProgressMonitor(monitor); + + try { + search(fProgressMonitor); + fProgressMonitor.done(); + } catch(InterruptedException ex) { + return Status.CANCEL_STATUS; + } catch (OperationCanceledException ex) { + return Status.CANCEL_STATUS; + } finally { + fProgressMonitor= null; + } + + return Status.OK_STATUS; + } + + /** + * Forwards progress info to the progress monitor and + * blocks until the job is finished. + * + * @param monitor Optional progress monitor. + * @throws InterruptedException + * + * @see Job#join + */ + public void join(IProgressMonitor monitor) throws InterruptedException { + if (fProgressMonitor != null) + fProgressMonitor.addDelegate(monitor); + super.join(); + } + + private void search(IProgressMonitor monitor) throws InterruptedException { + + monitor.beginTask(TypeCacheMessages.getString("TypeCacherJob.taskName"), 100); //$NON-NLS-1$ + + IWorkspace workspace= CCorePlugin.getWorkspace(); + if (workspace == null) + throw new InterruptedException(); + + ICSearchScope scope= new CWorkspaceScope(); + + // search for types and #include references + TypeSearchPattern pattern= new TypeSearchPattern(); + for (Iterator pathIter= fSearchPaths.iterator(); pathIter.hasNext(); ) { + IPath path= (IPath) pathIter.next(); + pattern.addDependencySearch(path); + } + TypeSearchPathCollector pathCollector= new TypeSearchPathCollector(); + + CModelManager modelManager= CModelManager.getDefault(); + IndexManager indexManager= modelManager.getIndexManager(); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + SubProgressMonitor subMonitor= new SubProgressMonitor(monitor, 5); + + /* index search */ + indexManager.performConcurrentJob( + new PatternSearchJob( + pattern, + scope, + pathCollector, + indexManager + ), + ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, + subMonitor, + null ); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + if (!fSearchPaths.isEmpty()) { + // flush all affected files from cache + fTypeCache.flush(fSearchPaths); + Set dependencyPaths= pathCollector.getDependencyPaths(); + if (dependencyPaths != null && !dependencyPaths.isEmpty()) { + fTypeCache.flush(dependencyPaths); + } + } + + Set allSearchPaths= pathCollector.getPaths(); + if (allSearchPaths == null) + allSearchPaths= new HashSet(); + + // remove cached files + allSearchPaths.removeAll(fTypeCache.getAllFiles()); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + subMonitor= new SubProgressMonitor(monitor, 95); + + IWorkingCopy[] workingCopies= null; + if (fWorkingCopyProvider != null) + workingCopies= fWorkingCopyProvider.getWorkingCopies(); + + TypeMatchCollector collector= new TypeMatchCollector(fTypeCache, subMonitor); + TypeMatchLocator matchLocator= new TypeMatchLocator(collector); + matchLocator.locateMatches(allSearchPaths, workspace, workingCopies); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + fTypeCache.markAsDirty(false); + monitor.done(); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java new file mode 100644 index 00000000000..0e3e726c77f --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.ArrayList; + +import org.eclipse.cdt.core.browser.TypeInfo; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +public class TypeMatchCollector { + private ArrayList results= new ArrayList(); + private TypeCache typeCache; + private IProgressMonitor progressMonitor; + + public TypeMatchCollector(TypeCache cache, IProgressMonitor monitor) { + progressMonitor= monitor; + typeCache= cache; + } + + public IProgressMonitor getProgressMonitor() { + return progressMonitor; + } + + public boolean beginParsing(IPath path) { + // check if path is in the cache already + if (typeCache.contains(path)) + return false; + + results.clear(); + return true; + } + + public void doneParsing(IPath path) { + if (!results.isEmpty()) { + // add types to cache + typeCache.insert(path, results); + } + } + + public void acceptType(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) { + // create new type info + TypeInfo info= new TypeInfo(name, type, enclosingNames, resource, path, startOffset, endOffset); + results.add(info); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java new file mode 100644 index 00000000000..e20b01c0270 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java @@ -0,0 +1,561 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corp. - Rational Software - initial implementation + * QNX Software Systems - adapted for type search + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.io.CharArrayReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.parser.DefaultProblemHandler; +import org.eclipse.cdt.core.parser.IParser; +import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.core.parser.ISourceElementCallbackDelegate; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserFactoryError; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ParserUtil; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.core.parser.ast.ASTClassKind; +import org.eclipse.cdt.core.parser.ast.IASTASMDefinition; +import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTClassReference; +import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTCodeScope; +import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit; +import org.eclipse.cdt.core.parser.ast.IASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTEnumerationReference; +import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTEnumeratorReference; +import org.eclipse.cdt.core.parser.ast.IASTField; +import org.eclipse.cdt.core.parser.ast.IASTFieldReference; +import org.eclipse.cdt.core.parser.ast.IASTFunction; +import org.eclipse.cdt.core.parser.ast.IASTFunctionReference; +import org.eclipse.cdt.core.parser.ast.IASTInclusion; +import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; +import org.eclipse.cdt.core.parser.ast.IASTMacro; +import org.eclipse.cdt.core.parser.ast.IASTMethod; +import org.eclipse.cdt.core.parser.ast.IASTMethodReference; +import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; +import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference; +import org.eclipse.cdt.core.parser.ast.IASTOffsetableNamedElement; +import org.eclipse.cdt.core.parser.ast.IASTParameterReference; +import org.eclipse.cdt.core.parser.ast.IASTQualifiedNameElement; +import org.eclipse.cdt.core.parser.ast.IASTReference; +import org.eclipse.cdt.core.parser.ast.IASTScope; +import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation; +import org.eclipse.cdt.core.parser.ast.IASTTemplateParameterReference; +import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization; +import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTTypedefReference; +import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; +import org.eclipse.cdt.core.parser.ast.IASTVariable; +import org.eclipse.cdt.core.parser.ast.IASTVariableReference; +import org.eclipse.cdt.core.search.ICSearchConstants; +import org.eclipse.cdt.core.search.ICSearchPattern; +import org.eclipse.cdt.internal.core.browser.util.PathUtil; +import org.eclipse.cdt.internal.core.browser.util.SimpleStack; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; + +public class TypeMatchLocator implements ISourceElementRequestor, ICSearchConstants { + private ISourceElementCallbackDelegate lastDeclaration; + private ICSearchPattern searchPattern; + private TypeMatchCollector resultCollector; + private IProgressMonitor progressMonitor; + private IWorkspaceRoot workspaceRoot= null; + private SimpleStack scopeStack= new SimpleStack(); + private SimpleStack resourceStack= new SimpleStack(); + private static boolean VERBOSE= false; + + public TypeMatchLocator(TypeMatchCollector collector) { + super(); + searchPattern= new TypeSearchPattern(); + resultCollector= collector; + progressMonitor= collector.getProgressMonitor(); + if (progressMonitor == null) + progressMonitor= new NullProgressMonitor(); + } + + public boolean acceptProblem(IProblem problem) { + return DefaultProblemHandler.ruleOnProblem(problem, ParserMode.COMPLETE_PARSE ); + } + public void acceptUsingDirective(IASTUsingDirective usageDirective) { } + public void acceptUsingDeclaration(IASTUsingDeclaration usageDeclaration) { } + public void acceptASMDefinition(IASTASMDefinition asmDefinition) { } + public void acceptAbstractTypeSpecDeclaration(IASTAbstractTypeSpecifierDeclaration abstractDeclaration) { } + public void enterTemplateDeclaration(IASTTemplateDeclaration declaration) { } + public void enterTemplateSpecialization(IASTTemplateSpecialization specialization) { } + public void enterTemplateInstantiation(IASTTemplateInstantiation instantiation) { } + public void exitTemplateDeclaration(IASTTemplateDeclaration declaration) { } + public void exitTemplateSpecialization(IASTTemplateSpecialization specialization) { } + public void exitTemplateExplicitInstantiation(IASTTemplateInstantiation instantiation) { } + public void acceptParameterReference(IASTParameterReference reference) { } + public void acceptTemplateParameterReference(IASTTemplateParameterReference reference) { } + public void acceptTypedefReference( IASTTypedefReference reference ) { } + public void acceptEnumeratorReference(IASTEnumeratorReference reference) { } + public void acceptClassReference(IASTClassReference reference) { } + public void acceptNamespaceReference( IASTNamespaceReference reference ) { } + public void acceptVariableReference( IASTVariableReference reference ) { } + public void acceptFieldReference( IASTFieldReference reference ) { } + public void acceptEnumerationReference( IASTEnumerationReference reference ) { } + public void acceptFunctionReference( IASTFunctionReference reference ) { } + public void acceptMethodReference( IASTMethodReference reference ) { } + public void acceptField(IASTField field) { } + public void acceptMacro(IASTMacro macro) { } + public void acceptVariable(IASTVariable variable) { } + public void acceptFunctionDeclaration(IASTFunction function) { } + public void acceptMethodDeclaration(IASTMethod method) { } + public void enterCodeBlock(IASTCodeScope scope) { } + public void exitCodeBlock(IASTCodeScope scope) { } + + public void acceptTypedefDeclaration(IASTTypedefDeclaration typedef){ + lastDeclaration = typedef; + check( DECLARATIONS, typedef ); + } + + public void acceptEnumerationSpecifier(IASTEnumerationSpecifier enumeration){ + lastDeclaration = enumeration; + check( DECLARATIONS, enumeration ); + } + + public void acceptElaboratedForewardDeclaration(IASTElaboratedTypeSpecifier elaboratedType){ + check( DECLARATIONS, elaboratedType ); + } + + public void enterLinkageSpecification(IASTLinkageSpecification linkageSpec){ + pushScope( linkageSpec ); + } + public void exitLinkageSpecification(IASTLinkageSpecification linkageSpec){ + popScope(); + } + + public void enterCompilationUnit(IASTCompilationUnit compilationUnit) { + pushScope( compilationUnit ); + } + public void exitCompilationUnit(IASTCompilationUnit compilationUnit){ + popScope(); + } + + public void enterFunctionBody(IASTFunction function){ + pushScope( function ); + } + public void exitFunctionBody(IASTFunction function) { + popScope(); + } + + public void enterMethodBody(IASTMethod method) { + pushScope( method ); + } + public void exitMethodBody(IASTMethod method) { + popScope(); + } + + public void enterNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) { + lastDeclaration = namespaceDefinition; + check( DECLARATIONS, namespaceDefinition ); + check( DEFINITIONS, namespaceDefinition ); + pushScope( namespaceDefinition ); + } + public void exitNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) { + popScope(); + } + + public void enterClassSpecifier(IASTClassSpecifier classSpecification) { + lastDeclaration = classSpecification; + check( DECLARATIONS, classSpecification ); + pushScope( classSpecification ); + } + public void exitClassSpecifier(IASTClassSpecifier classSpecification) { + popScope(); + } + + public void enterInclusion(IASTInclusion inclusion) { + String includePath = inclusion.getFullFileName(); + + IPath path = new Path( includePath ); + IResource resource = null; + + if (workspaceRoot != null) + resource = workspaceRoot.getFileForLocation( path ); + + if (resource == null) { + // we need to standardize the paths for external headers + path = PathUtil.getCanonicalPath(includePath); + } + + if (resource != null) + resourceStack.push(resource); + else + resourceStack.push(path); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + } + + public void exitInclusion(IASTInclusion inclusion) { + resourceStack.pop(); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + } + + protected void report( ISourceElementCallbackDelegate node, int accuracyLevel ){ + int offset = 0; + int end = 0; + IASTOffsetableNamedElement offsetable = null; + String name = null; + int type = 0; + + if( node instanceof IASTReference ){ + IASTReference reference = (IASTReference) node; + offset = reference.getOffset(); + end = offset + reference.getName().length(); + if (VERBOSE) + verbose("Report Match: " + reference.getName()); //$NON-NLS-1$ + } else if( node instanceof IASTOffsetableNamedElement ){ + offsetable= (IASTOffsetableNamedElement) node; + offset = offsetable.getNameOffset() != 0 ? offsetable.getNameOffset() + : offsetable.getStartingOffset(); + end = offsetable.getNameEndOffset(); + if( end == 0 ){ + end = offset + offsetable.getName().length(); + } + + if (VERBOSE) + verbose("Report Match: " + offsetable.getName()); //$NON-NLS-1$ + } + + if (node instanceof IASTReference) + node = lastDeclaration; + + if (node instanceof IASTReference) { + offsetable = (IASTOffsetableNamedElement) ((IASTReference)node).getReferencedElement(); + name = ((IASTReference)node).getName(); + } else if (node instanceof IASTOffsetableNamedElement) { + offsetable = (IASTOffsetableNamedElement)node; + name = offsetable.getName(); + } else { + return; + } + + // skip unnamed structs + if (name == null || name.length() == 0) + return; + + // skip unused types + type= getElementType(offsetable); + if (type == 0) { + return; + } + + // collect enclosing names + String[] enclosingNames = null; + if (offsetable instanceof IASTQualifiedNameElement) { + String[] names = ((IASTQualifiedNameElement) offsetable).getFullyQualifiedName(); + if (names != null && names.length > 1) { + enclosingNames = new String[names.length-1]; + System.arraycopy(names, 0, enclosingNames, 0, names.length-1); + } + } + +// // collect enclosing files +// IPath[] enclosingPaths= null; +// Object[] sourceRefs= resourceStack.toArray(); +// // assert(sourceRefs.length > 0) +// +// // walk through resource stack and +// // collect enclosing paths +// enclosingPaths= new IPath[sourceRefs.length-1]; +// for (int i= 0; i < sourceRefs.length-1; ++i) { +// Object obj= sourceRefs[i]; +// IPath sourcePath= null; +// if (obj instanceof IResource) { +// IResource res= (IResource) obj; +// enclosingPaths[i]= res.getFullPath(); +// } else { +// enclosingPaths[i]= (IPath) obj; +// } +// } + + IResource resource= null; + IPath path= null; + Object obj= (Object) resourceStack.top(); + if (obj instanceof IResource) + resource= (IResource) obj; + else + path= (IPath) obj; + + resultCollector.acceptType(name, type, enclosingNames, resource, path, offset, end); + } + + private void check( LimitTo limit, ISourceElementCallbackDelegate node ){ + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + + // skip local declarations + IASTScope currentScope= (IASTScope)scopeStack.top(); + if (currentScope instanceof IASTFunction || currentScope instanceof IASTMethod) { + return; + } + + // always limit == DECLARATIONS +// +// if( !searchPattern.canAccept( limit ) ) +// return; + + int level = ICSearchPattern.IMPOSSIBLE_MATCH; + + if( node instanceof IASTReference ){ + level = searchPattern.matchLevel( ((IASTReference)node).getReferencedElement(), limit ); + } else { + level = searchPattern.matchLevel( node, limit ); + } + + if( level != ICSearchPattern.IMPOSSIBLE_MATCH ) + { + report( node, level ); + } + } + + private void pushScope( IASTScope scope ){ + scopeStack.push(scope); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + } + + private IASTScope popScope(){ + IASTScope oldScope= (IASTScope) scopeStack.pop(); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + + return oldScope; + } + + private static void verbose(String log) { + System.out.println("(" + Thread.currentThread() + ") " + log); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#createReader(java.lang.String) + */ + public Reader createReader(String finalPath) { + return ParserUtil.createReader(finalPath); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#parserTimeout() + */ + public boolean parserTimeout() { + return false; + } + + + public void locateMatches(Set searchPaths, IWorkspace workspace, IWorkingCopy[] workingCopies) throws InterruptedException { + workspaceRoot= (workspace != null) ? workspace.getRoot() : null; + + Set searchablePaths= new HashSet(searchPaths); + Map workingCopyMap= null; + + if (workingCopies != null && workingCopies.length > 0) { + workingCopyMap= new HashMap(workingCopies.length); + for (int i= 0; i < workingCopies.length; ++i) { + IWorkingCopy workingCopy= workingCopies[i]; + IPath wcPath= workingCopy.getOriginalElement().getPath(); + workingCopyMap.put(wcPath, workingCopy); + searchablePaths.add(wcPath); + } + } + + progressMonitor.beginTask("", searchablePaths.size()); //$NON-NLS-1$ + + for (Iterator i= searchablePaths.iterator(); i.hasNext(); ) { + + if (progressMonitor.isCanceled()) + throw new InterruptedException(); + + IPath path= (IPath) i.next(); + + if (!resultCollector.beginParsing(path)) + continue; + + Reader reader= null; + IPath realPath= null; + IProject project= null; + IResource currentResource= null; + IPath currentPath= null; + + progressMonitor.worked(1); + + if (workspaceRoot != null) { + IWorkingCopy workingCopy= null; + if (workingCopyMap != null) + workingCopy= (IWorkingCopy) workingCopyMap.get(path); + if (workingCopy != null) { + currentResource= workingCopy.getResource(); + reader= new CharArrayReader(workingCopy.getContents()); + } else { + currentResource= workspaceRoot.findMember(path, true); + if (currentResource != null && currentResource instanceof IFile) { + IFile file= (IFile) currentResource; + try { + reader= new InputStreamReader(file.getContents()); + } catch (CoreException ex) { + continue; + } + } + } + } + + if (currentResource == null) { + try { + reader= new FileReader(path.toFile()); + } catch (FileNotFoundException ex) { + continue; + } + currentPath= path; + realPath= currentPath; + project= null; + } else { + currentPath= null; + realPath= currentResource.getLocation(); + project= currentResource.getProject(); + } + + if (currentResource != null) + resourceStack.push(currentResource); + else + resourceStack.push(currentPath); + + parseMatches(path, reader, realPath, project); + + resourceStack.pop(); + + resultCollector.doneParsing(path); + + if (progressMonitor.isCanceled()) + throw new InterruptedException(); + } + + progressMonitor.done(); + } + + private void parseMatches(IPath path, Reader reader, IPath realPath, IProject project) throws InterruptedException { + //Get the scanner info + IScannerInfo scanInfo = new ScannerInfo(); + IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); + if (provider != null){ + IScannerInfo buildScanInfo = provider.getScannerInformation(project); + if( buildScanInfo != null ) + scanInfo = new ScannerInfo(buildScanInfo.getDefinedSymbols(), buildScanInfo.getIncludePaths()); + } + + ParserLanguage language = null; + if( project != null ){ + language = CoreModel.getDefault().hasCCNature( project ) ? ParserLanguage.CPP : ParserLanguage.C; + } else { + //TODO no project, what language do we use? + language = ParserLanguage.CPP; + } + + IParser parser = null; + try + { + IScanner scanner = ParserFactory.createScanner( reader, realPath.toOSString(), scanInfo, ParserMode.COMPLETE_PARSE, language, this, ParserUtil.getScannerLogService() ); + parser = ParserFactory.createParser( scanner, this, ParserMode.COMPLETE_PARSE, language, ParserUtil.getParserLogService() ); + } + catch( ParserFactoryError pfe ) + { + + } + + if (VERBOSE) + verbose("*** New Search for path: " + path); //$NON-NLS-1$ + + try { + parser.parse(); + } + catch(OperationCanceledException ex) { + throw new InterruptedException(); + } + catch(Exception ex) { + if (VERBOSE){ + ex.printStackTrace(); + } + } + catch(VirtualMachineError vmErr){ + if (VERBOSE){ + verbose("TypeMatchLocator VM Error: "); //$NON-NLS-1$ + vmErr.printStackTrace(); + } + } + } + + private int getElementType(IASTOffsetableNamedElement offsetable) { + if (offsetable instanceof IASTClassSpecifier || + offsetable instanceof IASTElaboratedTypeSpecifier) { + + ASTClassKind kind = null; + if (offsetable instanceof IASTClassSpecifier) { + kind= ((IASTClassSpecifier)offsetable).getClassKind(); + } else { + kind= ((IASTElaboratedTypeSpecifier)offsetable).getClassKind(); + } + + if (kind == ASTClassKind.CLASS) { + return ICElement.C_CLASS; + } else if (kind == ASTClassKind.STRUCT) { + return ICElement.C_STRUCT; + } else if (kind == ASTClassKind.UNION) { + return ICElement.C_UNION; + } + } else if ( offsetable instanceof IASTNamespaceDefinition ){ + return ICElement.C_NAMESPACE; + } else if ( offsetable instanceof IASTEnumerationSpecifier ){ + return ICElement.C_ENUMERATION; + } else if ( offsetable instanceof IASTTypedefDeclaration ){ + return ICElement.C_TYPEDEF; + } + + return 0; + } + +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java new file mode 100644 index 00000000000..352140e53ef --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor; +import org.eclipse.core.runtime.Path; + +/** + * Collects type and dependency paths from search results. + */ +public class TypeSearchPathCollector implements IIndexSearchRequestor { + + public Set typePaths= new HashSet(5); + public Set dependencyPaths= new HashSet(5); + + public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames) { + typePaths.add(resourcePath); + } + + public void acceptNamespaceDeclaration(String resourcePath, char[] typeName, char[][] enclosingTypeNames) { + typePaths.add(resourcePath); + } + + public void acceptIncludeDeclaration(String resourcePath, char[] decodedSimpleName) { + dependencyPaths.add(resourcePath); + } + + public void acceptConstructorDeclaration(String resourcePath, char[] typeName, int parameterCount) { } + public void acceptConstructorReference(String resourcePath, char[] typeName, int parameterCount) { } + public void acceptFieldDeclaration(String resourcePath, char[] fieldName) { } + public void acceptFieldReference(String resourcePath, char[] fieldName) { } + public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) { } + public void acceptFunctionDeclaration(String resourcePath, char[] methodName, int parameterCount) { } + public void acceptMethodDeclaration(String resourcePath, char[] methodName, int parameterCount, char[][] enclosingTypeNames) { } + public void acceptMethodReference(String resourcePath, char[] methodName, int parameterCount) { } + public void acceptPackageReference(String resourcePath, char[] packageName) { } + public void acceptVariableDeclaration(String resourcePath, char[] simpleTypeName) { } + public void acceptFieldDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames) { } + public void acceptMacroDeclaration(String resourcePath, char[] decodedSimpleName) { } + public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) { } + public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) { } + public void acceptTypeReference(String resourcePath, char[] typeName) { } + + /** + * Returns the paths that have been collected. + */ + public Set getPaths() { + Set pathSet= new HashSet(typePaths.size()); + for (Iterator i= typePaths.iterator(); i.hasNext(); ) { + String path= (String) i.next(); + pathSet.add(new Path(path)); + } + return pathSet; + } + + /** + * Returns the dependency paths that have been collected. + */ + public Set getDependencyPaths() { + Set pathSet= new HashSet(dependencyPaths.size()); + for (Iterator i= dependencyPaths.iterator(); i.hasNext(); ) { + String path= (String) i.next(); + pathSet.add(new Path(path)); + } + return pathSet; + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java new file mode 100644 index 00000000000..47def56dd5f --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.search.ICSearchConstants; +import org.eclipse.cdt.core.search.OrPattern; +import org.eclipse.cdt.core.search.SearchEngine; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + + +public final class TypeSearchPattern extends OrPattern { + public TypeSearchPattern() { + super(); + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.NAMESPACE, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.CLASS, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.STRUCT, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.UNION, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.ENUM, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.TYPEDEF, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + } + + public void addDependencySearch(IPath path) { + // convert path to absolute or the search will fail + IResource res= CCorePlugin.getWorkspace().getRoot().findMember(path); + if (res != null) + path= res.getRawLocation(); + if (path != null) + addPattern(createPattern(path.toOSString(), ICSearchConstants.INCLUDE, ICSearchConstants.REFERENCES, ICSearchConstants.EXACT_MATCH, true)); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java new file mode 100644 index 00000000000..4cd93b656b4 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +/** + * A helper class which allows you to perform some + * simple set operations on int arrays. + */ +public class ArrayUtil { + private ArrayUtil() { + } + + // returns true if set contains elem + public static boolean contains(int[] set, int elem) { + if (set == null) + return false; + for (int i= 0; i < set.length; ++i) { + if (set[i] == elem) + return true; + } + return false; + } + + // returns true if set contains all of subset + public static boolean containsAll(int[] set, int[] subset) { + if (set == null || subset == null) + return false; + for (int i= 0; i < subset.length; ++i) { + if (!contains(set, subset[i])) + return false; + } + return true; + } + + // return a copy of fromSet + public static int[] clone(int[] fromSet) { + if (fromSet == null) + return null; + int[] newSet= new int[fromSet.length]; + for (int i= 0; i < fromSet.length; ++i) { + newSet[i]= fromSet[i]; + } + return newSet; + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java new file mode 100644 index 00000000000..a28a746d674 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java @@ -0,0 +1,228 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IProgressMonitorWithBlocking; +import org.eclipse.core.runtime.IStatus; + +/** + * A wrapper around one or more progress monitors. Forwards + * <code>IProgressMonitor</code> and <code>IProgressMonitorWithBlocking</code> + * methods to the delegate monitors. + */ +public class DelegatedProgressMonitor implements IProgressMonitor, IProgressMonitorWithBlocking { + + private static int INITIAL_DELEGATE_COUNT = 2; + private final ArrayList fDelegateList = new ArrayList(INITIAL_DELEGATE_COUNT); + private String fTaskName; + private String fSubTask; + private int fTotalWork = IProgressMonitor.UNKNOWN; + private double fWorked; + private boolean fIsBlocked = false; + private boolean fIsCanceled = false; + + /** + * Creates a new delegated monitor. + */ + public DelegatedProgressMonitor() { + } + + /** + * Creates a new delegated monitor, and adds a delegate. + */ + public DelegatedProgressMonitor(IProgressMonitor delegate) { + addDelegate(delegate); + } + + /* + * @see IProgressMonitor#beginTask + */ + public synchronized void beginTask(String name, int totalWork) { + fTaskName = name; + fTotalWork = totalWork; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.beginTask(fTaskName, fTotalWork); + } + }); + } + + /* + * @see IProgressMonitor#done + */ + public synchronized void done() { + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.done(); + } + }); + } + + /* + * @see IProgressMonitor#setTaskName + */ + public synchronized void setTaskName(String name) { + fTaskName = name; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.setTaskName(fTaskName); + } + }); + } + + /* + * @see IProgressMonitor#subTask + */ + public synchronized void subTask(String name) { + fSubTask = name; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.subTask(fSubTask); + } + }); + } + + /* + * @see IProgressMonitor#worked + */ + public void worked(int work) { + internalWorked(work); + } + + /* + * @see IProgressMonitor#internalWorked + */ + public synchronized void internalWorked(double internalWork) { + fWorked += internalWork; + final double fInternalWork = internalWork; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.internalWorked(fInternalWork); + } + }); + } + + /* + * @see IProgressMonitor#isCanceled + */ + public synchronized boolean isCanceled() { + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + fIsCanceled |= delegate.isCanceled(); + } + }); + return fIsCanceled; + } + + /* + * @see IProgressMonitor#setCanceled + */ + public synchronized void setCanceled(boolean canceled) { + fIsCanceled = canceled; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.setCanceled(fIsCanceled); + } + }); + } + + /* + * @see IProgressMonitor#setBlocked + */ + public synchronized void setBlocked(IStatus reason) { + fIsBlocked = true; + final IStatus fReason = reason; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + if (delegate instanceof IProgressMonitorWithBlocking) + ((IProgressMonitorWithBlocking) delegate).setBlocked(fReason); + } + }); + } + + /* + * @see IProgressMonitor#clearBlocked + */ + public synchronized void clearBlocked() { + fIsBlocked = false; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + if (delegate instanceof IProgressMonitorWithBlocking) + ((IProgressMonitorWithBlocking) delegate).clearBlocked(); + } + }); + } + + /** + * Adds a delegate. + */ + public synchronized void addDelegate(IProgressMonitor delegate) { + if (fDelegateList.indexOf(delegate) == -1) { + if (fTaskName != null) + syncUp(delegate); + fDelegateList.add(delegate); + } + } + + /** + * Brings delegate in sync with current progress. + */ + private void syncUp(IProgressMonitor delegate) { + delegate.beginTask(fTaskName, fTotalWork); + delegate.internalWorked(fWorked); + if (fSubTask != null && fSubTask.length() > 0) + delegate.subTask(fSubTask); + if (fIsBlocked && delegate instanceof IProgressMonitorWithBlocking) + ((IProgressMonitorWithBlocking) delegate).setBlocked(null); + } + + /** + * Removes a delegate. + */ + public synchronized void removeDelegate(IProgressMonitor delegate) { + int index = fDelegateList.indexOf(delegate); + if (index != -1) { + fDelegateList.remove(index); + } + } + + /** + * Returns the delegate list. + * + * @return An array of progress monitors added using <code>addDelegate()</code>. + */ + public synchronized IProgressMonitor[] getDelegates() { + return (IProgressMonitor[]) fDelegateList.toArray(); + } + + /** + * Defines a delegate visitor. + */ + private static interface IDelegateVisitor { + public void visit(IProgressMonitor delegate); + } + + /** + * Visits each delegate in the delegates list. + */ + private void visitDelegates(IDelegateVisitor visitor) { + // Clone the delegates since they could remove themselves when called + ArrayList delegatesList = (ArrayList) fDelegateList.clone(); + for (Iterator i = delegatesList.iterator(); i.hasNext(); ) { + IProgressMonitor delegate = (IProgressMonitor) i.next(); + visitor.visit(delegate); + } + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java new file mode 100644 index 00000000000..b638a54fbf1 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.core.runtime.Path; + +public class PathUtil { + + private static boolean fWindows = false; + static { + String os = System.getProperty("os.name"); //$NON-NLS-1$ + if (os != null && os.startsWith("Win")) { //$NON-NLS-1$ + fWindows= true; + } + } + public static boolean isWindowsSystem() { + return fWindows; + } + + public static Path getCanonicalPath(String fullPath) { + File file = new File(fullPath); + try { + String canonPath = file.getCanonicalPath(); + return new Path(canonPath); + } catch (IOException ex) { + } + return new Path(fullPath); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java new file mode 100644 index 00000000000..6e06dbc5e3c --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +import java.util.ArrayList; + +/** + * A helper class which allows you to perform some simple + * stack operations. Avoids the extra overhead of + * synchronization in Java.Util.Stack. + */ +public class SimpleStack { + + private static int INITIAL_STACK_SIZE = 10; + private ArrayList items; + private static boolean VERBOSE = false; + + public SimpleStack() { + items = new ArrayList(INITIAL_STACK_SIZE); + } + + public SimpleStack(int initialSize) { + items = new ArrayList(initialSize); + } + + public Object push(Object item) { + items.add(item); + if (VERBOSE) + trace("push on stack: " + item); //$NON-NLS-1$ + return item; + } + + public Object pop() { + int top = items.size()-1; + if (top < 0) + return null; + Object item = items.get(top); + items.remove(top); + if (VERBOSE) + trace("pop from stack: " + item); //$NON-NLS-1$ + return item; + } + + public Object top() { + int top = items.size()-1; + if (top < 0) + return null; + return items.get(top); + } + + public boolean isEmpty() { + return (items.size() == 0); + } + + public Object[] toArray() { + return items.toArray(); + } + + public Object[] toArray(Object a[]) { + return items.toArray(a); + } + + private static void trace(String msg) { + System.out.println("(" + Thread.currentThread() + ") " + msg); //$NON-NLS-1$ //$NON-NLS-2$ + } +} |