/// <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; } }
/// <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; }
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); } }
/// <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; }
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; } }
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); } } }