Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit 25fa355

Browse files
committed
Merge branch 'master' into envdte-nrefactory
2 parents 2a0cb43 + 543912d commit 25fa355

76 files changed

Lines changed: 785 additions & 431 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

data/resources/StringResources.de.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,6 +3314,9 @@ Bitte einen anderen Dateinamen wählen.</value>
33143314
<data name="ICSharpCode.CodeCoverage.Column" xml:space="preserve">
33153315
<value>Spalte</value>
33163316
</data>
3317+
<data name="ICSharpCode.CodeCoverage.Content" xml:space="preserve">
3318+
<value>Inhalt</value>
3319+
</data>
33173320
<data name="ICSharpCode.CodeCoverage.DisplayOptions" xml:space="preserve">
33183321
<value>Anzeige-Optionen</value>
33193322
</data>

data/resources/StringResources.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,6 +2039,15 @@ Do you want to add the new file to the project ${CurrentProjectName}?</value>
20392039
<value>Save</value>
20402040
<comment>Save *inputbox* items</comment>
20412041
</data>
2042+
<data name="Dialog.Options.IDEOptions.CodeCompletion.TooltipLinkTarget" xml:space="preserve">
2043+
<value>Links in tooltips should go to</value>
2044+
</data>
2045+
<data name="Dialog.Options.IDEOptions.CodeCompletion.TooltipLinkTargetDefinition" xml:space="preserve">
2046+
<value>Definition in code</value>
2047+
</data>
2048+
<data name="Dialog.Options.IDEOptions.CodeCompletion.TooltipLinkTargetDocumentation" xml:space="preserve">
2049+
<value>Documentation (if available)</value>
2050+
</data>
20422051
<data name="Dialog.Options.IDEOptions.CodeCompletion.UseDataUsageCache" xml:space="preserve">
20432052
<value>Pre-select recently used members</value>
20442053
</data>

src/AddIns/Analysis/UnitTesting/Options/UnitTestingOptionsPanel.xaml.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public partial class UnitTestingOptionsPanel : OptionPanel
2525
{
2626
public UnitTestingOptionsPanel()
2727
{
28+
InitializeComponent();
2829
}
2930
}
3031
}

src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/TextEditorWithParseInformationFolding.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,19 @@ public void InstallFoldingManager()
4242
{
4343
var textEditorAdapter = textEditor as AvalonEditTextEditorAdapter;
4444
if (textEditorAdapter != null) {
45+
RemoveExistingFoldingManager(textEditorAdapter);
4546
foldingManager = FoldingManager.Install(textEditorAdapter.TextEditor.TextArea);
4647
}
4748
}
4849

