public EditorScript(ITextEditor editor, SDRefactoringContext context, CSharpFormattingOptions formattingOptions) : base(editor.Document, formattingOptions, context.TextEditorOptions) { this.editor = editor; this.context = context; this.textSegmentCollection = new TextSegmentCollection<TextSegment>((TextDocument)editor.Document); }
CodeIssue CreateCodeIssue(Error error, SDRefactoringContext context) { IDocument document = context.Document; TextLocation begin = error.Region.Begin; if (begin.Line <= 0 || begin.Line > document.LineCount) return null; int offset = document.GetOffset(begin.Line, begin.Column); // the parser sometimes reports errors in the whitespace prior to the invalid token, so search for the next word: while (offset < document.TextLength && IsSpaceOrTab(document.GetCharAt(offset))) offset++; int endOffset = TextUtilities.GetNextCaretPosition(document, offset, System.Windows.Documents.LogicalDirection.Forward, CaretPositioningMode.WordBorderOrSymbol); if (endOffset < 0) endOffset = document.TextLength; int length = endOffset - offset; if (length < 1) { // marker should be at least 1 characters long, // but take care that we don't make it longer than the document length = Math.Min(1, document.TextLength - offset); } TextLocation start = document.GetLocation(offset); TextLocation end = document.GetLocation(offset + length); return new CodeIssue(start, end, error.Message); }
public void Execute(EditorRefactoringContext context) { var resolver = context.GetAstResolverAsync().Result; var refactoringContext = new SDRefactoringContext(context.Editor, resolver, context.CaretLocation); var action = getUpdatedCodeAction(refactoringContext); if (action != null) { using (var script = refactoringContext.StartScript()) { action.Run(script); } } }
public static SDRefactoringContext Create(FileName fileName, ITextSource textSource, TextLocation location = default(TextLocation), CancellationToken cancellationToken = default(CancellationToken)) { var parseInfo = SD.ParserService.Parse(fileName, textSource, cancellationToken: cancellationToken) as CSharpFullParseInformation; var compilation = SD.ParserService.GetCompilationForFile(fileName); CSharpAstResolver resolver; if (parseInfo != null) { resolver = parseInfo.GetResolver(compilation); } else { // create dummy refactoring context resolver = new CSharpAstResolver(compilation, new SyntaxTree()); } var context = new SDRefactoringContext(textSource, resolver, location, 0, 0, cancellationToken); return context; }
public static SDRefactoringContext Create(ITextEditor editor, CancellationToken cancellationToken) { var parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document, cancellationToken: cancellationToken) as CSharpFullParseInformation; var compilation = SD.ParserService.GetCompilationForFile(editor.FileName); CSharpAstResolver resolver; if (parseInfo != null) { resolver = parseInfo.GetResolver(compilation); } else { // create dummy refactoring context resolver = new CSharpAstResolver(compilation, new SyntaxTree()); } var context = new SDRefactoringContext(editor, resolver, editor.Caret.Location, cancellationToken); return context; }
CodeIssue CreateCodeIssue(Error error, SDRefactoringContext context) { IDocument document = context.Document; TextLocation begin = error.Region.Begin; int offset = document.GetOffset(begin.Line, begin.Column); int endOffset = TextUtilities.GetNextCaretPosition(document, offset, System.Windows.Documents.LogicalDirection.Forward, CaretPositioningMode.WordBorderOrSymbol); if (endOffset < 0) endOffset = document.TextLength; int length = endOffset - offset; if (length < 2) { // marker should be at least 2 characters long, but take care that we don't make // it longer than the document length = Math.Min(2, document.TextLength - offset); } TextLocation end = document.GetLocation(offset + length); return new CodeIssue(begin, end, error.Message); }
protected virtual void Initialize() { this.refactoringContext = SDRefactoringContext.Create(editor, CancellationToken.None); }
public Task<IContextAction[]> GetAvailableActionsAsync(EditorRefactoringContext context, CancellationToken cancellationToken) { ITextEditor editor = context.Editor; // grab SelectionStart/SelectionLength while we're still on the main thread int selectionStart = editor.SelectionStart; int selectionLength = editor.SelectionLength; return Task.Run( async delegate { try { if (!CreateCodeActionProvider()) return new IContextAction[0]; CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false); var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken); return codeActionProvider.GetActions(refactoringContext).Select(Wrap).ToArray(); } catch (Exception ex) { SD.Log.WarnFormatted("CSharpContextActionProviderWrapper crashed: {0}", ex); SD.AnalyticsMonitor.TrackException(ex); return new IContextAction[0]; } }, cancellationToken); }
public override void InsertEventHandler(ITypeDefinition target, string name, IEvent eventDefinition, bool jumpTo) { IUnresolvedTypeDefinition match = null; foreach (var part in target.Parts) { if (match == null || EntityModelContextUtils.IsBetterPart(part, match, ".cs")) { match = part; } } if (match == null) { return; } var view = SD.FileService.OpenFile(new FileName(match.Region.FileName), jumpTo); var editor = view.GetRequiredService <ITextEditor>(); var last = match.Members.LastOrDefault() ?? (IUnresolvedEntity)match; editor.Caret.Location = last.BodyRegion.End; var context = SDRefactoringContext.Create(editor, CancellationToken.None); var node = context.RootNode.GetNodeAt <EntityDeclaration>(last.Region.Begin); var resolver = context.GetResolverStateAfter(node); var builder = new TypeSystemAstBuilder(resolver); var invokeMethod = eventDefinition.ReturnType.GetDelegateInvokeMethod(); if (invokeMethod == null) { return; } var importedMethod = resolver.Compilation.Import(invokeMethod); var delegateDecl = builder.ConvertEntity(importedMethod) as MethodDeclaration; if (delegateDecl == null) { return; } var throwStmt = new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException"))); var decl = new MethodDeclaration() { ReturnType = delegateDecl.ReturnType.Clone(), Name = name, Body = new BlockStatement() { throwStmt } }; var param = delegateDecl.Parameters.Select(p => p.Clone()).ToArray(); decl.Parameters.AddRange(param); using (Script script = context.StartScript()) { // FIXME : will not work properly if there are no members. if (last == match) { throw new NotImplementedException(); // TODO InsertWithCursor not implemented! //script.InsertWithCursor("Insert event handler", Script.InsertPosition.End, decl).RunSynchronously(); } else { // TODO does not jump correctly... script.InsertAfter(node, decl); editor.JumpTo(throwStmt.StartLocation.Line, throwStmt.StartLocation.Column); } } }
public override Task <Script> InsertWithCursor(string operation, ITypeDefinition parentType, Func <Script, RefactoringContext, IList <AstNode> > nodeCallback) { // TODO : Use undo group var tcs = new TaskCompletionSource <Script>(); if (parentType == null) { return(tcs.Task); } IUnresolvedTypeDefinition part = null; foreach (var p in parentType.Parts) { if (part == null || EntityModelContextUtils.IsBetterPart(p, part, ".cs")) { part = p; } } if (part == null) { return(tcs.Task); } var fileName = new ICSharpCode.Core.FileName(part.Region.FileName); IViewContent document = SD.FileService.OpenFile(fileName); var area = document.GetService <TextArea>(); if (area == null) { return(tcs.Task); } var loc = part.Region.Begin; var parsedFile = SD.ParserService.ParseFile(fileName, area.Document, cancellationToken: context.CancellationToken); var declaringType = parsedFile.GetInnermostTypeDefinition(loc); EditorScript script; if (area.Document != context.Document) { script = new EditorScript(area.GetService <ITextEditor>(), SDRefactoringContext.Create(fileName, area.Document, loc, context.CancellationToken), FormattingOptions); startedScripts.Add(script); } else { script = this; } var nodes = nodeCallback(script, script.context); var insertionPoints = InsertionPoint.GetInsertionPoints(area.Document, part); if (insertionPoints.Count == 0) { SD.MessageService.ShowErrorFormatted("No valid insertion point can be found in type '{0}'.", part.Name); return(tcs.Task); } var layer = new InsertionCursorLayer(area, operation, insertionPoints); area.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)area.TextView.InvalidateVisual); InsertWithCursorOnLayer(script, layer, tcs, nodes, area.Document); return(tcs.Task); }
async void RunAnalysis(ITextSource textSource, CSharpFullParseInformation parseInfo) { if (markerService == null) return; if (cancellationTokenSource != null) cancellationTokenSource.Cancel(); cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; List<InspectionTag> results = new List<InspectionTag>(); try { await Task.Run( delegate { var compilation = SD.ParserService.GetCompilationForFile(parseInfo.FileName); var resolver = parseInfo.GetResolver(compilation); var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken); foreach (var issueProvider in issueProviders.Value) { if (issueProvider.CurrentSeverity == Severity.None) continue; foreach (var issue in issueProvider.GetIssues(context)) { if (issue.Start.IsEmpty || issue.End.IsEmpty) { // Issues can occur on invalid locations when analyzing incomplete code. // We'll just ignore them. continue; } results.Add(new InspectionTag( this, issueProvider, textSource.Version, issue.Description, context.GetOffset(issue.Start), context.GetOffset(issue.End), issue.IssueMarker, issue.Actions)); } } }, cancellationToken); } catch (TaskCanceledException) { } catch (OperationCanceledException) { } catch (Exception ex) { SD.Log.WarnFormatted("IssueManager crashed: {0}", ex); SD.AnalyticsMonitor.TrackException(ex); } if (!cancellationToken.IsCancellationRequested) { analyzedVersion = textSource.Version; Clear(); foreach (var newResult in results) { newResult.CreateMarker(editor.Document, markerService); } existingResults = results; } if (cancellationTokenSource != null && cancellationTokenSource.Token == cancellationToken) { // Dispose the cancellation token source if it's still the same one as we originally created cancellationTokenSource.Dispose(); cancellationTokenSource = null; } }
IEnumerable <SearchResultMatch> FindAndFixIssues(FileName fileName, List <IssueManager.IssueProvider> providers, CancellationToken cancellationToken, ref int fixedIssueCount) { cancellationToken.ThrowIfCancellationRequested(); var openedFile = SD.FileService.GetOpenedFile(fileName); bool documentWasLoadedFromDisk = false; IDocument document = null; if (openedFile != null && openedFile.CurrentView != null) { var provider = openedFile.CurrentView.GetService <IFileDocumentProvider>(); if (provider != null) { document = provider.GetDocumentForFile(openedFile); } } if (document == null) { documentWasLoadedFromDisk = true; document = new TextDocument(SD.FileService.GetFileContent(fileName)) { FileName = fileName }; } var context = SDRefactoringContext.Create(fileName, document, TextLocation.Empty, cancellationToken); List <CodeIssue> allIssues = new List <CodeIssue>(); bool documentWasChanged = false; foreach (var provider in providers) { cancellationToken.ThrowIfCancellationRequested(); var issues = provider.GetIssues(context).ToList(); // Fix issues, if possible: if (issues.Any(i => i.Actions.Count > 0)) { using (var script = context.StartScript()) { foreach (var issue in issues) { if (issue.Actions.Count > 0) { fixedIssueCount++; issue.Actions[0].Run(script); } } } documentWasChanged = true; // Update context now that we've modified the document context = SDRefactoringContext.Create(fileName, document, TextLocation.Empty, cancellationToken); // Find remaining issues: allIssues.AddRange(provider.GetIssues(context)); } else { allIssues.AddRange(issues); } } if (documentWasChanged && documentWasLoadedFromDisk) { // Save changes back to disk using (var writer = new StreamWriter(fileName, false, SD.FileService.DefaultFileEncoding)) { document.WriteTextTo(writer); } } if (allIssues.Count > 0) { using (var highlighter = SD.EditorControlService.CreateHighlighter(document)) { highlighter.BeginHighlighting(); return(allIssues.Select(issue => SearchResultMatch.Create(document, issue.Start, issue.End, highlighter)).ToList()); } } else { return(Enumerable.Empty <SearchResultMatch>()); } }
public override void InsertEventHandler(ITypeDefinition target, string name, IEvent eventDefinition, bool jumpTo, InsertEventHandlerBodyKind bodyKind = InsertEventHandlerBodyKind.ThrowNotImplementedException) { IUnresolvedTypeDefinition match = null; foreach (var part in target.Parts) { if (match == null || EntityModelContextUtils.IsBetterPart(part, match, ".cs")) { match = part; } } if (match == null) { return; } var view = SD.FileService.OpenFile(new FileName(match.Region.FileName), jumpTo); var editor = view.GetRequiredService <ITextEditor>(); var last = match.Members.LastOrDefault() ?? (IUnresolvedEntity)match; editor.Caret.Location = last.BodyRegion.End; var context = SDRefactoringContext.Create(editor, CancellationToken.None); var node = context.RootNode.GetNodeAt <EntityDeclaration>(last.Region.Begin); var resolver = context.GetResolverStateAfter(node); var builder = new TypeSystemAstBuilder(resolver); var invokeMethod = eventDefinition.ReturnType.GetDelegateInvokeMethod(); if (invokeMethod == null) { return; } var importedMethod = resolver.Compilation.Import(invokeMethod); var delegateDecl = builder.ConvertEntity(importedMethod) as MethodDeclaration; if (delegateDecl == null) { return; } var throwStmt = new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException"))); var decl = new MethodDeclaration() { ReturnType = delegateDecl.ReturnType.Clone(), Name = name, Body = new BlockStatement() { throwStmt } }; var param = delegateDecl.Parameters.Select(p => p.Clone()).ToArray(); decl.Parameters.AddRange(param); using (Script script = context.StartScript()) { int eolLen = 0; if (last == match) { eolLen = 2; script.AddTo((TypeDeclaration)node, decl); } else { script.InsertAfter(node, decl); } switch (bodyKind) { case InsertEventHandlerBodyKind.TodoComment: Comment comment = new Comment(" TODO: Implement " + name); script.Replace(throwStmt, comment); script.Select(comment); break; case InsertEventHandlerBodyKind.Nothing: var segment = script.GetSegment(throwStmt); if (script is DocumentScript && eolLen > 0) { eolLen = ((DocumentScript)script).CurrentDocument.GetLineByOffset(segment.Offset).DelimiterLength; } script.RemoveText(segment.Offset, segment.Length - eolLen); script.Select(segment.Offset, segment.Offset); break; case InsertEventHandlerBodyKind.ThrowNotImplementedException: script.Select(throwStmt); break; } } }
async void RunAnalysis(ITextSource textSource, CSharpFullParseInformation parseInfo) { if (markerService == null) { return; } if (cancellationTokenSource != null) { cancellationTokenSource.Cancel(); } cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; List <InspectionTag> results = new List <InspectionTag>(); try { await Task.Run( delegate { var compilation = SD.ParserService.GetCompilationForFile(parseInfo.FileName); var resolver = parseInfo.GetResolver(compilation); var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken); foreach (var issueProvider in issueProviders.Value) { if (issueProvider.CurrentSeverity == Severity.None) { continue; } foreach (var issue in issueProvider.GetIssues(context)) { if (issue.Start.IsEmpty || issue.End.IsEmpty) { // Issues can occur on invalid locations when analyzing incomplete code. // We'll just ignore them. continue; } results.Add(new InspectionTag( this, issueProvider, textSource.Version, issue.Description, context.GetOffset(issue.Start), context.GetOffset(issue.End), issue.IssueMarker, issue.Actions)); } } }, cancellationToken); } catch (TaskCanceledException) { } catch (OperationCanceledException) { } catch (Exception ex) { SD.Log.WarnFormatted("IssueManager crashed: {0}", ex); SD.AnalyticsMonitor.TrackException(ex); } if (!cancellationToken.IsCancellationRequested) { analyzedVersion = textSource.Version; Clear(); foreach (var newResult in results) { newResult.CreateMarker(editor.Document, markerService); } existingResults = results; } if (cancellationTokenSource != null && cancellationTokenSource.Token == cancellationToken) { // Dispose the cancellation token source if it's still the same one as we originally created cancellationTokenSource.Dispose(); cancellationTokenSource = null; } }
public Task<IContextAction[]> GetAvailableActionsAsync(EditorRefactoringContext context, CancellationToken cancellationToken) { ITextEditor editor = context.Editor; // grab SelectionStart/SelectionLength while we're still on the main thread int selectionStart = editor.SelectionStart; int selectionLength = editor.SelectionLength; return Task.Run( async delegate { if (!CreateCodeActionProvider()) return new IContextAction[0]; CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false); var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken); return codeActionProvider.GetActions(refactoringContext).Select(Wrap).ToArray(); }, cancellationToken); }