Exemplo n.º 1
0
		/// <summary>
		/// Finds all references to the specified entity.
		/// The results are reported using the callback.
		/// FindReferences may internally use parallelism, and may invoke the callback on multiple
		/// threads in parallel.
		/// </summary>
		public static async Task FindReferencesAsync(IEntity entity, IProgressMonitor progressMonitor, Action<SearchedFile> callback)
		{
			if (entity == null)
				throw new ArgumentNullException("entity");
			if (progressMonitor == null)
				throw new ArgumentNullException("progressMonitor");
			if (callback == null)
				throw new ArgumentNullException("callback");
			SD.MainThread.VerifyAccess();
			if (SD.ParserService.LoadSolutionProjectsThread.IsRunning) {
				progressMonitor.ShowingDialog = true;
				MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
				progressMonitor.ShowingDialog = false;
				return;
			}
			double totalWorkAmount;
			List<ISymbolSearch> symbolSearches = PrepareSymbolSearch(entity, progressMonitor.CancellationToken, out totalWorkAmount);
			double workDone = 0;
			ParseableFileContentFinder parseableFileContentFinder = new ParseableFileContentFinder();
			foreach (ISymbolSearch s in symbolSearches) {
				progressMonitor.CancellationToken.ThrowIfCancellationRequested();
				using (var childProgressMonitor = progressMonitor.CreateSubTask(s.WorkAmount / totalWorkAmount)) {
					await s.FindReferencesAsync(new SymbolSearchArgs(childProgressMonitor, parseableFileContentFinder), callback);
				}
				
				workDone += s.WorkAmount;
				progressMonitor.Progress = workDone / totalWorkAmount;
			}
		}
Exemplo n.º 2
0
		/// <summary>
		/// This method can be used in three modes:
		/// 1. Find references to classes (parentClass = targetClass, member = null, fileName = null)
		/// 2. Find references to members (parentClass = parent, member = member, fileName = null)
		/// 3. Find references to local variables (parentClass = parent, member = local var as field, fileName = parent.CompilationUnit.FileName)
		/// </summary>
		static List<Reference> RunFindReferences(IClass ownerClass, IMember member,
		                                         string fileName,
		                                         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;
			}
			
			CancellationToken ct = progressMonitor != null ? progressMonitor.CancellationToken : CancellationToken.None;
			
			List<ProjectItem> files;
			if (!string.IsNullOrEmpty(fileName)) {
				// search just in given file
				files = new List<ProjectItem>();
				files.Add(FindItem(fileName));
			} else {
				// search in all possible files
				ownerClass = ownerClass.GetCompoundClass();
				files = GetPossibleFiles(ownerClass, member);
			}
			ParseableFileContentFinder finder = new ParseableFileContentFinder();
			List<Reference> references = new List<Reference>();
			
			if (progressMonitor != null)
				progressMonitor.TaskName = StringParser.Parse("${res:SharpDevelop.Refactoring.FindingReferences}");
			
			foreach (ProjectItem item in files) {
				FileName itemFileName = FileName.Create(item.FileName);
				
				if (progressMonitor != null) {
					progressMonitor.Progress += 1.0 / files.Count;
					if (ct.IsCancellationRequested)
						return null;
				}
				// Don't read files we don't have a parser for.
				// This avoids loading huge files (e.g. sdps) when we have no intention of parsing them.
				if (ParserService.GetParser(itemFileName) != null) {
					ITextBuffer content = finder.Create(itemFileName);
					if (content != null) {
						try {
							AddReferences(references, ownerClass, member, itemFileName, content.Text, ct);
						} catch (OperationCanceledException ex) {
							if (ex.CancellationToken == ct)
								return null;
							else
								throw;
						}
					}
				}
			}
			
			return references;
		}