50+
void RemoveExistingFoldingManager(AvalonEditTextEditorAdapter textEditorAdapter)
51+
{
52+
var existingFoldingManager = textEditorAdapter.TextEditor.TextArea.GetService(typeof(FoldingManager)) as FoldingManager;
53+
if (existingFoldingManager != null) {
54+
FoldingManager.Uninstall(existingFoldingManager);
55+
}
56+
}
57+
4958
// TODO disable parse information folding?
5059
public bool IsParseInformationFoldingEnabled {
5160
get {

src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
using System;
2020
using System.Collections.Generic;
2121

22+
using System.Threading;
23+
using ICSharpCode.AvalonEdit.Highlighting;
2224
using ICSharpCode.NRefactory;
25+
using ICSharpCode.NRefactory.TypeSystem;
2326
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
2427
using CSharpBinding.Completion;
2528
using CSharpBinding.FormattingStrategy;
@@ -58,12 +61,15 @@ public class CSharpTextEditorExtension : ITextEditorExtension
5861
IssueManager inspectionManager;
5962
IList<IContextActionProvider> contextActionProviders;
6063
CodeManipulation codeManipulation;
64+
CSharpSemanticHighlighter highlighter;
65+
CancellationTokenSource caretMovementTokenSource;
6166

6267
public void Attach(ITextEditor editor)
6368
{
6469
this.editor = editor;
6570
inspectionManager = new IssueManager(editor);
6671
codeManipulation = new CodeManipulation(editor);
72+
this.editor.Caret.LocationChanged += CaretLocationChanged;
6773

6874
if (!editor.ContextActionProviders.IsReadOnly) {
6975
contextActionProviders = AddInTree.BuildItems<IContextActionProvider>("/SharpDevelop/ViewContent/TextEditor/C#/ContextActions", null);
@@ -81,7 +87,21 @@ public void Detach()
8187
if (contextActionProviders != null) {
8288
editor.ContextActionProviders.RemoveAll(contextActionProviders.Contains);
8389
}
90+
this.editor.Caret.LocationChanged -= CaretLocationChanged;
8491
this.editor = null;
8592
}
93+
94+
void CaretLocationChanged(object sender, EventArgs e)
95+
{
96+
if (highlighter == null)
97+
highlighter = editor.GetService<CSharpSemanticHighlighter>();
98+
if (highlighter == null)
99+
return;
100+
if (caretMovementTokenSource != null)
101+
caretMovementTokenSource.Cancel();
102+
caretMovementTokenSource = new CancellationTokenSource();
103+
var rr = SD.ParserService.Resolve(editor.FileName, editor.Caret.Location, editor.Document, cancellationToken: caretMovementTokenSource.Token);
104+
highlighter.SetCurrentSymbol(rr.GetSymbol());
105+
}
86106
}
87107
}

src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@
1818

1919
using System;
2020
using System.Collections.Generic;
21+
using System.ComponentModel.Design;
2122
using System.Diagnostics;
2223
using System.Linq;
24+
using System.Windows.Media;
2325
using ICSharpCode.AvalonEdit.Document;
2426
using ICSharpCode.AvalonEdit.Highlighting;
2527
using ICSharpCode.Core;
2628
using ICSharpCode.NRefactory;
29+
using ICSharpCode.NRefactory.CSharp;
2730
using ICSharpCode.NRefactory.CSharp.Analysis;
31+
using ICSharpCode.NRefactory.CSharp.Resolver;
2832
using ICSharpCode.NRefactory.Editor;
33+
using ICSharpCode.NRefactory.Semantics;
2934
using ICSharpCode.NRefactory.TypeSystem;
3035
using ICSharpCode.SharpDevelop;
3136
using ICSharpCode.SharpDevelop.Parser;
@@ -50,6 +55,9 @@ public class CSharpSemanticHighlighter : SemanticHighlightingVisitor<Highlightin
5055
int lineNumber;
5156
HighlightedLine line;
5257
CSharpFullParseInformation parseInfo;
58+
ISymbolReference currentSymbolReference;
59+
IResolveVisitorNavigator currentNavigator;
60+
HighlightingColor symbolReferenceColor;
5361

5462
#region Constructor + Dispose
5563
public CSharpSemanticHighlighter(IDocument document)
@@ -66,6 +74,7 @@ public CSharpSemanticHighlighter(IDocument document)
6674
this.enumerationTypeColor = this.valueKeywordColor;
6775
this.typeParameterTypeColor = this.referenceTypeColor;
6876
this.delegateTypeColor = this.referenceTypeColor;
77+
this.symbolReferenceColor = new HighlightingColor { Background = new SimpleHighlightingBrush(DefaultFillColor) };
6978

7079
this.methodDeclarationColor = this.methodCallColor = highlighting.GetNamedColor("MethodCall");
7180
//this.eventDeclarationColor = this.eventAccessColor = defaultTextColor;
@@ -92,6 +101,7 @@ public CSharpSemanticHighlighter(IDocument document)
92101
SD.ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
93102
SD.ParserService.LoadSolutionProjectsThread.Finished += ParserService_LoadSolutionProjectsThreadEnded;
94103
eventHandlersAreRegistered = true;
104+
document.GetService<IServiceContainer>().AddService(typeof(CSharpSemanticHighlighter), this);
95105
}
96106
}
97107

@@ -101,6 +111,7 @@ public void Dispose()
101111
SD.ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
102112
SD.ParserService.LoadSolutionProjectsThread.Finished -= ParserService_LoadSolutionProjectsThreadEnded;
103113
eventHandlersAreRegistered = false;
114+
document.GetService<IServiceContainer>().RemoveService(typeof(CSharpSemanticHighlighter));
104115
}
105116
this.resolver = null;
106117
this.parseInfo = null;
@@ -174,10 +185,7 @@ void syntaxHighlighter_VisibleDocumentLinesChanged(object sender, EventArgs e)
174185

175186
void ParserService_LoadSolutionProjectsThreadEnded(object sender, EventArgs e)
176187
{
177-
cachedLines.Clear();
178-
invalidLines.Clear();
179-
forceParseOnNextRefresh = true;
180-
OnHighlightingStateChanged(1, document.LineCount);
188+
InvalidateAll();
181189
}
182190

