Beispiel #1
0
        static void ReparseProjectsInternal()
        {
            bool parsing = false;
            ParseProjectContent job;
            IProgressMonitor    progressMonitor = StatusBarService.CreateProgressMonitor();

            while (true)
            {
                // get next job
                lock (reParse1) {
                    if (reParse1.Count > 0)
                    {
                        if (parsing)
                        {
                            progressMonitor.Done();
                        }
                        parsing = false;
                        job     = reParse1.Dequeue();
                    }
                    else if (reParse2.Count > 0)
                    {
                        if (!parsing)
                        {
                            int workAmount = 0;
                            foreach (ParseProjectContent ppc in reParse2)
                            {
                                workAmount += ppc.GetInitializationWorkAmount();
                            }
                            progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount, false);
                        }
                        parsing = true;
                        job     = reParse2.Dequeue();
                    }
                    else
                    {
                        // all jobs done
                        reParseThread = null;
                        if (parsing)
                        {
                            progressMonitor.Done();
                        }
                        LoggingService.Info("reParse thread finished all jobs");
                        return;
                    }
                }

                // execute job
                if (parsing)
                {
                    LoggingService.Info("reparsing code for " + job.Project);
                    job.ReInitialize2(progressMonitor);
                }
                else
                {
                    LoggingService.Debug("reloading references for " + job.Project);
                    job.ReInitialize1(progressMonitor);
                }
            }
        }
Beispiel #2
0
        static void LoadSolutionProjectsInternal()
        {
            IProgressMonitor           progressMonitor = StatusBarService.CreateProgressMonitor();
            List <ParseProjectContent> createdContents = new List <ParseProjectContent>();

            foreach (IProject project in ProjectService.OpenSolution.Projects)
            {
                try {
                    ParseProjectContent newContent = project.CreateProjectContent();
                    if (newContent != null)
                    {
                        lock (projectContents) {
                            projectContents[project] = newContent;
                        }
                        createdContents.Add(newContent);
                    }
                } catch (Exception e) {
                    MessageService.ShowError(e, "Error while retrieving project contents from " + project);
                }
            }
            WorkbenchSingleton.SafeThreadAsyncCall(ProjectService.ParserServiceCreatedProjectContents);
            try {
                // multiply Count with 2 so that the progress bar is only at 50% when references are done
                progressMonitor.BeginTask("Loading references...", createdContents.Count * 2, false);
                int workAmount = 0;
                for (int i = 0; i < createdContents.Count; i++)
                {
                    if (abortLoadSolutionProjectsThread)
                    {
                        return;
                    }
                    ParseProjectContent newContent = createdContents[i];
                    progressMonitor.WorkDone = i;
                    try {
                        newContent.Initialize1(progressMonitor);
                        workAmount += newContent.GetInitializationWorkAmount();
                    } catch (Exception e) {
                        MessageService.ShowError(e, "Error while initializing project references:" + newContent);
                    }
                }
                // multiply workamount with two and start at workAmount so that the progress bar continues
                // from 50% towards 100%.
                progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount * 2, false);
                progressMonitor.WorkDone = workAmount;
                foreach (ParseProjectContent newContent in createdContents)
                {
                    if (abortLoadSolutionProjectsThread)
                    {
                        return;
                    }
                    try {
                        newContent.Initialize2(progressMonitor);
                    } catch (Exception e) {
                        MessageService.ShowError(e, "Error while initializing project contents:" + newContent);
                    }
                }
            } finally {
                progressMonitor.Done();
            }
        }
Beispiel #3
0
 public void Done()
 {
     lock (lockObject) {
         isCancelAllowed = false;
     }
     baseProgressMonitor.Done();
 }