Exemplo n.º 3
0
		internal void Initialize2(IProgressMonitor progressMonitor)
		{
			if (!initializing) return;
			try {
				IProjectContent[] referencedContents;
				lock (this.ReferencedContents) {
					referencedContents = new IProjectContent[this.ReferencedContents.Count];
					this.ReferencedContents.CopyTo(referencedContents, 0);
				}
				
				foreach (IProjectContent referencedContent in referencedContents) {
					if (referencedContent is ReflectionProjectContent) {
						((ReflectionProjectContent)referencedContent).InitializeReferences();
					}
				}
				
				ParseableFileContentFinder finder = new ParseableFileContentFinder();
				var fileContents = (
					from p in project.Items.AsParallel().WithCancellation(progressMonitor.CancellationToken)
					where !ItemType.NonFileItemTypes.Contains(p.ItemType) && !String.IsNullOrEmpty(p.FileName)
					select FileName.Create(p.FileName)
				).ToList();
				
				object progressLock = new object();
				double fileCountInverse = 1.0 / fileContents.Count;
				Parallel.ForEach(
					fileContents,
					new ParallelOptions {
						MaxDegreeOfParallelism = Environment.ProcessorCount * 2,
						CancellationToken = progressMonitor.CancellationToken
					},
					fileName => {
						// Don't read files we don't have a parser for.
						// This avoids loading huge files (e.g. sdps) when we have no intention of parsing them.
						if (ParserService.GetParser(fileName) != null) {
							ITextBuffer content = finder.Create(fileName);
							if (content != null)
								ParserService.ParseFile(this, fileName, content);
						}
						lock (progressLock) {
							progressMonitor.Progress += fileCountInverse;
						}
					}
				);
			} finally {
				initializing = false;
				progressMonitor.Progress = 1;
			}
		}
		public SymbolRenameArgs(string newName, IProgressMonitor progressMonitor, ParseableFileContentFinder parseableFileContentFinder)
			: base(progressMonitor, parseableFileContentFinder)
		{
			if (newName == null)
				throw new ArgumentNullException("newName");
			NewName = newName;
		}
		public SymbolSearchArgs(IProgressMonitor progressMonitor, ParseableFileContentFinder parseableFileContentFinder)
		{
			if (progressMonitor == null)
				throw new ArgumentNullException("progressMonitor");
			if (parseableFileContentFinder == null)
				throw new ArgumentNullException("parseableFileContentFinder");
			this.ProgressMonitor = progressMonitor;
			this.ParseableFileContentFinder = parseableFileContentFinder;
			this.ProvideHighlightedLine = true;
		}
		public static async Task RenameSymbolAsync(ISymbol symbol, string newName, IProgressMonitor progressMonitor, Action<Error> errorCallback)
		{
			if (symbol == null)
				throw new ArgumentNullException("symbol");
			if (progressMonitor == null)
				throw new ArgumentNullException("progressMonitor");
			SD.MainThread.VerifyAccess();
			if (SD.ParserService.LoadSolutionProjectsThread.IsRunning) {
				progressMonitor.ShowingDialog = true;
				MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
				progressMonitor.ShowingDialog = false;
				return;
			}
			double totalWorkAmount;
			List<ISymbolSearch> symbolSearches = PrepareSymbolSearch(symbol, progressMonitor.CancellationToken, out totalWorkAmount);
			double workDone = 0;
			ParseableFileContentFinder parseableFileContentFinder = new ParseableFileContentFinder();
			var errors = new List<Error>();
			var changes = new List<PatchedFile>();
			foreach (ISymbolSearch s in symbolSearches) {
				progressMonitor.CancellationToken.ThrowIfCancellationRequested();
				using (var childProgressMonitor = progressMonitor.CreateSubTask(s.WorkAmount / totalWorkAmount)) {
					var args = new SymbolRenameArgs(newName, childProgressMonitor, parseableFileContentFinder);
					args.ProvideHighlightedLine = false;
					await s.RenameAsync(args, file => changes.Add(file), error => errors.Add(error));
				}
				
				workDone += s.WorkAmount;
				progressMonitor.Progress = workDone / totalWorkAmount;
			}
			if (errors.Count == 0) {
				foreach (var file in changes) {
					ApplyChanges(file);
				}
			} else {
				foreach (var error in errors) {
					errorCallback(error);
				}
			}
		}
		void DoReparseCode(List<FileName> filesToParse, IProgressMonitor progressMonitor)
		{
			ParseableFileContentFinder finder = new ParseableFileContentFinder();
			double fileCountInverse = 1.0 / filesToParse.Count;
			object progressLock = new object();
			Parallel.ForEach(
				filesToParse,
				new ParallelOptions {
					MaxDegreeOfParallelism = Environment.ProcessorCount,
					CancellationToken = progressMonitor.CancellationToken
				},
				fileName => {
					// Clear cached parse information so that the file is forced to be reparsed even if it is unchanged
					parserService.ClearParseInformation(fileName);
					
					ITextSource content = finder.Create(fileName);
					if (content != null) {
						parserService.ParseFile(fileName, content, project);
					}
					lock (progressLock) {
						progressMonitor.Progress += fileCountInverse;
					}
				});
		}
		void ParseFiles(List<FileName> filesToParse, IProgressMonitor progressMonitor)
		{
			IProjectContent cachedPC = TryReadFromCache(cacheFileName);
			ParseableFileContentFinder finder = new ParseableFileContentFinder();
			
			object progressLock = new object();
			double fileCountInverse = 1.0 / filesToParse.Count;
			int fileCountLoadedFromCache = 0;
			int fileCountParsed = 0;
			int fileCountParsedAndSerializable = 0;
			Parallel.ForEach(
				filesToParse,
				new ParallelOptions {
					MaxDegreeOfParallelism = Environment.ProcessorCount,
					CancellationToken = progressMonitor.CancellationToken
				},
				fileName => {
					ITextSource content = finder.CreateForOpenFile(fileName);
					bool wasLoadedFromCache = false;
					IUnresolvedFile unresolvedFile = null;
					if (content == null && cachedPC != null) {
						unresolvedFile = cachedPC.GetFile(fileName);
						if (unresolvedFile != null && unresolvedFile.LastWriteTime == File.GetLastWriteTimeUtc(fileName)) {
							parserService.RegisterUnresolvedFile(fileName, project, unresolvedFile);
							wasLoadedFromCache = true;
						}
					}
					if (!wasLoadedFromCache) {
						if (content == null) {
							try {
								content = SD.FileService.GetFileContentFromDisk(fileName);
							} catch (IOException) {
							} catch (UnauthorizedAccessException) {
							}
						}
						if (content != null) {
							unresolvedFile = parserService.ParseFile(fileName, content, project);
						}
					}
					lock (progressLock) {
						if (wasLoadedFromCache) {
							fileCountLoadedFromCache++;
						} else {
							fileCountParsed++;
							if (IsSerializable(unresolvedFile))
								fileCountParsedAndSerializable++;
						}
						SD.MainThread.InvokeAsyncAndForget(delegate { assemblyModel.Update(null, unresolvedFile); });
						progressMonitor.Progress += fileCountInverse;
					}
				});
			LoggingService.Debug(projectContent.AssemblyName + ": ParseFiles() finished. "
			                     + fileCountLoadedFromCache + " files were re-used from CC cache; "
			                     + fileCountParsed + " files were parsed (" + fileCountParsedAndSerializable + " of those are serializable)");
			lock (lockObj) {
				serializedProjectContentIsUpToDate = (fileCountLoadedFromCache > 0 && fileCountParsedAndSerializable == 0);
			}
		}