183191
void ParserService_ParseInformationUpdated(object sender, ParseInformationEventArgs e)
@@ -389,6 +397,109 @@ protected override void Colorize(TextLocation start, TextLocation end, Highlight
389397
});
390398
}
391399
}
400+
401+
protected override void Colorize(AstNode node, HighlightingColor color)
402+
{
403+
if (currentSymbolReference != null && currentNavigator == null)
404+
currentNavigator = InitNavigator();
405+
406+
if (currentNavigator != null) {
407+
var resolverNode = node;
408+
while (CSharpAstResolver.IsUnresolvableNode(resolverNode) && resolverNode.Parent != null)
409+
resolverNode = resolverNode.Parent;
410+
if (resolverNode.Role == Roles.TargetExpression && resolverNode.Parent is InvocationExpression)
411+
resolverNode = resolverNode.Parent;
412+
if (resolverNode.Role == Roles.Type && resolverNode.Parent is ObjectCreateExpression)
413+
resolverNode = resolverNode.Parent;
414+
415+
if (node is Identifier && !node.IsNull)
416+
resolverNode.AddAnnotation(node);
417+
if (color != null)
418+
resolverNode.AddAnnotation(color);
419+
currentNavigator.Resolved(resolverNode, resolver.Resolve(resolverNode));
420+
}
421+
base.Colorize(node, color);
422+
}
423+
424+
protected override void Colorize(Identifier identifier, ResolveResult rr)
425+
{
426+
if (currentSymbolReference != null && currentNavigator == null)
427+
currentNavigator = InitNavigator();
428+
429+
if (currentNavigator != null) {
430+
currentNavigator.Resolved(identifier, rr);
431+
}
432+
base.Colorize(identifier, rr);
433+
}
434+
435+
public override void VisitPrimitiveType(PrimitiveType primitiveType)
436+
{
437+
// highlight usages of primitive types as well.
438+
Colorize(primitiveType, null);
439+
}
440+
441+
public readonly Color DefaultFillColor = Color.FromArgb(22, 30, 130, 255);
442+
443+
public void SetCurrentSymbol(ISymbol symbol)
444+
{
445+
currentNavigator = null;
446+
currentSymbolReference = null;
447+
if (symbol != null)
448+
currentSymbolReference = symbol.ToReference();
449+
InvalidateAll();
450+
}
451+
452+
void InvalidateAll()
453+
{
454+
cachedLines.Clear();
455+
invalidLines.Clear();
456+
forceParseOnNextRefresh = true;
457+
OnHighlightingStateChanged(1, document.LineCount);
458+
}
459+
460+
FindReferences findReferences = new FindReferences();
461+
462+
IResolveVisitorNavigator InitNavigator()
463+
{
464+
if (currentSymbolReference == null) return null;
465+
var compilation = resolver.Compilation;
466+
var symbol = currentSymbolReference.Resolve(compilation.TypeResolveContext);
467+
var searchScopes = findReferences.GetSearchScopes(symbol);
468+
if (searchScopes.Count == 0)
469+
return null;
470+
var navigators = new IResolveVisitorNavigator[searchScopes.Count];
471+
for (int i = 0; i < navigators.Length; i++) {
472+
navigators[i] = searchScopes[i].GetNavigator(compilation, ColorizeMatch);
473+
}
474+
IResolveVisitorNavigator combinedNavigator;
475+
if (searchScopes.Count == 1) {
476+
combinedNavigator = navigators[0];
477+
} else {
478+
combinedNavigator = new CompositeResolveVisitorNavigator(navigators);
479+
}
480+
481+
return combinedNavigator;
482+
}
483+
484+
void ColorizeMatch(AstNode node, ResolveResult result)
485+
{
486+
Identifier identifier = node.Annotation<Identifier>() ?? node.GetChildByRole(Roles.Identifier);
487+
TextLocation start, end;
488+
if (!identifier.IsNull) {
489+
start = identifier.StartLocation;
490+
end = identifier.EndLocation;
491+
} else {
492+
start = node.StartLocation;
493+
end = node.EndLocation;
494+
}
495+
var complementary = node.Annotation<HighlightingColor>();
496+
HighlightingColor newColor = symbolReferenceColor;
497+
if (complementary != null) {
498+
newColor = newColor.Clone();
499+
newColor.MergeWith(complementary);
500+
}
501+
Colorize(start, end, newColor);
502+
}
392503
#endregion
393504
}
394505
}

src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using System.Linq;
2222
using System.Text;
2323