Beispiel #4
0
        /// <summary>
        /// This method can be used in three modes:
        /// 1. Find references to classes (parentClass = targetClass, member = null, isLocal = false)
        /// 2. Find references to members (parentClass = parent, member = member, isLocal = false)
        /// 3. Find references to local variables (parentClass = parent, member = local var as field, isLocal = true)
        /// </summary>
        static List <Reference> RunFindReferences(IClass ownerClass, IMember member,
                                                  bool isLocal,
                                                  IProgressMonitor progressMonitor)
        {
            if (ParserService.LoadSolutionProjectsThreadRunning)
            {
                progressMonitor.ShowingDialog = true;
                MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
                progressMonitor.ShowingDialog = false;
                return(null);
            }
            List <ProjectItem> files;

            if (isLocal)
            {
                files = new List <ProjectItem>();
                files.Add(FindItem(ownerClass.CompilationUnit.FileName));
            }
            else
            {
                ownerClass = ownerClass.GetCompoundClass();
                files      = GetPossibleFiles(ownerClass, member);
            }
            ParseableFileContentEnumerator enumerator = new ParseableFileContentEnumerator(files.ToArray());
            List <Reference> references = new List <Reference>();

            try {
                if (progressMonitor != null)
                {
                    progressMonitor.BeginTask("${res:SharpDevelop.Refactoring.FindingReferences}", files.Count, true);
                }
                                #if DEBUG
                if (System.Windows.Forms.Control.ModifierKeys == System.Windows.Forms.Keys.Control)
                {
                    System.Diagnostics.Debugger.Break();
                }
                                #endif
                while (enumerator.MoveNext())
                {
                    if (progressMonitor != null)
                    {
                        progressMonitor.WorkDone = enumerator.Index;
                        if (progressMonitor.IsCancelled)
                        {
                            return(null);
                        }
                    }

                    AddReferences(references, ownerClass, member, isLocal, enumerator.CurrentFileName, enumerator.CurrentFileContent);
                }
            } finally {
                if (progressMonitor != null)
                {
                    progressMonitor.Done();
                }
                enumerator.Dispose();
            }
            return(references);
        }
Beispiel #5
0
        static void InitAddedProject(object state)
        {
            ParseProjectContent newContent      = (ParseProjectContent)state;
            IProgressMonitor    progressMonitor = StatusBarService.CreateProgressMonitor();

            newContent.Initialize1(progressMonitor);
            progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", newContent.GetInitializationWorkAmount(), false);
            newContent.Initialize2(progressMonitor);
            progressMonitor.Done();
        }
Beispiel #6
0
        void BuildDone()
        {
            lock (this) {
                if (buildIsDone)
                {
                    return;
                }
                buildIsDone = true;
            }
            if (!buildIsCancelled)
            {
                foreach (BuildNode n in nodeDict.Values)
                {
                    if (!n.buildFinished)
                    {
                        throw new Exception("All workers done, but a project did not finish building");
                    }
                }
            }
            string buildTime = " (" + (DateTime.Now - buildStart).ToString() + ")";

            if (buildIsCancelled)
            {
                results.Result = BuildResultCode.Cancelled;

                ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildCancelled}");
            }
            else if (rootNode.hasErrors)
            {
                results.Result = BuildResultCode.Error;

                ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildFailed}" + buildTime);
            }
            else
            {
                results.Result = BuildResultCode.Success;

                ReportMessageInternal("${res:MainWindow.CompilerMessages.BuildFinished}" + buildTime);
            }
            if (progressMonitor != null)
            {
                progressMonitor.Done();
            }
            ReportDone();
        }
 /// <summary>
 /// Marks the task as finished.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Equivalent to calling <see cref="IProgressMonitor.Done" /> on the associated <see cref="IProgressMonitor"/>.
 /// This method is provded as a convenience for use with the C# using statement.
 /// </para>
 /// </remarks>
 public void Dispose()
 {
     progressMonitor.Done();
 }