Exemplo n.º 9
0
		/// <summary>
		/// This method can be used in three modes:
		/// 1. Find references to classes (parentClass = targetClass, member = null, fileName = null)
		/// 2. Find references to members (parentClass = parent, member = member, fileName = null)
		/// 3. Find references to local variables (parentClass = parent, member = local var as field, fileName = parent.CompilationUnit.FileName)
		/// </summary>
		static List<Reference> RunFindReferences(IClass ownerClass, IMember member,
		                                         string fileName,
		                                         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 (!string.IsNullOrEmpty(fileName)) {
				// search just in given file
				files = new List<ProjectItem>();
				files.Add(FindItem(fileName));
			} else {
				// search in all possible files
				ownerClass = ownerClass.GetCompoundClass();
				files = GetPossibleFiles(ownerClass, member);
			}
			ParseableFileContentFinder finder = new ParseableFileContentFinder();
			List<Reference> references = new List<Reference>();
			
			if (progressMonitor != null)
				progressMonitor.TaskName = StringParser.Parse("${res:SharpDevelop.Refactoring.FindingReferences}");
			
			foreach (ProjectItem item in files) {
				FileName itemFileName = FileName.Create(item.FileName);
				
				if (progressMonitor != null) {
					progressMonitor.Progress += 1.0 / files.Count;
					if (progressMonitor.CancellationToken.IsCancellationRequested)
						return null;
				}
				
				ITextBuffer content = finder.Create(itemFileName);
				if (content != null) {
					AddReferences(references, ownerClass, member, itemFileName, content.Text);
				}
			}
			
			return references;
		}
