diff options
author | Mike Krüger <mkrueger@xamarin.com> | 2017-09-14 19:11:51 +0300 |
---|---|---|
committer | Mike Krüger <mkrueger@xamarin.com> | 2017-09-14 19:11:51 +0300 |
commit | d981c2b0925ca56e21f779b85de021f926baad85 (patch) | |
tree | f59bcdf24e9026c52bd64a3e9d846cf24ca5efde /main/src/addins | |
parent | c7142878dcd8d27aef238320bbe73b5940bec6a2 (diff) | |
parent | 46267973e22b371bd270e4c4ef65fbcf4e390970 (diff) |
Merge branch 'master' into master-refactorings
Diffstat (limited to 'main/src/addins')
10 files changed, 126 insertions, 276 deletions
diff --git a/main/src/addins/CSharpBinding/CSharpBinding.csproj b/main/src/addins/CSharpBinding/CSharpBinding.csproj index a46b2df442..3e96de55c6 100644 --- a/main/src/addins/CSharpBinding/CSharpBinding.csproj +++ b/main/src/addins/CSharpBinding/CSharpBinding.csproj @@ -430,7 +430,6 @@ <Compile Include="MonoDevelop.CSharp.Features\GotoDefinition\GotoDefinitionHelpers.cs" /> <Compile Include="MonoDevelop.CSharp.Features\GotoDefinition\GotoDefinitionService.cs" /> <Compile Include="Util\PortingExtensions.cs" /> - <Compile Include="MonoDevelop.CSharp.Features\Formatter\SmartTokenFormatter.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Formatter/CSharpEditorFormattingService.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Formatter/CSharpEditorFormattingService.cs index 42cd28f7ec..0ff246db8a 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Formatter/CSharpEditorFormattingService.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Formatter/CSharpEditorFormattingService.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory6.CSharp public CSharpEditorFormattingService() { - _autoFormattingTriggerChars = ImmutableHashSet.CreateRange<char>(";}#ntef"); + _autoFormattingTriggerChars = ImmutableHashSet.CreateRange<char>(";}#nte"); // add all auto formatting trigger to supported char _supportedChars = _autoFormattingTriggerChars.Union("{}#nte:)"); @@ -185,56 +185,56 @@ namespace ICSharpCode.NRefactory6.CSharp return token; } - public static async Task<IList<TextChange>> FormatTokenAsync(Document document, SyntaxToken token, IEnumerable<IFormattingRule> formattingRules, CancellationToken cancellationToken) - { - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var formatter = CreateSmartTokenFormatter(document.Project.Solution.Workspace.Options, formattingRules, root); - var changes = await formatter.FormatTokenAsync(document.Project.Solution.Workspace, token, cancellationToken); - return changes; - } - - static SmartTokenFormatter CreateSmartTokenFormatter(OptionSet optionSet, IEnumerable<IFormattingRule> formattingRules, SyntaxNode root) - { - return new SmartTokenFormatter(optionSet, formattingRules, (CompilationUnitSyntax)root); - } - - public static async Task<IList<TextChange>> FormatRangeAsync( - Document document, SyntaxToken endToken, IEnumerable<IFormattingRule> formattingRules, - CancellationToken cancellationToken) - { - if (!IsEndToken(endToken)) - { - return SpecializedCollections.EmptyList<TextChange>(); - } - - var tokenRange = FormattingRangeHelper.FindAppropriateRange(endToken); - if (tokenRange == null || tokenRange.Value.Item1.Equals(tokenRange.Value.Item2)) - { - return SpecializedCollections.EmptyList<TextChange>(); - } - - if (IsInvalidTokenKind(tokenRange.Value.Item1) || IsInvalidTokenKind(tokenRange.Value.Item2)) - { - return SpecializedCollections.EmptyList<TextChange>(); - } - - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var formatter = new SmartTokenFormatter(document.Project.Solution.Workspace.Options, formattingRules, (CompilationUnitSyntax)root); - - var changes = formatter.FormatRange(document.Project.Solution.Workspace, tokenRange.Value.Item1, tokenRange.Value.Item2, cancellationToken); - return changes; - } - - static bool IsEndToken(SyntaxToken endToken) - { - if (endToken.IsKind(SyntaxKind.OpenBraceToken)) - { - return false; - } - - return true; - } - + // private async Task<IList<TextChange>> FormatTokenAsync(Document document, SyntaxToken token, IEnumerable<IFormattingRule> formattingRules, CancellationToken cancellationToken) + // { + // var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + // var formatter = CreateSmartTokenFormatter(document.Project.Solution.Workspace.Options, formattingRules, root); + // var changes = formatter.FormatToken(document.Project.Solution.Workspace, token, cancellationToken); + // return changes; + // } + // + // private ISmartTokenFormatter CreateSmartTokenFormatter(OptionSet optionSet, IEnumerable<IFormattingRule> formattingRules, SyntaxNode root) + // { + // return new SmartTokenFormatter(optionSet, formattingRules, (CompilationUnitSyntax)root); + // } + // + // private async Task<IList<TextChange>> FormatRangeAsync( + // Document document, SyntaxToken endToken, IEnumerable<IFormattingRule> formattingRules, + // CancellationToken cancellationToken) + // { + // if (!IsEndToken(endToken)) + // { + // return SpecializedCollections.EmptyList<TextChange>(); + // } + // + // var tokenRange = FormattingRangeHelper.FindAppropriateRange(endToken); + // if (tokenRange == null || tokenRange.Value.Item1.Equals(tokenRange.Value.Item2)) + // { + // return SpecializedCollections.EmptyList<TextChange>(); + // } + // + // if (IsInvalidTokenKind(tokenRange.Value.Item1) || IsInvalidTokenKind(tokenRange.Value.Item2)) + // { + // return SpecializedCollections.EmptyList<TextChange>(); + // } + // + // var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + // var formatter = new SmartTokenFormatter(document.Project.Solution.Workspace.Options, formattingRules, (CompilationUnitSyntax)root); + // + // var changes = formatter.FormatRange(document.Project.Solution.Workspace, tokenRange.Value.Item1, tokenRange.Value.Item2, cancellationToken); + // return changes; + // } + // + // private bool IsEndToken(SyntaxToken endToken) + // { + // if (endToken.IsKind(SyntaxKind.OpenBraceToken)) + // { + // return false; + // } + // + // return true; + // } + // public bool ValidSingleOrMultiCharactersTokenKind(char typedChar, SyntaxKind kind) { ImmutableHashSet<SyntaxKind> set; @@ -247,7 +247,7 @@ namespace ICSharpCode.NRefactory6.CSharp return set.Contains(kind); } - public static bool IsInvalidToken(char typedChar, SyntaxToken token) + public bool IsInvalidToken(char typedChar, SyntaxToken token) { string text = null; if (IsInvalidToken(token, ref text)) @@ -258,7 +258,7 @@ namespace ICSharpCode.NRefactory6.CSharp return text[0] != typedChar; } - public static bool IsInvalidToken(SyntaxToken token, ref string text) + public bool IsInvalidToken(SyntaxToken token, ref string text) { if (IsInvalidTokenKind(token)) { @@ -274,7 +274,7 @@ namespace ICSharpCode.NRefactory6.CSharp return false; } - static bool IsInvalidTokenKind(SyntaxToken token) + private bool IsInvalidTokenKind(SyntaxToken token) { // invalid token to be formatted return token.IsKind(SyntaxKind.None) || diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Formatter/SmartTokenFormatter.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Formatter/SmartTokenFormatter.cs deleted file mode 100644 index f7c2bf793b..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Formatter/SmartTokenFormatter.cs +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Extensions; -using Microsoft.CodeAnalysis.CSharp.Formatting; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Formatting.Rules; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; - -namespace ICSharpCode.NRefactory6.CSharp -{ - internal class SmartTokenFormatter - { - private readonly OptionSet _optionSet; - private readonly IEnumerable<IFormattingRule> _formattingRules; - - private readonly CompilationUnitSyntax _root; - - public SmartTokenFormatter( - OptionSet optionSet, - IEnumerable<IFormattingRule> formattingRules, - CompilationUnitSyntax root) - { - Contract.ThrowIfNull(optionSet); - Contract.ThrowIfNull(formattingRules); - Contract.ThrowIfNull(root); - - _optionSet = optionSet; - _formattingRules = formattingRules; - - _root = root; - } - - public IList<TextChange> FormatRange( - Workspace workspace, SyntaxToken startToken, SyntaxToken endToken, CancellationToken cancellationToken) - { - Contract.ThrowIfTrue(startToken.Kind() == SyntaxKind.None || startToken.Kind() == SyntaxKind.EndOfFileToken); - Contract.ThrowIfTrue(endToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.EndOfFileToken); - - var smartTokenformattingRules = _formattingRules; - var common = startToken.GetCommonRoot(endToken); - - // if there are errors, do not touch lines - // Exception 1: In the case of try-catch-finally block, a try block without a catch/finally block is considered incomplete - // but we would like to apply line operation in a completed try block even if there is no catch/finally block - // Exception 2: Similar behavior for do-while - if (common.ContainsDiagnostics && !CloseBraceOfTryOrDoBlock(endToken)) - { - smartTokenformattingRules = (new NoLineChangeFormattingRule()).Concat(_formattingRules); - } - - return Formatter.GetFormattedTextChanges(_root, new TextSpan[] { TextSpan.FromBounds(startToken.SpanStart, endToken.Span.End) }, workspace, _optionSet, smartTokenformattingRules, cancellationToken); - } - - private bool CloseBraceOfTryOrDoBlock(SyntaxToken endToken) - { - return endToken.IsKind(SyntaxKind.CloseBraceToken) && - endToken.Parent.IsKind(SyntaxKind.Block) && - (endToken.Parent.IsParentKind(SyntaxKind.TryStatement) || endToken.Parent.IsParentKind(SyntaxKind.DoStatement)); - } - - public async Task<IList<TextChange>> FormatTokenAsync( - Workspace workspace, SyntaxToken token, CancellationToken cancellationToken) - { - Contract.ThrowIfTrue(token.Kind() == SyntaxKind.None || token.Kind() == SyntaxKind.EndOfFileToken); - - // get previous token - var previousToken = token.GetPreviousToken(includeZeroWidth: true); - if (previousToken.Kind() == SyntaxKind.None) - { - // no previous token. nothing to format - return SpecializedCollections.EmptyList<TextChange>(); - } - - // This is a heuristic to prevent brace completion from breaking user expectation/muscle memory in common scenarios (see Devdiv:823958). - // Formatter uses FindToken on the position, which returns token to left, if there is nothing to the right and returns token to the right - // if there exists one. If the shape is "{|}", we're including '}' in the formatting range. Avoid doing that to improve verbatim typing - // in the following special scenarios. - int adjustedEndPosition = token.Span.End; - if (token.IsKind(SyntaxKind.OpenBraceToken) && - (token.Parent.IsInitializerForArrayOrCollectionCreationExpression() || - token.Parent is AnonymousObjectCreationExpressionSyntax)) - { - var nextToken = token.GetNextToken(includeZeroWidth: true); - if (nextToken.IsKind(SyntaxKind.CloseBraceToken)) - { - // Format upto '{' and exclude '}' - adjustedEndPosition = token.SpanStart; - } - } - - var smartTokenformattingRules = (new SmartTokenFormattingRule()).Concat(_formattingRules); - var adjustedStartPosition = previousToken.SpanStart; - var indentStyle = _optionSet.GetOption(FormattingOptions.SmartIndent, LanguageNames.CSharp); - if (token.IsKind(SyntaxKind.OpenBraceToken) && - indentStyle != FormattingOptions.IndentStyle.Smart) - { - var text = await token.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); - if (token.IsFirstTokenOnLine(text)) - { - adjustedStartPosition = token.SpanStart; - } - } - - return await Formatter.GetFormattedTextChangesAsync(_root, - new TextSpan[] { TextSpan.FromBounds(adjustedStartPosition, adjustedEndPosition) }, - workspace, _optionSet, smartTokenformattingRules, cancellationToken).ConfigureAwait(false); - } - - private class NoLineChangeFormattingRule : AbstractFormattingRule - { - public override AdjustNewLinesOperation GetAdjustNewLinesOperation(SyntaxToken previousToken, SyntaxToken currentToken, OptionSet optionSet, NextOperation<AdjustNewLinesOperation> nextOperation) - { - // no line operation. no line changes what so ever - var lineOperation = base.GetAdjustNewLinesOperation(previousToken, currentToken, optionSet, nextOperation); - if (lineOperation != null) - { - // ignore force if same line option - if (lineOperation.Option == AdjustNewLinesOption.ForceLinesIfOnSingleLine) - { - return null; - } - - // basically means don't ever put new line if there isn't already one, but do - // indentation. - return FormattingOperations.CreateAdjustNewLinesOperation(line: 0, option: AdjustNewLinesOption.PreserveLines); - } - - return null; - } - } - - private class SmartTokenFormattingRule : NoLineChangeFormattingRule - { - public override void AddSuppressOperations(List<SuppressOperation> list, SyntaxNode node, SyntaxToken lastToken, OptionSet optionSet, NextAction<SuppressOperation> nextOperation) - { - // don't suppress anything - } - - public override AdjustSpacesOperation GetAdjustSpacesOperation(SyntaxToken previousToken, SyntaxToken currentToken, OptionSet optionSet, NextOperation<AdjustSpacesOperation> nextOperation) - { - var spaceOperation = base.GetAdjustSpacesOperation(previousToken, currentToken, optionSet, nextOperation); - - // if there is force space operation, convert it to ForceSpaceIfSingleLine operation. - // (force space basically means remove all line breaks) - if (spaceOperation != null && spaceOperation.Option == AdjustSpacesOption.ForceSpaces) - { - return FormattingOperations.CreateAdjustSpacesOperation(spaceOperation.Space, AdjustSpacesOption.ForceSpacesIfOnSingleLine); - } - - return spaceOperation; - } - } - } -} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs index 8085f90997..e85128bbe7 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextEditorIndentation.cs @@ -13,10 +13,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -45,7 +45,6 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Options;
using MonoDevelop.Refactoring; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace MonoDevelop.CSharp.Formatting { @@ -191,7 +190,7 @@ namespace MonoDevelop.CSharp.Formatting } IdeApp.Workspace.ActiveConfigurationChanged -= HandleTextOptionsChanged; CompletionWindowManager.WindowClosed -= CompletionWindowManager_WindowClosed; - + stateTracker = null; base.Dispose (); } @@ -414,7 +413,7 @@ namespace MonoDevelop.CSharp.Formatting } return retval; } - + if (descriptor.SpecialKey == SpecialKey.Tab && descriptor.ModifierKeys == ModifierKeys.None && !CompletionWindowManager.IsVisible) { SafeUpdateIndentEngine (Editor.CaretOffset); if (stateTracker.IsInsideStringLiteral && !Editor.IsSomethingSelected) { @@ -463,9 +462,9 @@ namespace MonoDevelop.CSharp.Formatting bool returnBetweenBraces = - descriptor.SpecialKey == SpecialKey.Return && - descriptor.ModifierKeys == ModifierKeys.None && - Editor.CaretOffset > 0 && Editor.CaretOffset < Editor.Length && + descriptor.SpecialKey == SpecialKey.Return && + descriptor.ModifierKeys == ModifierKeys.None && + Editor.CaretOffset > 0 && Editor.CaretOffset < Editor.Length && Editor.GetCharAt (Editor.CaretOffset - 1) == '{' && Editor.GetCharAt (Editor.CaretOffset) == '}' && !stateTracker.IsInsideOrdinaryCommentOrString; bool automaticReindent; @@ -485,7 +484,7 @@ namespace MonoDevelop.CSharp.Formatting //handle inserted characters if (Editor.CaretOffset <= 0 || Editor.IsSomethingSelected) return retval; - + lastCharInserted = TranslateKeyCharForIndenter (descriptor.SpecialKey, descriptor.KeyChar, Editor.GetCharAt (Editor.CaretOffset - 1)); if (lastCharInserted == '\0') return retval; @@ -510,7 +509,7 @@ namespace MonoDevelop.CSharp.Formatting } } //reindent the line after the insertion, if needed - //N.B. if the engine says we need to reindent, make sure that it's because a char was + //N.B. if the engine says we need to reindent, make sure that it's because a char was //inserted rather than just updating the stack due to moving around SafeUpdateIndentEngine (Editor.CaretOffset); @@ -558,7 +557,7 @@ namespace MonoDevelop.CSharp.Formatting CheckXmlCommentCloseTag (descriptor.KeyChar); HandleOnTheFlyFormatting (descriptor); - + return result; } @@ -584,12 +583,7 @@ namespace MonoDevelop.CSharp.Formatting using (var undo = Editor.OpenUndoGroup ()) { if (OnTheFlyFormatting && Editor != null && Editor.EditMode == EditMode.Edit) { var oldVersion = Editor.Version; - int start = token.SpanStart; - var parentStatement = token.Parent.AncestorsAndSelf().OfType<StatementSyntax>().FirstOrDefault(); - if (parentStatement != null) - start = parentStatement.SpanStart; - OnTheFlyFormatter.Format(Editor, DocumentContext, start, Editor.CaretOffset, exact:true, optionSet: optionSet); - //OnTheFlyFormatter.FormatStatmentAt (Editor, DocumentContext, Editor.CaretLocation, optionSet: optionSet); + OnTheFlyFormatter.FormatStatmentAt (Editor, DocumentContext, Editor.CaretLocation, optionSet: optionSet); if (oldVersion.CompareAge (Editor.Version) != 0) CompletionWindowManager.HideWindow (); } @@ -617,7 +611,7 @@ namespace MonoDevelop.CSharp.Formatting var tokenRange = Microsoft.CodeAnalysis.CSharp.Utilities.FormattingRangeHelper.FindAppropriateRange (token); if (tokenRange == null || !tokenRange.HasValue || tokenRange.Value.Item1.Equals (tokenRange.Value.Item2)) return; - + var value = tokenRange.Value; using (var undo = Editor.OpenUndoGroup ()) { OnTheFlyFormatter.Format (Editor, DocumentContext, value.Item1.SpanStart, value.Item2.Span.End, optionSet: optionSet); @@ -635,7 +629,7 @@ namespace MonoDevelop.CSharp.Formatting return; string text = null; - if (CSharpEditorFormattingService.IsInvalidToken (token, ref text)) + if (service.IsInvalidToken (token, ref text)) return; // Check to see if the token is ')' and also the parent is a using statement. If not, bail if (CSharpEditorFormattingService.TokenShouldNotFormatOnReturn (token)) @@ -700,7 +694,7 @@ namespace MonoDevelop.CSharp.Formatting lastNonWsChar = ch; } return false; - }); + }); // if the line ends with ';' the line end is not the correct place for a new semicolon. if (lastNonWsChar == ';') return false; @@ -782,7 +776,7 @@ namespace MonoDevelop.CSharp.Formatting reIndent = true; break; case '\n': - if (completionWindowWasVisible) // \n is handled by an open completion window + if (completionWindowWasVisible) // \n is handled by an open completion window return; if (FixLineStart (Editor, stateTracker, Editor.OffsetToLineNumber (stateTracker.Offset))) return; @@ -887,7 +881,7 @@ namespace MonoDevelop.CSharp.Formatting } catch (Exception e) { LoggingService.LogError ("Exception during indentation", e); } - + int pos = line.Offset; string curIndent = line.GetIndentation (Editor); int nlwsp = curIndent.Length; diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/OnTheFlyFormatter.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/OnTheFlyFormatter.cs index a99fadc5bf..74c1e980dd 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/OnTheFlyFormatter.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/OnTheFlyFormatter.cs @@ -26,11 +26,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading; -using ICSharpCode.NRefactory6.CSharp; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; @@ -81,10 +77,8 @@ namespace MonoDevelop.CSharp.Formatting try { var syntaxTree = await analysisDocument.GetSyntaxTreeAsync (); var root = syntaxTree.GetRoot (); - bool smartIndentOnly = false; - var token = root.FindToken(endOffset); - smartIndentOnly = token.IsKind(SyntaxKind.CloseBraceToken); if (formatLastStatementOnly) { + var token = root.FindToken (endOffset); var tokens = Microsoft.CodeAnalysis.CSharp.Utilities.FormattingRangeHelper.FindAppropriateRange (token); if (tokens.HasValue) { span = new TextSpan (tokens.Value.Item1.SpanStart, editor.CaretOffset - tokens.Value.Item1.SpanStart); @@ -101,21 +95,8 @@ namespace MonoDevelop.CSharp.Formatting optionSet = policy.CreateOptions (textPolicy); } var rules = Formatter.GetDefaultFormattingRules (analysisDocument); - IList<TextChange> changes; - - if (smartIndentOnly) { - // if we're only doing smart indent, then ignore all edits to this token that occur before - // the span of the token. They're irrelevant and may screw up other code the user doesn't - // want touched. - var tokenEdits = await CSharpEditorFormattingService.FormatTokenAsync(analysisDocument, token, rules, default(CancellationToken)).ConfigureAwait(false); - changes = tokenEdits.Where(t => t.Span.Start >= token.FullSpan.Start).ToList(); - } else { - changes = await CSharpEditorFormattingService.FormatRangeAsync(analysisDocument, token, rules, default(CancellationToken)).ConfigureAwait(false); - if (changes.Count == 0) - changes = await CSharpEditorFormattingService.FormatTokenAsync(analysisDocument, token, rules, default(CancellationToken)).ConfigureAwait(false); - } - - editor.ApplyTextChanges(changes); + var changes = Formatter.GetFormattedTextChanges (root, SpecializedCollections.SingletonEnumerable (span), context.RoslynWorkspace, optionSet, rules, default(CancellationToken)); + editor.ApplyTextChanges (changes); } catch (Exception e) { LoggingService.LogError ("Error in on the fly formatter", e); } diff --git a/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs b/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs index a089a5dc61..3fd6f0b506 100644 --- a/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs +++ b/main/src/addins/MacPlatform/MacExternalConsoleProcess.cs @@ -145,12 +145,14 @@ bash pause on exit trick }; if (pauseWhenFinished) - sb.Append ("; echo; read -p 'Press any key to continue...' -n1"); + sb.Append ("; echo; read -p \"Press any key to continue...\" -n1"); sb.Append ("; exit"); } //run the command in Terminal.app and extract tab and window IDs - var ret = AppleScript.Run ("tell app \"{0}\" to do script \"{1}\"", TERMINAL_APP, Escape (sb.ToString ())); + // run the command inside Bash because we do echo $? and that is a bash extension and breaks when people + // use other shells such as zsh or fish. https://bugzilla.xamarin.com/show_bug.cgi?id=56053 + var ret = AppleScript.Run ("tell app \"{0}\" to do script \"bash -c '{1}'; exit\"", TERMINAL_APP, Escape (sb.ToString ())); int i = ret.IndexOf ("of", StringComparison.Ordinal); tabId = ret.Substring (0, i -1); windowId = ret.Substring (i + 3); diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTests.cs index 6722455f78..ed75ec4dd2 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTests.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTests.cs @@ -190,5 +190,30 @@ namespace MonoDevelop.DotNetCore.Tests Assert.IsNotNull (jsonNetReferenceLibB); Assert.IsNotNull (jsonNetReferenceLibC); } + + /// <summary> + /// Mirror Visual Studio on Windows behaviour where a .NET Standard project or a .NET Core + /// project can add a reference to any PCL project. + /// </summary> + [Test] + public async Task CanReference_PortableClassLibrary_FromNetStandardOrNetCoreAppProject () + { + string solutionFileName = Util.GetSampleProject ("dotnetcore-pcl", "dotnetcore-pcl.sln"); + var solution = (Solution) await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solutionFileName); + var pclProject = solution.FindProjectByName ("PclProfile111") as DotNetProject; + var netStandardProject = solution.FindProjectByName ("NetStandard14") as DotNetProject; + var netCoreProject = solution.FindProjectByName ("NetCore11") as DotNetProject; + + string reason = null; + bool canReferenceFromNetStandard = netStandardProject.CanReferenceProject (pclProject, out reason); + bool canReferenceFromNetCore = netCoreProject.CanReferenceProject (pclProject, out reason); + bool canReferenceNetCoreFromNetStandard = netStandardProject.CanReferenceProject (netCoreProject, out reason); + bool canReferenceNetStandardFromNetCore = netCoreProject.CanReferenceProject (netStandardProject, out reason); + + Assert.IsTrue (canReferenceFromNetStandard); + Assert.IsTrue (canReferenceFromNetCore); + Assert.IsFalse (canReferenceNetCoreFromNetStandard); + Assert.IsTrue (canReferenceNetStandardFromNetCore); + } } }
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs index c62b4595f5..b981c5f589 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs @@ -98,6 +98,9 @@ namespace MonoDevelop.DotNetCore bool CanReferenceProject (DotNetProject targetProject) { + if (targetProject.IsPortableLibrary) + return true; + if (!targetProject.TargetFramework.IsNetStandard ()) return false; diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingNuGetProject.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingNuGetProject.cs index 34d7a274bf..2db0f33801 100644 --- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingNuGetProject.cs +++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingNuGetProject.cs @@ -55,14 +55,17 @@ namespace MonoDevelop.Packaging InternalMetadata.Add (NuGetProjectMetadataKeys.UniqueName, project.Name); } - public override async Task<IEnumerable<NuGet.Packaging.PackageReference>> GetInstalledPackagesAsync (CancellationToken token) + public override Task<IEnumerable<NuGet.Packaging.PackageReference>> GetInstalledPackagesAsync (CancellationToken token) { - return await Runtime.RunInMainThread (() => { - return project - .PackageReferences - .Select (packageReference => packageReference.ToNuGetPackageReference ()) - .ToList (); - }); + return Task.FromResult (GetPackageReferences ()); + } + + IEnumerable<NuGet.Packaging.PackageReference> GetPackageReferences () + { + return project + .PackageReferences + .Select (packageReference => packageReference.ToNuGetPackageReference ()) + .ToList (); } public override async Task<bool> InstallPackageAsync ( diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs index 07c7c3f684..73588a7786 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs @@ -400,6 +400,7 @@ namespace MonoDevelop.SourceEditor if (extension is TopLevelWidgetExtension) { var widgetExtension = (TopLevelWidgetExtension)extension; Widget w = widgetExtension.CreateWidget (); + w.SizeAllocated += (o, args) => UpdateWidgetPosition(widgetExtension, w); int x, y; if (!CalcWidgetPosition (widgetExtension, w, out x, out y)) { w.Destroy (); @@ -466,14 +467,19 @@ namespace MonoDevelop.SourceEditor void UpdateWidgetPositions () { foreach (var e in widgetExtensions) { - int x,y; - if (CalcWidgetPosition ((TopLevelWidgetExtension)e.Key, e.Value, out x, out y)) - widget.TextEditor.TextArea.MoveTopLevelWidget (e.Value, x, y); - else - e.Value.Hide (); + UpdateWidgetPosition (e.Key, e.Value); } } + void UpdateWidgetPosition (TopLevelWidgetExtension widgetExtension, Widget w) + { + int x, y; + if (CalcWidgetPosition(widgetExtension, w, out x, out y)) + widget.TextEditor.TextArea.MoveTopLevelWidget(w, x, y); + else + w.Hide(); + } + bool CalcWidgetPosition (TopLevelWidgetExtension widgetExtension, Widget w, out int x, out int y) { DocumentLine line = widget.TextEditor.Document.GetLine (widgetExtension.Line); |