Beispiel #8
0
        protected virtual void CopyItems(IProject sourceProject, IProject targetProject, IProgressMonitor monitor)
        {
            if (sourceProject == null)
            {
                throw new ArgumentNullException("sourceProject");
            }
            if (targetProject == null)
            {
                throw new ArgumentNullException("targetProject");
            }
            IProjectItemListProvider targetProjectItems = targetProject as IProjectItemListProvider;

            if (targetProjectItems == null)
            {
                throw new ArgumentNullException("targetProjectItems");
            }

            ICollection <ProjectItem> sourceItems = sourceProject.Items;
            int totalWork = 0;

            foreach (ProjectItem item in sourceItems)
            {
                totalWork += GetRequiredWork(item);
            }

            monitor.BeginTask("Converting", totalWork, true);
            int workDone = 0;

            foreach (ProjectItem item in sourceItems)
            {
                FileProjectItem fileItem = item as FileProjectItem;
                if (fileItem != null && FileUtility.IsBaseDirectory(sourceProject.Directory, fileItem.FileName))
                {
                    FileProjectItem targetItem = new FileProjectItem(targetProject, fileItem.ItemType);
                    fileItem.CopyMetadataTo(targetItem);
                    targetItem.Include = fileItem.Include;
                    if (File.Exists(fileItem.FileName))
                    {
                        if (!Directory.Exists(Path.GetDirectoryName(targetItem.FileName)))
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(targetItem.FileName));
                        }
                        try {
                            ConvertFile(fileItem, targetItem);
                        } catch (Exception ex) {
                            throw new ConversionException("Error converting " + fileItem.FileName, ex);
                        }
                    }
                    targetProjectItems.AddProjectItem(targetItem);
                }
                else
                {
                    targetProjectItems.AddProjectItem(item.CloneFor(targetProject));
                }
                if (monitor.IsCancelled)
                {
                    return;
                }
                workDone        += GetRequiredWork(item);
                monitor.WorkDone = workDone;
            }
            monitor.Done();
        }
        /// <summary>
        /// Finds all references to resources (except the definition) using the specified
        /// <see cref="IResourceReferenceFinder"/> object.
        /// </summary>
        /// <param name="finder">The <see cref="IResourceReferenceFinder"/> to use to find resource references.</param>
        /// <param name="monitor">An object implementing <see cref="IProgressMonitor"/> to report the progress of the operation. Can be <c>null</c>.</param>
        /// <param name="scope">The scope which should be searched.</param>
        /// <returns>A list of references to resources.</returns>
        public static List <Reference> FindReferences(IResourceReferenceFinder finder, IProgressMonitor monitor, SearchScope scope)
        {
            if (finder == null)
            {
                throw new ArgumentNullException("finder");
            }

            if (ParserService.LoadSolutionProjectsThreadRunning)
            {
                if (monitor != null)
                {
                    monitor.ShowingDialog = true;
                }
                MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
                if (monitor != null)
                {
                    monitor.ShowingDialog = false;
                }
                return(null);
            }

            DateTime startTime = DateTime.UtcNow;

            List <Reference> references = new List <Reference>();

            try {
                NRefactoryAstCacheService.EnableCache();

                ICollection <string> files = GetPossibleFiles(scope);

                if (monitor != null)
                {
                    monitor.BeginTask("${res:SharpDevelop.Refactoring.FindingReferences}", files.Count, true);
                }

                foreach (string fileName in files)
                {
                    if (monitor != null && monitor.IsCancelled)
                    {
                        return(null);
                    }

                    IDocument doc = null;
                    try {
                        // The following line throws an exception if the file does not exist.
                        // But the file may be in an unsaved view content (which would be found by GetDocumentInformation),
                        // so we cannot simply loop on !File.Exists(...).
                        doc = FindReferencesAndRenameHelper.GetDocumentInformation(fileName).CreateDocument();
                    } catch (FileNotFoundException) {
                    }
                    if (doc == null)
                    {
                        if (monitor != null)
                        {
                            ++monitor.WorkDone;
                        }
                        continue;
                    }

                    string fileContent = doc.TextContent;
                    if (String.IsNullOrEmpty(fileContent))
                    {
                        if (monitor != null)
                        {
                            ++monitor.WorkDone;
                        }
                        continue;
                    }

                    int pos = -1;
                    while ((pos = finder.GetNextPossibleOffset(fileName, fileContent, pos)) >= 0)
                    {
                        TextLocation          docPos = doc.OffsetToPosition(pos);
                        ResourceResolveResult rrr    = ResourceResolverService.Resolve(fileName, doc, docPos.Y, docPos.X, null);

                        if (rrr != null && rrr.ResourceFileContent != null)
                        {
                            if (finder.IsReferenceToResource(rrr))
                            {
                                if (rrr.Key != null)
                                {
                                    // The actual location of the key string may be after 'pos' because
                                    // the resolvers may find an expression just before it.
                                    string keyString = rrr.Key;
                                    int    keyPos    = fileContent.IndexOf(keyString, pos, StringComparison.OrdinalIgnoreCase);

                                    if (keyPos < pos)
                                    {
                                        // The key may be escaped in some way in the document.
                                        // Try using the code generator to find this out.
                                        keyPos = FindStringLiteral(fileName, fileContent, rrr.Key, pos, out keyString);
                                    }

                                    if (keyPos < pos)
                                    {
                                        if (monitor != null)
                                        {
                                            monitor.ShowingDialog = true;
                                        }
                                        MessageService.ShowWarning("ResourceToolkit: The key '" + rrr.Key + "' could not be located at the resolved position in the file '" + fileName + "'.");
                                        if (monitor != null)
                                        {
                                            monitor.ShowingDialog = false;
                                        }
                                    }
                                    else
                                    {
                                        references.Add(new Reference(fileName, keyPos, keyString.Length, keyString, rrr));
                                    }
                                }
                                else
                                {
                                    references.Add(new Reference(fileName, pos, 0, null, rrr));
                                }
                            }
                        }
                    }

                    if (monitor != null)
                    {
                        ++monitor.WorkDone;
                    }
                }

                LoggingService.Info("ResourceToolkit: FindReferences finished in " + (DateTime.UtcNow - startTime).TotalSeconds.ToString(System.Globalization.CultureInfo.CurrentCulture) + "s");
            } finally {
                NRefactoryAstCacheService.DisableCache();
                if (monitor != null)
                {
                    monitor.Done();
                }
            }

            return(references);
        }
        /// <summary>
        /// Renames all references to a resource including the definition.
        /// </summary>
        /// <param name="rrr">The resource to be renamed.</param>
        /// <param name="newKey">The new name of the resource key.</param>
        /// <param name="monitor">An object implementing <see cref="IProgressMonitor"/> to report the progress of the operation. Can be <c>null</c>.</param>
        public static void Rename(ResourceResolveResult rrr, string newKey, IProgressMonitor monitor)
        {
            // Prevent duplicate key names
            if (rrr.ResourceFileContent.ContainsKey(newKey))
            {
                if (monitor != null)
                {
                    monitor.ShowingDialog = true;
                }
                MessageService.ShowWarning("${res:Hornung.ResourceToolkit.EditStringResourceDialog.DuplicateKey}");
                if (monitor != null)
                {
                    monitor.ShowingDialog = false;
                }
                return;
            }

            List <Reference> references = FindReferences(rrr.FileName, rrr.Key, monitor);

            if (references == null)
            {
                return;
            }

            if (monitor != null)
            {
                monitor.BeginTask(null, 0, false);
            }

            try {
                // rename definition (if present)
                if (rrr.ResourceFileContent.ContainsKey(rrr.Key))
                {
                    rrr.ResourceFileContent.RenameKey(rrr.Key, newKey);
                }
                else
                {
                    if (monitor != null)
                    {
                        monitor.ShowingDialog = true;
                    }
                    MessageService.ShowWarning("${res:Hornung.ResourceToolkit.RenameKeyDefinitionNotFoundWarning}");
                    if (monitor != null)
                    {
                        monitor.ShowingDialog = false;
                    }
                }
            } catch (Exception ex) {
                if (monitor != null)
                {
                    monitor.ShowingDialog = true;
                }
                MessageService.ShowWarningFormatted("${res:Hornung.ResourceToolkit.ErrorProcessingResourceFile}" + Environment.NewLine + ex.Message, rrr.ResourceFileContent.FileName);
                if (monitor != null)
                {
                    monitor.ShowingDialog = false;
                }
                if (monitor != null)
                {
                    monitor.Done();
                }
                // Do not rename the references when renaming the definition failed.
                return;
            }

            // rename references
            // FIXME: RenameReferences does not enforce escaping rules. May be a problem if someone uses double-quotes in the new resource key name.
            FindReferencesAndRenameHelper.RenameReferences(references, newKey);

            // rename definitions in localized resource files
            foreach (KeyValuePair <string, IResourceFileContent> entry in ResourceFileContentRegistry.GetLocalizedContents(rrr.FileName))
            {
                try {
                    if (entry.Value.ContainsKey(rrr.Key))
                    {
                        entry.Value.RenameKey(rrr.Key, newKey);
                    }
                } catch (Exception ex) {
                    if (monitor != null)
                    {
                        monitor.ShowingDialog = true;
                    }
                    MessageService.ShowWarningFormatted("${res:Hornung.ResourceToolkit.ErrorProcessingResourceFile}" + Environment.NewLine + ex.Message, entry.Value.FileName);
                    if (monitor != null)
                    {
                        monitor.ShowingDialog = false;
                    }
                }
            }

            if (monitor != null)
            {
                monitor.Done();
            }
        }
        /// <summary>
        /// Finds all unused resource keys in all resource files that are referenced
        /// in code at least once in the whole solution.
        /// </summary>
        /// <param name="monitor">An object implementing <see cref="IProgressMonitor"/> to report the progress of the operation. Can be <c>null</c>.</param>
        /// <returns>A collection of <see cref="ResourceItem"/> classes that represent the unused resource keys.</returns>
        public static ICollection <ResourceItem> FindUnusedKeys(IProgressMonitor monitor)
        {
            List <Reference> references = FindAllReferences(monitor, SearchScope.WholeSolution);

            if (references == null)
            {
                return(null);
            }

            if (monitor != null)
            {
                monitor.BeginTask(null, 0, false);
            }

            List <ResourceItem> unused = new List <ResourceItem>();

            // Get a list of all referenced resource files.
            // Generate a dictonary of resource file names and the
            // corresponding referenced keys.
            Dictionary <string, List <string> > referencedKeys     = new Dictionary <string, List <string> >();
            Dictionary <string, List <string> > referencedPrefixes = new Dictionary <string, List <string> >();

            foreach (Reference reference in references)
            {
                ResourceResolveResult rrr = (ResourceResolveResult)reference.ResolveResult;
                if (rrr.ResourceFileContent != null)
                {
                    string fileName = rrr.FileName;
                    if (!referencedKeys.ContainsKey(fileName))
                    {
                        referencedKeys.Add(fileName, new List <string>());
                        referencedPrefixes.Add(fileName, new List <string>());
                    }
                    if (rrr.Key != null && !referencedKeys[fileName].Contains(rrr.Key))
                    {
                        referencedKeys[fileName].Add(rrr.Key);
                    }
                    else
                    {
                        ResourcePrefixResolveResult rprr = rrr as ResourcePrefixResolveResult;
                        if (rprr != null && rprr.Prefix != null && !referencedPrefixes[fileName].Contains(rprr.Prefix))
                        {
                            referencedPrefixes[fileName].Add(rprr.Prefix);
                        }
                    }
                }
                else
                {
                    if (monitor != null)
                    {
                        monitor.ShowingDialog = true;
                    }
                    MessageService.ShowWarning("Found a resource reference that could not be resolved." + Environment.NewLine + (reference.FileName ?? "<null>") + ":" + reference.Offset + Environment.NewLine + "Expression: " + (reference.Expression ?? "<null>"));
                    if (monitor != null)
                    {
                        monitor.ShowingDialog = false;
                    }
                }
            }

            // Find keys that are not referenced anywhere.
            foreach (string fileName in referencedKeys.Keys)
            {
                                #if DEBUG
                LoggingService.Debug("ResourceToolkit: FindUnusedKeys: Referenced resource file '" + fileName + "'");
                                #endif
                foreach (KeyValuePair <string, object> entry in ResourceFileContentRegistry.GetResourceFileContent(fileName).Data)
                {
                    if (!referencedKeys[fileName].Contains(entry.Key) &&
                        !referencedPrefixes[fileName].Any(prefix => entry.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
                    {
                        unused.Add(new ResourceItem(fileName, entry.Key));
                    }
                }
            }

            if (monitor != null)
            {
                monitor.Done();
            }

            return(unused.AsReadOnly());
        }
		/// <summary>
		/// This method can be used in three modes:
		/// 1. Find references to classes (parentClass = targetClass, member = null, isLocal = false)
		/// 2. Find references to members (parentClass = parent, member = member, isLocal = false)
		/// 3. Find references to local variables (parentClass = parent, member = local var as field, isLocal = true)
		/// </summary>
		static List<Reference> RunFindReferences(IClass ownerClass, IMember member,
		                                         bool isLocal,
		                                         IProgressMonitor progressMonitor)
		{
			if (ParserService.LoadSolutionProjectsThreadRunning) {
				if (progressMonitor != null) progressMonitor.ShowingDialog = true;
				MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
				if (progressMonitor != null) progressMonitor.ShowingDialog = false;
				return null;
			}
			List<ProjectItem> files;
			if (isLocal) {
				files = new List<ProjectItem>();
				files.Add(FindItem(ownerClass.CompilationUnit.FileName));
			} else {
				ownerClass = ownerClass.GetCompoundClass();
				files = GetPossibleFiles(ownerClass, member);
			}
			ParseableFileContentEnumerator enumerator = new ParseableFileContentEnumerator(files.ToArray());
			List<Reference> references = new List<Reference>();
			try {
				if (progressMonitor != null) {
					progressMonitor.BeginTask("${res:SharpDevelop.Refactoring.FindingReferences}", files.Count, true);
				}
				#if DEBUG
				if (System.Windows.Forms.Control.ModifierKeys == DefaultEditor.Gui.Editor.SharpDevelopTextAreaControl.DebugBreakModifiers) {
					System.Diagnostics.Debugger.Break();
				}
				#endif
				while (enumerator.MoveNext()) {
					if (progressMonitor != null) {
						progressMonitor.WorkDone = enumerator.Index;
						if (progressMonitor.IsCancelled) {
							return null;
						}
					}
					
					AddReferences(references, ownerClass, member, isLocal, enumerator.CurrentFileName, enumerator.CurrentFileContent);
				}
			} finally {
				if (progressMonitor != null) {
					progressMonitor.Done();
				}
				enumerator.Dispose();
			}
			return references;
		}
		/// <summary>
		/// Finds all references to resources (except the definition) using the specified
		/// <see cref="IResourceReferenceFinder"/> object.
		/// </summary>
		/// <param name="finder">The <see cref="IResourceReferenceFinder"/> to use to find resource references.</param>
		/// <param name="monitor">An object implementing <see cref="IProgressMonitor"/> to report the progress of the operation. Can be <c>null</c>.</param>
		/// <param name="scope">The scope which should be searched.</param>
		/// <returns>A list of references to resources.</returns>
		public static List<Reference> FindReferences(IResourceReferenceFinder finder, IProgressMonitor monitor, SearchScope scope)
		{
			if (finder == null) {
				throw new ArgumentNullException("finder");
			}
			
			if (ParserService.LoadSolutionProjectsThreadRunning) {
				if (monitor != null) monitor.ShowingDialog = true;
				MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
				if (monitor != null) monitor.ShowingDialog = false;
				return null;
			}
			
			DateTime startTime = DateTime.UtcNow;
			
			List<Reference> references = new List<Reference>();
			
			try {
				
				NRefactoryAstCacheService.EnableCache();
				
				ICollection<string> files = GetPossibleFiles(scope);
				
				if (monitor != null) {
					monitor.BeginTask("${res:SharpDevelop.Refactoring.FindingReferences}", files.Count, true);
				}
				
				foreach (string fileName in files) {
					
					if (monitor != null && monitor.IsCancelled) {
						return null;
					}
					
					IDocument doc = null;
					try {
						// The following line throws an exception if the file does not exist.
						// But the file may be in an unsaved view content (which would be found by GetDocumentInformation),
						// so we cannot simply loop on !File.Exists(...).
						doc = FindReferencesAndRenameHelper.GetDocumentInformation(fileName).CreateDocument();
					} catch (FileNotFoundException) {
					}
					if (doc == null) {
						if (monitor != null) ++monitor.WorkDone;
						continue;
					}
					
					string fileContent = doc.TextContent;
					if (String.IsNullOrEmpty(fileContent)) {
						if (monitor != null) ++monitor.WorkDone;
						continue;
					}
					
					int pos = -1;
					while ((pos = finder.GetNextPossibleOffset(fileName, fileContent, pos)) >= 0) {
						
						TextLocation docPos = doc.OffsetToPosition(pos);
						ResourceResolveResult rrr = ResourceResolverService.Resolve(fileName, doc, docPos.Y, docPos.X, null);
						
						if (rrr != null && rrr.ResourceFileContent != null) {
							if (finder.IsReferenceToResource(rrr)) {
								
								if (rrr.Key != null) {
									
									// The actual location of the key string may be after 'pos' because
									// the resolvers may find an expression just before it.
									string keyString = rrr.Key;
									int keyPos = fileContent.IndexOf(keyString, pos, StringComparison.OrdinalIgnoreCase);
									
									if (keyPos < pos) {
										// The key may be escaped in some way in the document.
										// Try using the code generator to find this out.
										keyPos = FindStringLiteral(fileName, fileContent, rrr.Key, pos, out keyString);
									}
									
									if (keyPos < pos) {
										if (monitor != null) monitor.ShowingDialog = true;
										MessageService.ShowWarning("ResourceToolkit: The key '"+rrr.Key+"' could not be located at the resolved position in the file '"+fileName+"'.");
										if (monitor != null) monitor.ShowingDialog = false;
									} else {
										references.Add(new Reference(fileName, keyPos, keyString.Length, keyString, rrr));
									}
									
								} else {
									references.Add(new Reference(fileName, pos, 0, null, rrr));
								}
								
							}
						}
						
					}
					
					if (monitor != null) ++monitor.WorkDone;
				}
				
				LoggingService.Info("ResourceToolkit: FindReferences finished in "+(DateTime.UtcNow - startTime).TotalSeconds.ToString(System.Globalization.CultureInfo.CurrentCulture)+"s");
				
			} finally {
				NRefactoryAstCacheService.DisableCache();
				if (monitor != null) monitor.Done();
			}
			
			return references;
		}
		/// <summary>
		/// Renames all references to a resource including the definition.
		/// </summary>
		/// <param name="rrr">The resource to be renamed.</param>
		/// <param name="newKey">The new name of the resource key.</param>
		/// <param name="monitor">An object implementing <see cref="IProgressMonitor"/> to report the progress of the operation. Can be <c>null</c>.</param>
		public static void Rename(ResourceResolveResult rrr, string newKey, IProgressMonitor monitor)
		{
			// Prevent duplicate key names
			if (rrr.ResourceFileContent.ContainsKey(newKey)) {
				if (monitor != null) monitor.ShowingDialog = true;
				MessageService.ShowWarning("${res:Hornung.ResourceToolkit.EditStringResourceDialog.DuplicateKey}");
				if (monitor != null) monitor.ShowingDialog = false;
				return;
			}
			
			List<Reference> references = FindReferences(rrr.FileName, rrr.Key, monitor);
			if (references == null) {
				return;
			}
			
			if (monitor != null) {
				monitor.BeginTask(null, 0, false);
			}
			
			try {
				// rename definition (if present)
				if (rrr.ResourceFileContent.ContainsKey(rrr.Key)) {
					rrr.ResourceFileContent.RenameKey(rrr.Key, newKey);
				} else {
					if (monitor != null) monitor.ShowingDialog = true;
					MessageService.ShowWarning("${res:Hornung.ResourceToolkit.RenameKeyDefinitionNotFoundWarning}");
					if (monitor != null) monitor.ShowingDialog = false;
				}
			} catch (Exception ex) {
				if (monitor != null) monitor.ShowingDialog = true;
				MessageService.ShowWarningFormatted("${res:Hornung.ResourceToolkit.ErrorProcessingResourceFile}" + Environment.NewLine + ex.Message, rrr.ResourceFileContent.FileName);
				if (monitor != null) monitor.ShowingDialog = false;
				if (monitor != null) monitor.Done();
				// Do not rename the references when renaming the definition failed.
				return;
			}
			
			// rename references
			// FIXME: RenameReferences does not enforce escaping rules. May be a problem if someone uses double-quotes in the new resource key name.
			FindReferencesAndRenameHelper.RenameReferences(references, newKey);
			
			// rename definitions in localized resource files
			foreach (KeyValuePair<string, IResourceFileContent> entry in ResourceFileContentRegistry.GetLocalizedContents(rrr.FileName)) {
				try {
					if (entry.Value.ContainsKey(rrr.Key)) {
						entry.Value.RenameKey(rrr.Key, newKey);
					}
				} catch (Exception ex) {
					if (monitor != null) monitor.ShowingDialog = true;
					MessageService.ShowWarningFormatted("${res:Hornung.ResourceToolkit.ErrorProcessingResourceFile}" + Environment.NewLine + ex.Message, entry.Value.FileName);
					if (monitor != null) monitor.ShowingDialog = false;
				}
			}
			
			if (monitor != null) monitor.Done();
		}
		/// <summary>
		/// Finds all unused resource keys in all resource files that are referenced
		/// in code at least once in the whole solution.
		/// </summary>
		/// <param name="monitor">An object implementing <see cref="IProgressMonitor"/> to report the progress of the operation. Can be <c>null</c>.</param>
		/// <returns>A collection of <see cref="ResourceItem"/> classes that represent the unused resource keys.</returns>
		public static ICollection<ResourceItem> FindUnusedKeys(IProgressMonitor monitor)
		{
			List<Reference> references = FindAllReferences(monitor, SearchScope.WholeSolution);
			if (references == null) {
				return null;
			}
			
			if (monitor != null) {
				monitor.BeginTask(null, 0, false);
			}
			
			List<ResourceItem> unused = new List<ResourceItem>();
			
			// Get a list of all referenced resource files.
			// Generate a dictonary of resource file names and the
			// corresponding referenced keys.
			Dictionary<string, List<string>> referencedKeys = new Dictionary<string, List<string>>();
			Dictionary<string, List<string>> referencedPrefixes = new Dictionary<string, List<string>>();
			foreach (Reference reference in references) {
				ResourceResolveResult rrr = (ResourceResolveResult)reference.ResolveResult;
				if (rrr.ResourceFileContent != null) {
					string fileName = rrr.FileName;
					if (!referencedKeys.ContainsKey(fileName)) {
						referencedKeys.Add(fileName, new List<string>());
						referencedPrefixes.Add(fileName, new List<string>());
					}
					if (rrr.Key != null && !referencedKeys[fileName].Contains(rrr.Key)) {
						referencedKeys[fileName].Add(rrr.Key);
					} else {
						ResourcePrefixResolveResult rprr = rrr as ResourcePrefixResolveResult;
						if (rprr != null && rprr.Prefix != null && !referencedPrefixes[fileName].Contains(rprr.Prefix)) {
							referencedPrefixes[fileName].Add(rprr.Prefix);
						}
					}
				} else {
					if (monitor != null) monitor.ShowingDialog = true;
					MessageService.ShowWarning("Found a resource reference that could not be resolved."+Environment.NewLine+(reference.FileName ?? "<null>")+":"+reference.Offset+Environment.NewLine+"Expression: "+(reference.Expression ?? "<null>"));
					if (monitor != null) monitor.ShowingDialog = false;
				}
			}
			
			// Find keys that are not referenced anywhere.
			foreach (string fileName in referencedKeys.Keys) {
				#if DEBUG
				LoggingService.Debug("ResourceToolkit: FindUnusedKeys: Referenced resource file '"+fileName+"'");
				#endif
				foreach (KeyValuePair<string, object> entry in ResourceFileContentRegistry.GetResourceFileContent(fileName).Data) {
					if (!referencedKeys[fileName].Contains(entry.Key) &&
					    !referencedPrefixes[fileName].Any(prefix => entry.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) {
						unused.Add(new ResourceItem(fileName, entry.Key));
					}
				}
			}
			
			if (monitor != null) monitor.Done();
			
			return unused.AsReadOnly();
		}
		protected virtual void CopyItems(IProject sourceProject, IProject targetProject, IProgressMonitor monitor)
		{
			if (sourceProject == null)
				throw new ArgumentNullException("sourceProject");
			if (targetProject == null)
				throw new ArgumentNullException("targetProject");
			IProjectItemListProvider targetProjectItems = targetProject as IProjectItemListProvider;
			if (targetProjectItems == null)
				throw new ArgumentNullException("targetProjectItems");
			
			ICollection<ProjectItem> sourceItems = sourceProject.Items;
			int totalWork = 0;
			foreach (ProjectItem item in sourceItems) {
				totalWork += GetRequiredWork(item);
			}
			
			monitor.BeginTask("Converting", totalWork, true);
			int workDone = 0;
			foreach (ProjectItem item in sourceItems) {
				FileProjectItem fileItem = item as FileProjectItem;
				if (fileItem != null && FileUtility.IsBaseDirectory(sourceProject.Directory, fileItem.FileName)) {
					FileProjectItem targetItem = new FileProjectItem(targetProject, fileItem.ItemType);
					fileItem.CopyMetadataTo(targetItem);
					targetItem.Include = fileItem.Include;
					if (File.Exists(fileItem.FileName)) {
						if (!Directory.Exists(Path.GetDirectoryName(targetItem.FileName))) {
							Directory.CreateDirectory(Path.GetDirectoryName(targetItem.FileName));
						}
						try {
							ConvertFile(fileItem, targetItem);
						} catch (Exception ex) {
							throw new ConversionException("Error converting " + fileItem.FileName, ex);
						}
					}
					targetProjectItems.AddProjectItem(targetItem);
				} else {
					targetProjectItems.AddProjectItem(item.CloneFor(targetProject));
				}
				if (monitor.IsCancelled) {
					return;
				}
				workDone += GetRequiredWork(item);
				monitor.WorkDone = workDone;
			}
			monitor.Done();
		}