Exemplo n.º 10
0
		void SearchForIssues(List<FileName> fileNames, IEnumerable<IssueManager.IssueProvider> providers, Action<SearchedFile> callback, IProgressMonitor monitor)
		{
			// used for debugging so that we can break in the crashing issue
			ParseableFileContentFinder contentFinder = new ParseableFileContentFinder();
			int filesProcessed = 0;
			foreach (FileName fileName in fileNames) {
				var fileContent = contentFinder.Create(fileName);
				var resultForFile = SearchForIssues(fileName, fileContent, providers, monitor.CancellationToken);
				if (resultForFile != null) {
					callback(resultForFile);
				}
				monitor.Progress = (double)(++filesProcessed) / fileNames.Count;
			}
		}
Exemplo n.º 11
0
		void SearchForIssuesParallel(List<FileName> fileNames, IEnumerable<IssueManager.IssueProvider> providers, Action<SearchedFile> callback, IProgressMonitor monitor)
		{
			ParseableFileContentFinder contentFinder = new ParseableFileContentFinder();
			int filesProcessed = 0;
			Parallel.ForEach(
				fileNames,
				new ParallelOptions {
					MaxDegreeOfParallelism = Environment.ProcessorCount,
					CancellationToken = monitor.CancellationToken
				},
				delegate (FileName fileName) {
					var fileContent = contentFinder.Create(fileName);
					try {
						var resultForFile = SearchForIssues(fileName, fileContent, providers, monitor.CancellationToken);
						if (resultForFile != null) {
							callback(resultForFile);
						}
					} catch (IOException) {
						// ignore IO exceptions (e.g. a file is missing)
					} catch (OperationCanceledException) {
						throw;
					} catch (Exception ex) {
						throw new ApplicationException("Exception while searching for issues in " + fileName, ex);
					}
					monitor.Progress = (double)Interlocked.Increment(ref filesProcessed) / fileNames.Count;
				});
		}
		void InsertEventHandlerInternal(string methodName, IEvent evt)
		{
			CSharpCodeGenerator generator = new CSharpCodeGenerator();
			var primary = loader.GetPrimaryTypeDefinition();
			var evtHandler = primary.GetMethods(m => m.Name == methodName, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
			if (evtHandler == null) {
				generator.InsertEventHandler(primary, methodName, evt, true);
			} else {
				CSharpBinding.Parser.CSharpFullParseInformation parseInfo;
				var node = evtHandler.GetDeclaration(out parseInfo) as MethodDeclaration;
				var fileName = new FileName(evtHandler.Region.FileName);
				var fileContentFinder = new ParseableFileContentFinder();
				
				if (node != null && !node.Body.IsNull) {
					var location = node.Body.FirstChild.StartLocation;
					var firstStatement = node.Body.Children.OfType<Statement>().FirstOrDefault();
					
					if (firstStatement == null) {
						var fileContent = fileContentFinder.Create(fileName);
						var document = new ReadOnlyDocument(fileContent);
						var offset = document.GetOffset(new TextLocation(location.Line + 1, 1));
						var length = DocumentUtilities.GetWhitespaceAfter(fileContent, offset).Length;
						location = new TextLocation(location.Line + 1, length + 1);
					} else {
						location = firstStatement.StartLocation;
					}
					SD.FileService.JumpToFilePosition(fileName, location.Line, location.Column);
				}
			}
		}