24+
using ICSharpCode.AvalonEdit.Document;
2425
using ICSharpCode.AvalonEdit.Highlighting;
2526
using ICSharpCode.AvalonEdit.Indentation.CSharp;
2627
using ICSharpCode.Core;
@@ -62,11 +63,10 @@ static void IndentSingleLine(CacheIndentEngine engine, IDocument document, IDocu
6263
{
6364
engine.Update(line.EndOffset);
6465
if (engine.NeedsReindent) {
65-
int textOffset = line.Offset;
66-
while (textOffset < line.EndOffset && char.IsWhiteSpace(document.GetCharAt(textOffset)))
67-
textOffset++;
68-
string newText = document.GetText(textOffset, line.Length + line.Offset - textOffset);
69-
document.Replace(line.Offset, line.Length, engine.ThisLineIndent + newText);
66+
var indentation = TextUtilities.GetWhitespaceAfter(document, line.Offset);
67+
// replacing the indentation in two steps is necessary to make the caret move accordingly.
68+
document.Replace(indentation.Offset, indentation.Length, "");
69+
document.Replace(indentation.Offset, 0, engine.ThisLineIndent);
7070
engine.ResetEngineToPosition(line.Offset);
7171
}
7272
}
@@ -194,7 +194,7 @@ bool IsInsideDocumentationComment(ITextEditor textArea, IDocumentLine curLine, i
194194
char ch = textArea.Document.GetCharAt(i);
195195
if (ch == '"') {
196196
// parsing strings correctly is too complicated (see above),
197-
// but I don't now any case where a doc comment is after a string...
197+
// but I don't know any case where a doc comment is after a string...
198198
return false;
199199
}
200200
if (ch == '/' && i + 2 < cursorOffset && textArea.Document.GetCharAt(i + 1) == '/' && textArea.Document.GetCharAt(i + 2) == '/') {
@@ -274,11 +274,11 @@ void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char
274274
string terminator = DocumentUtilities.GetLineTerminator(textArea.Document, lineNr);
275275

276276
string curLineText;
277-
//// local string for curLine segment
277+
// local string for curLine segment
278278
if (ch == '/') {
279279
curLineText = textArea.Document.GetText(curLine);
280280
string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove);
281-
if (curLineText != null && curLineText.EndsWith("///") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///"))) {
281+
if (curLineText != null && curLineText.EndsWith("///", StringComparison.Ordinal) && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///", StringComparison.Ordinal))) {
282282
string indentation = DocumentUtilities.GetWhitespaceAfter(textArea.Document, curLine.Offset);
283283
IUnresolvedEntity member = GetMemberAfter(textArea, lineNr);
284284
if (member != null) {
@@ -341,10 +341,10 @@ void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char
341341
commentBuilder.Append(curLineText[ i]);
342342
}
343343
string tag = commentBuilder.ToString().Trim();
344-
if (!tag.EndsWith(">")) {
344+
if (!tag.EndsWith(">", StringComparison.Ordinal)) {
345345
tag += ">";
346346
}
347-
if (!tag.StartsWith("/")) {
347+
if (!tag.StartsWith("/", StringComparison.Ordinal)) {
348348
textArea.Document.Insert(cursorOffset, "</" + tag.Substring(1), AnchorMovementType.BeforeInsertion);
349349
}
350350
}
@@ -361,10 +361,10 @@ void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char
361361
break;
362362
case '\n':
363363
string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove);
364-
//// curLine might have some text which should be added to indentation
364+
// curLine might have some text which should be added to indentation
365365
curLineText = textArea.Document.GetText(curLine);
366366

367-
if (lineAboveText != null && lineAboveText.Trim().StartsWith("#region")
367+
if (lineAboveText != null && lineAboveText.Trim().StartsWith("#region", StringComparison.Ordinal)
368368
&& NeedEndregion(textArea.Document))
369369
{
370370
textArea.Document.Insert(cursorOffset, "#endregion");
@@ -398,8 +398,8 @@ void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char
398398
IDocumentLine nextLine = lineNr + 1 <= textArea.Document.LineCount ? textArea.Document.GetLineByNumber(lineNr + 1) : null;
399399
string nextLineText = (nextLine != null) ? textArea.Document.GetText(nextLine) : "";
400400

401-
int indexAbove = lineAboveText.IndexOf("///");
402-
int indexNext = nextLineText.IndexOf("///");
401+
int indexAbove = lineAboveText.IndexOf("///", StringComparison.Ordinal);
402+
int indexNext = nextLineText.IndexOf("///", StringComparison.Ordinal);
403403
if (indexAbove > 0 && (indexNext != -1 || indexAbove + 4 < lineAbove.Length)) {
404404
textArea.Document.Insert(cursorOffset, "/// ");
405405
return;
@@ -413,7 +413,7 @@ void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char
413413
}
414414
if (textArea.Options.AutoInsertBlockEnd && lineAbove != null && isInNormalCode) {
415415
string oldLineText = textArea.Document.GetText(lineAbove);
416-
if (oldLineText.EndsWith("{")) {
416+
if (oldLineText.EndsWith("{", StringComparison.Ordinal)) {
417417
if (NeedCurlyBracket(textArea.Document.Text)) {
418418
int insertionPoint = curLine.Offset + curLine.Length;
419419
textArea.Document.Insert(insertionPoint, terminator + "}");

src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeActionProviderDoozer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ async delegate {
115115
CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false);
116116
var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken);
117117
return codeActionProvider.GetActions(refactoringContext).Select(Wrap).ToArray();
118+
} catch (OperationCanceledException) {
119+
throw; // don't catch cancellations
118120
} catch (Exception ex) {
119121
SD.Log.WarnFormatted("CSharpContextActionProviderWrapper crashed: {0}", ex);
120122
SD.AnalyticsMonitor.TrackException(ex);

0 commit comments

Comments
 (0)