diff options
author | Matt Ward <matt.ward@xamarin.com> | 2017-07-25 18:59:45 +0300 |
---|---|---|
committer | Matt Ward <matt.ward@xamarin.com> | 2017-07-25 18:59:45 +0300 |
commit | 202808927267a66dc29375f7f5a05870a587b4ea (patch) | |
tree | 9e4d53a0cd6c703a4b1fdf1c21abe98507a4f9b3 /main/src | |
parent | 916957afd71fb68b2dffdfc043e9a4fdfbc9fd36 (diff) | |
parent | 45e6ac29cf6e32967709cd8959afe36567ad8777 (diff) |
Merge branch 'master' into nuget-support-asset-target-fallback
Diffstat (limited to 'main/src')
136 files changed, 2800 insertions, 752 deletions
diff --git a/main/src/addins/AspNet/Templates/MvcCommon/_Layout.cshtml b/main/src/addins/AspNet/Templates/MvcCommon/_Layout.cshtml index 547f680145..2843df700f 100644 --- a/main/src/addins/AspNet/Templates/MvcCommon/_Layout.cshtml +++ b/main/src/addins/AspNet/Templates/MvcCommon/_Layout.cshtml @@ -2,6 +2,7 @@ <html>
<head>
<title>@ViewBag.Title</title>
+ <meta charset="utf-8" />
</head>
<body>
@RenderBody()
diff --git a/main/src/addins/CSharpBinding/CSharpBinding.csproj b/main/src/addins/CSharpBinding/CSharpBinding.csproj index cf8543b3a4..2a2746c11d 100644 --- a/main/src/addins/CSharpBinding/CSharpBinding.csproj +++ b/main/src/addins/CSharpBinding/CSharpBinding.csproj @@ -168,7 +168,7 @@ <Private>False</Private> </Reference> <Reference Include="System.ValueTuple"> - <HintPath>..\..\..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath> + <HintPath>..\..\..\packages\System.ValueTuple.4.3.1\lib\netstandard1.0\System.ValueTuple.dll</HintPath> <Private>False</Private> </Reference> </ItemGroup> diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCodeCompletionFactory.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCodeCompletionFactory.cs index 4cd34d87c6..6104167644 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCodeCompletionFactory.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCodeCompletionFactory.cs @@ -112,8 +112,7 @@ namespace MonoDevelop.CSharp.Completion bool runCompletionCompletionCommand = false; var method = Symbol as IMethodSymbol; - bool addParens = IdeApp.Preferences.AddParenthesesAfterCompletion; - bool addOpeningOnly = IdeApp.Preferences.AddOpeningOnly; + bool addParens = DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket; var Editor = ext.Editor; var Policy = ext.FormattingPolicy; string insertionText = this.CompletionText; @@ -127,11 +126,7 @@ namespace MonoDevelop.CSharp.Completion var keys = new [] { SpecialKey.Return, SpecialKey.Tab, SpecialKey.Space }; if (keys.Contains (descriptor.SpecialKey) || descriptor.KeyChar == ' ') { - if (addOpeningOnly) { - insertionText += addSpace ? " (|" : "(|"; - } else { - insertionText += addSpace ? " (|)" : "(|)"; - } + insertionText += addSpace ? " (|)" : "(|)"; } ka |= KeyActions.Ignore; } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs index 37ed523e58..b1c19494f9 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs @@ -185,7 +185,7 @@ namespace MonoDevelop.CSharp.Completion replaceLength = partialWordLength; } int endOffset = Math.Min (window.StartOffset + replaceLength, window.CompletionWidget.TextLength); - if (descriptor.KeyChar == '(' && IdeApp.Preferences.AddParenthesesAfterCompletion) { + if (descriptor.KeyChar == '(' && DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket) { endOffset++; if (DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket) endOffset++; @@ -201,8 +201,7 @@ namespace MonoDevelop.CSharp.Completion bool runCompletionCompletionCommand = false; var method = Symbol as IMethodSymbol; - bool addParens = IdeApp.Preferences.AddParenthesesAfterCompletion; - bool addOpeningOnly = IdeApp.Preferences.AddOpeningOnly; + bool addParens = DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket; var Editor = ext.Editor; var Policy = ext.FormattingPolicy; var ctx = window.CodeCompletionContext; @@ -231,66 +230,56 @@ namespace MonoDevelop.CSharp.Completion var keys = new [] { SpecialKey.Return, SpecialKey.Tab, SpecialKey.Space }; if (keys.Contains (descriptor.SpecialKey) || descriptor.KeyChar == '.' || descriptor.KeyChar == '(') { if (HasAnyOverloadWithParameters (method)) { - if (addOpeningOnly) { - insertionText += RequireGenerics (method) ? "<|" : (addSpace ? " (|" : "(|"); + if (descriptor.KeyChar == '.') { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<> ()" : "<>()"; + } else { + insertionText += addSpace ? " ()" : "()"; + } skipChars = 0; } else { - if (descriptor.KeyChar == '.') { + if (insertSemicolon) { if (RequireGenerics (method)) { - insertionText += addSpace ? "<> ()" : "<>()"; + insertionText += addSpace ? "<|> ();" : "<|>();"; + skipChars = addSpace ? 5 : 4; } else { - insertionText += addSpace ? " ()" : "()"; + insertionText += addSpace ? " (|);" : "(|);"; + skipChars = 2; } - skipChars = 0; } else { - if (insertSemicolon) { - if (RequireGenerics (method)) { - insertionText += addSpace ? "<|> ();" : "<|>();"; - skipChars = addSpace ? 5 : 4; - } else { - insertionText += addSpace ? " (|);" : "(|);"; - skipChars = 2; - } + if (RequireGenerics (method)) { + insertionText += addSpace ? "<|> ()" : "<|>()"; + skipChars = addSpace ? 4 : 3; } else { - if (RequireGenerics (method)) { - insertionText += addSpace ? "<|> ()" : "<|>()"; - skipChars = addSpace ? 4 : 3; - } else { - insertionText += addSpace ? " (|)" : "(|)"; - skipChars = 1; - } + insertionText += addSpace ? " (|)" : "(|)"; + skipChars = 1; } } } runParameterCompletionCommand = true; } else { - if (addOpeningOnly) { - insertionText += RequireGenerics (method) ? "<|" : (addSpace ? " (|" : "(|"); + if (descriptor.KeyChar == '.') { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<> ()" : "<>()"; + } else { + insertionText += addSpace ? " ()" : "()"; + } skipChars = 0; } else { - if (descriptor.KeyChar == '.') { + if (insertSemicolon) { if (RequireGenerics (method)) { - insertionText += addSpace ? "<> ()" : "<>()"; + insertionText += addSpace ? "<|> ();" : "<|>();"; } else { - insertionText += addSpace ? " ()" : "()"; + insertionText += addSpace ? " ();|" : "();|"; } - skipChars = 0; - } else { - if (insertSemicolon) { - if (RequireGenerics (method)) { - insertionText += addSpace ? "<|> ();" : "<|>();"; - } else { - insertionText += addSpace ? " ();|" : "();|"; - } + } else { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<|> ()" : "<|>()"; } else { - if (RequireGenerics (method)) { - insertionText += addSpace ? "<|> ()" : "<|>()"; - } else { - insertionText += addSpace ? " ()|" : "()|"; - } - + insertionText += addSpace ? " ()|" : "()|"; } + } } } @@ -303,7 +292,7 @@ namespace MonoDevelop.CSharp.Completion } if ((DisplayFlags & DisplayFlags.NamedArgument) == DisplayFlags.NamedArgument && - IdeApp.Preferences.AddParenthesesAfterCompletion && + DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket && (descriptor.SpecialKey == SpecialKey.Tab || descriptor.SpecialKey == SpecialKey.Return || descriptor.SpecialKey == SpecialKey.Space)) { diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Completion/ContextHandler/RoslynRecommendationsCompletionContextHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Completion/ContextHandler/RoslynRecommendationsCompletionContextHandler.cs index b176c2dba1..ba91548b2f 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Completion/ContextHandler/RoslynRecommendationsCompletionContextHandler.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/Completion/ContextHandler/RoslynRecommendationsCompletionContextHandler.cs @@ -105,7 +105,11 @@ namespace ICSharpCode.NRefactory6.CSharp.Completion if (isInAttribute) { var type = (ITypeSymbol)symbol; if (type.IsAttribute ()) { - var v = type.Name.Substring (0, type.Name.Length - "Attribute".Length); + const string attributeSuffix = "Attribute"; + var v = type.Name.EndsWith (attributeSuffix, StringComparison.Ordinal) + ? type.Name.Substring (0, type.Name.Length - attributeSuffix.Length) + : type.Name; + var needsEscaping = SyntaxFacts.GetKeywordKind(v) != SyntaxKind.None; needsEscaping = needsEscaping || (isInQuery && SyntaxFacts.IsQueryContextualKeyword(SyntaxFacts.GetContextualKeywordKind(v))); if (!needsEscaping) { diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CodeGenerationPanel.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CodeGenerationPanel.cs index a651062891..ded7b3db7d 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CodeGenerationPanel.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CodeGenerationPanel.cs @@ -58,6 +58,7 @@ namespace MonoDevelop.CSharp.Project void SetupAccessibility () { + label81.Accessible.Role = Atk.Role.Filler; generateOverflowChecksCheckButton.SetCommonAccessibilityAttributes ("CompilerOptions.OverflowChecks", "", GettextCatalog.GetString ("Check this to enable overflow checking")); enableOptimizationCheckButton.SetCommonAccessibilityAttributes ("CompilerOptions.Optimizations", "", diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs index f2f6370aa1..e7c6da4235 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CompilerOptionsPanelWidget.cs @@ -58,16 +58,7 @@ namespace MonoDevelop.CSharp.Project CSharpCompilerParameters compilerParameters = (CSharpCompilerParameters) configuration.CompilationParameters; var csproject = (CSharpProject)project; - ListStore store = new ListStore (typeof (string));
- store.AppendValues (GettextCatalog.GetString ("Executable"));
- store.AppendValues (GettextCatalog.GetString ("Library")); - store.AppendValues (GettextCatalog.GetString ("Executable with GUI"));
- store.AppendValues (GettextCatalog.GetString ("Module"));
- compileTargetCombo.Model = store;
- CellRendererText cr = new CellRendererText ();
- compileTargetCombo.PackStart (cr, true);
- compileTargetCombo.AddAttribute (cr, "text", 0);
- compileTargetCombo.Active = (int) configuration.CompileTarget;
+ compileTargetCombo.CompileTarget = configuration.CompileTarget;
compileTargetCombo.Changed += new EventHandler (OnTargetChanged); if (project.IsLibraryBasedProjectType) { @@ -131,6 +122,7 @@ namespace MonoDevelop.CSharp.Project void SetupAccessibility () { + label76.Accessible.Role = Atk.Role.Filler; compileTargetCombo.SetCommonAccessibilityAttributes ("CodeGeneration.CompileTarget", label86, GettextCatalog.GetString ("Select the compile target for the code generation")); @@ -178,7 +170,6 @@ namespace MonoDevelop.CSharp.Project public void Store (ItemConfigurationCollection<ItemConfiguration> configs) { int codePage; - var compileTarget = (CompileTarget) compileTargetCombo.Active; var langVersion = LanguageVersion.Default; TreeIter iter; @@ -207,7 +198,7 @@ namespace MonoDevelop.CSharp.Project } else codePage = 0; - project.CompileTarget = compileTarget; + project.CompileTarget = compileTargetCombo.CompileTarget; var csproject = (CSharpProject)project; @@ -233,7 +224,7 @@ namespace MonoDevelop.CSharp.Project void UpdateTarget ()
{
- if ((CompileTarget) compileTargetCombo.Active == CompileTarget.Library) {
+ if (compileTargetCombo.CompileTarget == CompileTarget.Library) {
iconEntry.Sensitive = false;
} else {
iconEntry.Sensitive = true;
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpFindReferencesProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpFindReferencesProvider.cs index 0e455c79cc..3d4ad63add 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpFindReferencesProvider.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpFindReferencesProvider.cs @@ -48,7 +48,7 @@ namespace MonoDevelop.CSharp.Refactoring { public static LookupResult Failure = new LookupResult (); - public bool Success { get; private set; } + public bool Success { get; private set; } public ISymbol Symbol { get; private set; } public Solution Solution { get; private set; } public MonoDevelop.Projects.Project MonoDevelopProject { get; internal set; } @@ -71,8 +71,8 @@ namespace MonoDevelop.CSharp.Refactoring { if (string.IsNullOrEmpty (documentationCommentId)) return LookupResult.Failure; - bool searchNs = documentationCommentId[0] == 'N'; - bool searchType = documentationCommentId[0] == 'T'; + bool searchNs = documentationCommentId [0] == 'N'; + bool searchType = documentationCommentId [0] == 'T'; int reminderIndex = 2; var comp = await prj.GetCompilationAsync (token).ConfigureAwait (false); return await Task.Run (() => { @@ -101,7 +101,7 @@ namespace MonoDevelop.CSharp.Refactoring foreach (var member in type.GetMembers ()) { if (token.IsCancellationRequested) return LookupResult.Failure; -
+ if (member.GetDocumentationCommentId () == documentationCommentId) {
return new LookupResult (member, prj.Solution, comp);
}
@@ -163,14 +163,14 @@ namespace MonoDevelop.CSharp.Refactoring foreach (var subType in current.GetTypeMembers ()) { if (token.IsCancellationRequested) return null; - - var child = LookupType (documentationCommentId, idx + 1, subType, token); + + var child = LookupType (documentationCommentId, idx + 1, subType, token); if (child != null) { return child; } } return current; - + } return null; } @@ -182,10 +182,10 @@ namespace MonoDevelop.CSharp.Refactoring foreach (var subNamespace in current.GetNamespaceMembers ()) { if (token.IsCancellationRequested) return null; - + if (exact) { if (subNamespace.Name.Length == documentationCommentId.Length - reminder && - string.CompareOrdinal (documentationCommentId, reminder, subNamespace.Name, 0, subNamespace.Name.Length) == 0) + string.CompareOrdinal (documentationCommentId, reminder, subNamespace.Name, 0, subNamespace.Name.Length) == 0) return subNamespace; } else { if (subNamespace.Name.Length < documentationCommentId.Length - reminder - 1 && @@ -206,9 +206,9 @@ namespace MonoDevelop.CSharp.Refactoring var result = new List<SearchResult> (); var antiDuplicatesSet = new HashSet<SearchResult> (new SearchResultComparer ()); var lookup = await TryLookupSymbol (documentationCommentId, hintProject, token); - if (lookup == null || !lookup.Success) + if (lookup == null || !lookup.Success) return Enumerable.Empty<SearchResult> (); - + var workspace = TypeSystemService.AllWorkspaces.FirstOrDefault (w => w.CurrentSolution == lookup.Solution) as MonoDevelopWorkspace; if (workspace == null) return Enumerable.Empty<SearchResult> (); @@ -282,41 +282,50 @@ namespace MonoDevelop.CSharp.Refactoring var workspace = TypeSystemService.AllWorkspaces.FirstOrDefault (w => w.CurrentSolution == lookup.Solution) as MonoDevelopWorkspace; if (workspace == null) return Enumerable.Empty<SearchResult> (); - foreach (var curSymbol in lookup.Symbol.ContainingType.GetMembers ().Where (m => m.Kind == lookup.Symbol.Kind && m.Name == lookup.Symbol.Name)) { - foreach (var sym in SymbolFinder.FindSimilarSymbols (curSymbol, lookup.Compilation)) { - foreach (var simSym in await GatherSymbols (sym, lookup.Solution, token)) { - foreach (var loc in simSym.Locations) { - if (!loc.IsInSource) - continue; - var sr = new SearchResult (new FileProvider (loc.SourceTree.FilePath), loc.SourceSpan.Start, loc.SourceSpan.Length); - if (antiDuplicatesSet.Add (sr)) { - result.Add (sr); - } - } - - foreach (var mref in await SymbolFinder.FindReferencesAsync (simSym, lookup.Solution).ConfigureAwait (false)) { - foreach (var loc in mref.Locations) { - var fileName = loc.Document.FilePath; - var offset = loc.Location.SourceSpan.Start; - string projectedName; - int projectedOffset; - if (workspace.TryGetOriginalFileFromProjection (fileName, offset, out projectedName, out projectedOffset)) { - fileName = projectedName; - offset = projectedOffset; - } - - var sr = new SearchResult (new FileProvider (fileName), offset, loc.Location.SourceSpan.Length); - if (antiDuplicatesSet.Add (sr)) { - result.Add (sr); - } - } + if (lookup.Symbol.Kind == SymbolKind.Method) { + foreach (var curSymbol in lookup.Symbol.ContainingType.GetMembers ().Where (m => m.Kind == lookup.Symbol.Kind && m.Name == lookup.Symbol.Name)) { + foreach (var sym in SymbolFinder.FindSimilarSymbols (curSymbol, lookup.Compilation)) { + foreach (var simSym in await GatherSymbols (sym, lookup.Solution, token)) { + await FindSymbolReferencesAsync (antiDuplicatesSet, result, lookup, workspace, simSym); } } } + } else { + await FindSymbolReferencesAsync (antiDuplicatesSet, result, lookup, workspace, lookup.Symbol); } return (IEnumerable<SearchResult>)result; }); } + + static async Task FindSymbolReferencesAsync (HashSet<SearchResult> antiDuplicatesSet, List<SearchResult> result, LookupResult lookup, MonoDevelopWorkspace workspace, ISymbol simSym) + { + foreach (var loc in simSym.Locations) { + if (!loc.IsInSource) + continue; + var sr = new SearchResult (new FileProvider (loc.SourceTree.FilePath), loc.SourceSpan.Start, loc.SourceSpan.Length); + if (antiDuplicatesSet.Add (sr)) { + result.Add (sr); + } + } + + foreach (var mref in await SymbolFinder.FindReferencesAsync (simSym, lookup.Solution).ConfigureAwait (false)) { + foreach (var loc in mref.Locations) { + var fileName = loc.Document.FilePath; + var offset = loc.Location.SourceSpan.Start; + string projectedName; + int projectedOffset; + if (workspace.TryGetOriginalFileFromProjection (fileName, offset, out projectedName, out projectedOffset)) { + fileName = projectedName; + offset = projectedOffset; + } + + var sr = new SearchResult (new FileProvider (fileName), offset, loc.Location.SourceSpan.Length); + if (antiDuplicatesSet.Add (sr)) { + result.Add (sr); + } + } + } + } } - + } diff --git a/main/src/addins/CSharpBinding/gtk-gui/MonoDevelop.CSharp.Project.CompilerOptionsPanelWidget.cs b/main/src/addins/CSharpBinding/gtk-gui/MonoDevelop.CSharp.Project.CompilerOptionsPanelWidget.cs index 9c54345a54..07dd324940 100644 --- a/main/src/addins/CSharpBinding/gtk-gui/MonoDevelop.CSharp.Project.CompilerOptionsPanelWidget.cs +++ b/main/src/addins/CSharpBinding/gtk-gui/MonoDevelop.CSharp.Project.CompilerOptionsPanelWidget.cs @@ -20,7 +20,7 @@ namespace MonoDevelop.CSharp.Project private global::Gtk.HBox hbox57; - private global::Gtk.ComboBox compileTargetCombo; + private MonoDevelop.Ide.Gui.OptionPanels.DotNetCompileTargetSelector compileTargetCombo; private global::MonoDevelop.Components.FileEntry iconEntry; @@ -112,7 +112,7 @@ namespace MonoDevelop.CSharp.Project this.hbox57 = new global::Gtk.HBox (); this.hbox57.Name = "hbox57"; // Container child hbox57.Gtk.Box+BoxChild - this.compileTargetCombo = new global::Gtk.ComboBox (); + this.compileTargetCombo = new MonoDevelop.Ide.Gui.OptionPanels.DotNetCompileTargetSelector(); this.compileTargetCombo.Name = "compileTargetCombo"; this.hbox57.Add (this.compileTargetCombo); global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox57 [this.compileTargetCombo])); diff --git a/main/src/addins/CSharpBinding/gtk-gui/gui.stetic b/main/src/addins/CSharpBinding/gtk-gui/gui.stetic index 5f3d55580e..09142aa1e5 100644 --- a/main/src/addins/CSharpBinding/gtk-gui/gui.stetic +++ b/main/src/addins/CSharpBinding/gtk-gui/gui.stetic @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <stetic-interface> <configuration> <images-root-path>..</images-root-path> @@ -589,7 +589,7 @@ None</property> <widget class="Gtk.HBox" id="hbox57"> <property name="MemberName" /> <child> - <widget class="Gtk.ComboBox" id="compileTargetCombo"> + <widget class="MonoDevelop.Ide.Gui.OptionPanels.DotNetCompileTargetSelector" id="compileTargetCombo"> <property name="MemberName" /> <property name="IsTextCombo">False</property> <property name="Items" /> @@ -1674,4 +1674,4 @@ None</property> </widget> </child> </widget> -</stetic-interface>
\ No newline at end of file +</stetic-interface> diff --git a/main/src/addins/CSharpBinding/packages.config b/main/src/addins/CSharpBinding/packages.config index 8c56e0c54c..9958f16fbb 100644 --- a/main/src/addins/CSharpBinding/packages.config +++ b/main/src/addins/CSharpBinding/packages.config @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="System.ValueTuple" version="4.3.0" targetFramework="net461" /> + <package id="System.ValueTuple" version="4.3.1" targetFramework="net461" /> </packages>
\ No newline at end of file diff --git a/main/src/addins/MacPlatform/MacPlatform.cs b/main/src/addins/MacPlatform/MacPlatform.cs index 3f8f857cb7..42b47fc36b 100644 --- a/main/src/addins/MacPlatform/MacPlatform.cs +++ b/main/src/addins/MacPlatform/MacPlatform.cs @@ -174,7 +174,8 @@ namespace MonoDevelop.MacIntegration var keyboardMode = NSUserDefaults.StandardUserDefaults.IntForKey ("AppleKeyboardUIMode"); // 0 - Text boxes and lists only // 2 - All controls - if (keyboardMode == 2) { + // 3 - All controls + keyboard access + if (keyboardMode != 0) { Gtk.Rc.ParseString ("style \"default\" { engine \"xamarin\" { focusstyle = 2 } }"); Gtk.Rc.ParseString ("style \"radio-or-check-box\" { engine \"xamarin\" { focusstyle = 2 } } "); } diff --git a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.csproj b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.csproj index cca9a4aa83..0db8172cb0 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.csproj +++ b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.csproj @@ -175,6 +175,6 @@ <Version>$(TemplatesVersion)</Version> </NuGetPackage> </ItemGroup> - <Copy SourceFiles="..\..\..\packages\%(NuGetPackage.Identity).%(NuGetPackage.Version)\%(NuGetPackage.Identity).%(NuGetPackage.Version).nupkg" DestinationFolder="$(OutputPath)\Templates" /> + <Copy SourceFiles="..\..\..\packages\%(NuGetPackage.Identity).%(NuGetPackage.Version)\%(NuGetPackage.Identity).%(NuGetPackage.Version).nupkg" DestinationFolder="$(OutputPath)\Templates" SkipUnchangedFiles="true" /> </Target> </Project>
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj index 5379281ee3..51fdd1a28c 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj @@ -201,6 +201,7 @@ <Compile Include="gtk-gui\MonoDevelop.Debugger.DebugApplicationDialog.cs" /> <Compile Include="MonoDevelop.Debugger\DebugApplicationDialog.cs" /> <Compile Include="MonoDevelop.Debugger\Styles.cs" /> + <Compile Include="MonoDevelop.Debugger\ProcessAttacher.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDevelop.Debugger.addin.xml"> diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs index 0b95d4c645..e77429f1ef 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs @@ -32,35 +32,36 @@ using MonoDevelop.Components; using Mono.Debugging.Client; using MonoDevelop.Ide.Gui; using System.Threading; +using System.Linq; +using MonoDevelop.Projects; +using MonoDevelop.Core.Execution; +using MonoDevelop.Ide; namespace MonoDevelop.Debugger { public partial class AttachToProcessDialog : Gtk.Dialog { - List<DebuggerEngine> currentDebEngines; - Dictionary<long, List<DebuggerEngine>> procEngines; - List<ProcessInfo> procs; + List<DebuggerEngine> debugEngines = new List<DebuggerEngine> (); + DebuggerEngine selectedEngine; + ProcessInfo [] procs; Gtk.ListStore store; TreeViewState state; - bool closed; + ProcessAttacher processAttacher; + CancellationTokenSource refreshLoopTokenSource = new CancellationTokenSource (); - public AttachToProcessDialog() + public AttachToProcessDialog () { - this.Build(); + this.Build (); - store = new Gtk.ListStore (typeof(ProcessInfo), typeof(string), typeof(string)); + store = new Gtk.ListStore (typeof (ProcessInfo), typeof (string), typeof (string), typeof (string)); tree.Model = store; tree.AppendColumn ("PID", new Gtk.CellRendererText (), "text", 1); - tree.AppendColumn (GettextCatalog.GetString ("Process Name"), new Gtk.CellRendererText (), "text", 2); + tree.AppendColumn (GettextCatalog.GetString ("Name"), new Gtk.CellRendererText (), "text", 2); + tree.AppendColumn (GettextCatalog.GetString ("Description"), new Gtk.CellRendererText (), "text", 3); tree.RowActivated += OnRowActivated; state = new TreeViewState (tree, 1); - var refreshThread = new Thread (new ThreadStart (Refresh)); - refreshThread.IsBackground = true; - refreshThread.Start (); - - comboDebs.Sensitive = false; buttonOk.Sensitive = false; tree.Selection.UnselectAll (); tree.Selection.Changed += OnSelectionChanged; @@ -68,41 +69,90 @@ namespace MonoDevelop.Debugger Gtk.TreeIter it; if (store.GetIterFirst (out it)) tree.Selection.SelectIter (it); + + //Logic below tries to CreateExecutionCommand which is used to determine default debug engine + var startupConfig = IdeApp.ProjectOperations.CurrentSelectedSolution?.StartupConfiguration as SingleItemSolutionRunConfiguration; + ExecutionCommand executionCommand = null; + if (startupConfig?.Item is DotNetProject dnp) { + var config = dnp.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration; + var runProjectConfiguration = startupConfig.RunConfiguration as ProjectRunConfiguration ?? dnp.GetDefaultRunConfiguration () as ProjectRunConfiguration; + if (config != null) { + executionCommand = dnp.CreateExecutionCommand (IdeApp.Workspace.ActiveConfiguration, config, runProjectConfiguration); + } + } + DebuggerEngine defaultEngine = null; + foreach (DebuggerEngine de in DebuggingService.GetDebuggerEngines ()) { + if ((de.SupportedFeatures & DebuggerFeatures.Attaching) == 0) + continue; + if (executionCommand != null && de.CanDebugCommand (executionCommand)) + defaultEngine = de; + debugEngines.Add (de); + comboDebs.AppendText (de.Name); + } + if (!debugEngines.Any ()) + return; + if (defaultEngine == null) + defaultEngine = debugEngines.First (); + comboDebs.Active = debugEngines.IndexOf (defaultEngine); + ChangeEngine (defaultEngine); + comboDebs.Changed += delegate { + ChangeEngine (debugEngines [comboDebs.Active]); + }; + } + + private void ChangeEngine (DebuggerEngine newEngine) + { + if (selectedEngine == newEngine) + return; + selectedEngine = newEngine; + + refreshLoopTokenSource.Cancel (); + refreshLoopTokenSource = new CancellationTokenSource (); + + if (processAttacher != null) { + processAttacher.AttachableProcessesChanged -= ProcessAttacher_AttachableProcessesChanged; + processAttacher.Dispose (); + } + + processAttacher = selectedEngine.GetProcessAttacher (); + if (processAttacher != null) { + processAttacher.AttachableProcessesChanged += ProcessAttacher_AttachableProcessesChanged; + this.procs = processAttacher.GetAttachableProcesses (); + Runtime.RunInMainThread (new Action (FillList)).Ignore (); + } else { + var refreshThread = new Thread (new ParameterizedThreadStart (Refresh)); + refreshThread.IsBackground = true; + refreshThread.Start (refreshLoopTokenSource.Token); + } + } + + void ProcessAttacher_AttachableProcessesChanged (Debugger.ProcessAttacher sender) + { + this.procs = sender.GetAttachableProcesses (); + Runtime.RunInMainThread (new Action (FillList)).Ignore (); } public override void Destroy () { - closed = true; + if (processAttacher != null) { + processAttacher.AttachableProcessesChanged -= ProcessAttacher_AttachableProcessesChanged; + processAttacher.Dispose (); + } + refreshLoopTokenSource.Cancel (); base.Destroy (); } - void Refresh () + void Refresh (object tokenObject) { - while (!closed) { - var procEngines = new Dictionary<long, List<DebuggerEngine>> (); - var procs = new List<ProcessInfo> (); - - foreach (DebuggerEngine de in DebuggingService.GetDebuggerEngines ()) { - if ((de.SupportedFeatures & DebuggerFeatures.Attaching) == 0) - continue; - try { - var infos = de.GetAttachableProcesses (); - foreach (ProcessInfo pi in infos) { - List<DebuggerEngine> engs; - if (!procEngines.TryGetValue (pi.Id, out engs)) { - engs = new List<DebuggerEngine> (); - procEngines [pi.Id] = engs; - procs.Add (pi); - } - engs.Add (de); - } - } catch (Exception ex) { - LoggingService.LogError ("Could not get attachable processes.", ex); - } + var token = (CancellationToken)tokenObject; + var engine = selectedEngine; + while (!token.IsCancellationRequested) { + try { + this.procs = engine.GetAttachableProcesses (); + } catch (Exception ex) { + LoggingService.LogError ("Could not get attachable processes.", ex); } - this.procEngines = procEngines; - this.procs = procs; - Runtime.RunInMainThread (new Action(FillList)).Ignore (); + Runtime.RunInMainThread (new Action (FillList)).Ignore (); Thread.Sleep (3000); } } @@ -113,13 +163,21 @@ namespace MonoDevelop.Debugger tree.Model = null; store.Clear (); string filter = entryFilter.Text; + bool anyPidSet = false; + bool anyDescriptionSet = false; foreach (ProcessInfo pi in procs) { - if (filter.Length == 0 || pi.Id.ToString().Contains (filter) || pi.Name.Contains (filter)) - store.AppendValues (pi, pi.Id.ToString (), pi.Name); + if (pi.Id != 0) + anyPidSet = true; + if (pi.Description != null) + anyDescriptionSet = true; + if (filter.Length == 0 || (pi.Id != 0 && pi.Id.ToString ().Contains (filter)) || pi.Name.Contains (filter) || (pi.Description?.Contains (filter) ?? false)) + store.AppendValues (pi, pi.Id.ToString (), pi.Name, pi.Description); } + tree.Columns [0].Visible = anyPidSet; + tree.Columns [2].Visible = anyDescriptionSet; tree.Model = store; state.Load (); - + tree.ColumnsAutosize (); if (tree.Selection.CountSelectedRows () == 0) { Gtk.TreeIter it; if (store.GetIterFirst (out it)) @@ -129,21 +187,10 @@ namespace MonoDevelop.Debugger void OnSelectionChanged (object s, EventArgs args) { - ((Gtk.ListStore)comboDebs.Model).Clear (); - Gtk.TreeIter iter; if (tree.Selection.GetSelected (out iter)) { - ProcessInfo pi = (ProcessInfo) store.GetValue (iter, 0); - currentDebEngines = procEngines [pi.Id]; - foreach (DebuggerEngine de in currentDebEngines) { - comboDebs.AppendText (de.Name); - } - comboDebs.Sensitive = true; - buttonOk.Sensitive = currentDebEngines.Count > 0; - comboDebs.Active = 0; - } - else { - comboDebs.Sensitive = false; + buttonOk.Sensitive = true; + } else { buttonOk.Sensitive = false; } } @@ -162,13 +209,13 @@ namespace MonoDevelop.Debugger get { Gtk.TreeIter iter; tree.Selection.GetSelected (out iter); - return (ProcessInfo) store.GetValue (iter, 0); + return (ProcessInfo)store.GetValue (iter, 0); } } public DebuggerEngine SelectedDebugger { get { - return currentDebEngines [comboDebs.Active]; + return selectedEngine; } } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs index dca6dac7f8..8727d98594 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPropertiesDialog.cs @@ -54,7 +54,7 @@ namespace MonoDevelop.Debugger Catchpoint } - sealed class BreakpointPropertiesDialog : Dialog + sealed class BreakpointPropertiesDialog : Xwt.Dialog { // For button sensitivity. DialogButton buttonOk; @@ -121,6 +121,7 @@ namespace MonoDevelop.Debugger Task.Run (LoadExceptionList); Initialize (); SetInitialData (); + SetAccessibility (); SetLayout (); if (be == null) { switch (breakpointType) { @@ -649,18 +650,108 @@ namespace MonoDevelop.Debugger return be; } + void SetAccessibility () + { + var accessible = breakpointActionPause.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.Pause"; + accessible.Description = GettextCatalog.GetString ("Cause the program to pause when the breakpoint is hit"); + + accessible = breakpointActionPrint.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.Print"; + accessible.Description = GettextCatalog.GetString ("Cause the program to print a message and continue when the breakpoint is hit"); + + accessible = entryPrintExpression.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.PrintExpression"; + accessible.Label = GettextCatalog.GetString ("Breakpoint Expression"); + accessible.Description = GettextCatalog.GetString ("Enter the expression you wish to have printed to the console. Place simple C# expressions within {} to interpolate them."); + + accessible = warningPrintExpression.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.WarningPrintExpression"; + accessible.Description = GettextCatalog.GetString ("There is a warning for the print expression"); + + accessible = stopOnFunction.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.StopOnFunction"; + accessible.Description = GettextCatalog.GetString ("Execute the action when a function is entered"); + + accessible = entryFunctionName.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.FunctionName"; + accessible.Label = GettextCatalog.GetString ("Breakpoint Function"); + accessible.Description = GettextCatalog.GetString ("Enter the name of the breakpoint function"); + + accessible = warningFunction.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.WarningFunction"; + accessible.Description = GettextCatalog.GetString ("There is a warning for the function name"); + + accessible = stopOnException.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.StopOnException"; + accessible.Description = GettextCatalog.GetString ("Execute the action when an exception is thrown"); + + accessible = entryExceptionType.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.ExceptionType"; + accessible.Label = GettextCatalog.GetString ("Breakpoint Exception"); + accessible.Description = GettextCatalog.GetString ("Enter the type of the breakpoint exception"); + + accessible = warningException.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.WarningException"; + accessible.Description = GettextCatalog.GetString ("There is a warning for the exception type"); + + accessible = checkIncludeSubclass.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.IncludeSubclasses"; + accessible.Description = GettextCatalog.GetString ("Select whether to also break on exception subclasses"); + + accessible = stopOnLocation.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.StopOnLocation"; + accessible.Description = GettextCatalog.GetString ("Execute the action when the program reaches a location in a file"); + + accessible = entryLocationFile.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.FileLocation"; + accessible.Label = GettextCatalog.GetString ("Breakpoint Location"); + accessible.Description = GettextCatalog.GetString ("Enter the file and line number of the breakpoint location"); + + accessible = warningLocation.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.WarningLocation"; + accessible.Description = GettextCatalog.GetString ("There is a warning for the breakpoint location"); + + accessible = ignoreHitType.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.HitType"; + accessible.Label = GettextCatalog.GetString ("Breakpoint Hit Count Type"); + accessible.Description = GettextCatalog.GetString ("Select a hit count condition for this breakpoint"); + + accessible = ignoreHitCount.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.HitCount"; + accessible.Label = GettextCatalog.GetString ("Hit Count"); + accessible.Description = GettextCatalog.GetString ("Enter the hit count required for the condition"); + + accessible = conditionalHitType.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.ConditionalHit"; + accessible.Label = GettextCatalog.GetString ("Conditional Breakpoint Hit Type"); + accessible.Description = GettextCatalog.GetString ("Select an extra condition for this breakpoint"); + + accessible = entryConditionalExpression.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.ConditionEntry"; + accessible.Label = GettextCatalog.GetString ("Conditional Breakpoint Expression"); + accessible.Description = GettextCatalog.GetString ("Enter a C# boolean expression to act as a condition for this breakpoint. The scope of the expression is local to the breakpoint"); + + accessible = warningCondition.Accessible; + accessible.Identifier = "BreakpointPropertiesDialog.WarningCondition"; + accessible.Description = GettextCatalog.GetString ("There is a warning for the condition expression"); + } + void SetLayout () { var vbox = new VBox (); + vbox.Accessible.Role = Xwt.Accessibility.Role.Filler; vbox.MinWidth = 450; - vbox.PackStart (new Label (GettextCatalog.GetString ("Breakpoint Action")) { + var actionLabel = new Label (GettextCatalog.GetString ("Breakpoint Action")) { Font = vbox.Font.WithWeight (FontWeight.Bold) - }); + }; + vbox.PackStart (actionLabel); var breakpointActionGroup = new VBox { MarginLeft = 12 }; + breakpointActionGroup.Accessible.Role = Xwt.Accessibility.Role.Filler; breakpointActionGroup.PackStart (breakpointActionPause); breakpointActionGroup.PackStart (breakpointActionPrint); @@ -669,7 +760,13 @@ namespace MonoDevelop.Debugger MarginLeft = 18 }; + printExpressionGroup.Accessible.Role = Xwt.Accessibility.Role.Filler; + printExpressionGroup.PackStart (entryPrintExpression, true); + + // We'll ignore this label because the content of the label is included in the accessibility Help text of the + // entryPrintExpression widget + warningPrintExpression.Accessible.Role = Xwt.Accessibility.Role.Filler; printExpressionGroup.PackStart (warningPrintExpression); breakpointActionGroup.PackStart (printExpressionGroup); @@ -677,13 +774,15 @@ namespace MonoDevelop.Debugger vbox.PackStart (breakpointActionGroup); - vbox.PackStart (new Label (GettextCatalog.GetString ("When to Take Action")) { + var whenLabel = new Label (GettextCatalog.GetString ("When to Take Action")) { Font = vbox.Font.WithWeight (FontWeight.Bold) - }); + }; + vbox.PackStart (whenLabel); var whenToTakeActionRadioGroup = new VBox { MarginLeft = 12 }; + whenToTakeActionRadioGroup.Accessible.Role = Xwt.Accessibility.Role.Filler; // Function group { @@ -700,6 +799,8 @@ namespace MonoDevelop.Debugger whenToTakeActionRadioGroup.PackStart (stopOnException); hboxException = new HBox (); + hboxException.Accessible.Role = Xwt.Accessibility.Role.Filler; + hboxException.PackStart (entryExceptionType, true); hboxException.PackEnd (warningException); @@ -720,23 +821,31 @@ namespace MonoDevelop.Debugger } vbox.PackStart (whenToTakeActionRadioGroup); - vbox.PackStart (new Label (GettextCatalog.GetString ("Advanced Conditions")) { + var advancedLabel = new Label (GettextCatalog.GetString ("Advanced Conditions")) { Font = vbox.Font.WithWeight (FontWeight.Bold) - }); + }; + vbox.PackStart (advancedLabel); var vboxAdvancedConditions = new VBox { MarginLeft = 30 }; + vboxAdvancedConditions.Accessible.Role = Xwt.Accessibility.Role.Filler; + var hboxHitCount = new HBox (); + hboxHitCount.Accessible.Role = Xwt.Accessibility.Role.Filler; hboxHitCount.PackStart (ignoreHitType, true); hboxHitCount.PackStart (ignoreHitCount); vboxAdvancedConditions.PackStart (hboxHitCount); vboxAdvancedConditions.PackStart (conditionalHitType); hboxCondition = new HBox (); + hboxCondition.Accessible.Role = Xwt.Accessibility.Role.Filler; + hboxCondition.PackStart (entryConditionalExpression, true); hboxCondition.PackStart (warningCondition); vboxAdvancedConditions.PackStart (hboxCondition); + + conditionalExpressionTip.Accessible.Role = Xwt.Accessibility.Role.Filler; vboxAdvancedConditions.PackEnd (conditionalExpressionTip); vbox.PackStart (vboxAdvancedConditions); diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngine.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngine.cs index 605a3c3906..b07b3952c6 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngine.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngine.cs @@ -94,7 +94,14 @@ namespace MonoDevelop.Debugger LoadEngine (); return engine.CreateDebuggerStartInfo (cmd); } - + + public ProcessAttacher GetProcessAttacher () + { + LoadEngine (); + + return engine?.GetProcessAttacher (); + } + public ProcessInfo[] GetAttachableProcesses () { LoadEngine (); diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngineBackend.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngineBackend.cs index be5e10e002..caa5139161 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngineBackend.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerEngineBackend.cs @@ -50,6 +50,20 @@ namespace MonoDevelop.Debugger return new ProcessInfo[0]; } + /// <summary> + /// <see cref="GetProcessAttacher"/> has two advantages over <see cref="GetAttachableProcesses"/>: + /// 1) it gives debugger engine ability to update processes list as soon as it discovers new processes via <see cref="ProcessAttacher.AttachableProcessesChanged"/> + /// 2) it gives debugger engine lifetime information via <see cref="ProcessAttacher.Dispose"/>, so debugger engine can clean resources used to look for processes e.g. loop thread, sockets... + /// </summary> + /// <remarks> + /// If this method returns valid <see cref="ProcessAttacher"/>, <see cref="GetAttachableProcesses"/> won't be called. + /// </remarks> + /// <returns>The process attacher.</returns> + public virtual ProcessAttacher GetProcessAttacher () + { + return null; + } + public abstract DebuggerSession CreateSession (); } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs index 27e6da652c..1d3692426e 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs @@ -254,11 +254,11 @@ namespace MonoDevelop.Debugger return GetSetConverter<T> (val) != null; } - public static void ShowValueVisualizer (ObjectValue val) + public static bool ShowValueVisualizer (ObjectValue val) { using (var dlg = new ValueVisualizerDialog ()) { dlg.Show (val); - MessageService.ShowCustomDialog (dlg); + return MessageService.ShowCustomDialog (dlg) == (int)Gtk.ResponseType.Ok; } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs index 4bfec4d843..3d28974ddd 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs @@ -79,6 +79,7 @@ namespace MonoDevelop.Debugger readonly ValueCellRenderer crtValue; readonly CellRendererText crtType; readonly CellRendererRoundedButton crpButton; + readonly CellRendererImage evaluateStatusCell; readonly CellRendererImage crpPin; readonly CellRendererImage crpLiveUpdate; readonly CellRendererImage crpViewer; @@ -343,7 +344,7 @@ namespace MonoDevelop.Debugger valueCol = new TreeViewColumn (); valueCol.Title = GettextCatalog.GetString ("Value"); - var evaluateStatusCell = new CellRendererImage (); + evaluateStatusCell = new CellRendererImage (); valueCol.PackStart (evaluateStatusCell, false); valueCol.AddAttribute (evaluateStatusCell, "visible", EvaluateStatusIconVisibleColumn); valueCol.AddAttribute (evaluateStatusCell, "image", EvaluateStatusIconColumn); @@ -1125,7 +1126,7 @@ namespace MonoDevelop.Debugger RegisterValue (val, iter); } - void SetValues (TreeIter parent, TreeIter it, string name, ObjectValue val) + void SetValues (TreeIter parent, TreeIter it, string name, ObjectValue val, bool updateJustValue = false) { string strval; bool canEdit; @@ -1209,10 +1210,13 @@ namespace MonoDevelop.Debugger strval = strval.Replace ("\r\n", " ").Replace ("\n", " "); + store.SetValue (it, ValueColumn, strval); + if (updateJustValue) + return; + bool hasChildren = val.HasChildren; string icon = GetIcon (val.Flags); store.SetValue (it, NameColumn, name); - store.SetValue (it, ValueColumn, strval); store.SetValue (it, TypeColumn, val.TypeName); store.SetValue (it, ObjectColumn, val); store.SetValue (it, NameEditableColumn, !hasParent && AllowAdding); @@ -1509,8 +1513,35 @@ namespace MonoDevelop.Debugger store.SetValue (it, NameColorColumn, newColor); store.SetValue (it, ValueColorColumn, newColor); + UpdateParentValue (it); } - + + private void UpdateParentValue (TreeIter it) + { + if (store.IterParent (out var parentIter, it)) { + if (store.GetValue (parentIter, ObjectColumn) is ObjectValue parentVal) { + parentVal.Refresh (); + nodes [parentVal] = new TreeRowReference (store, store.GetPath (parentIter)); + if (parentVal.IsEvaluating) + parentVal.ValueChanged += UpdateObjectValue; + else + UpdateObjectValue (parentVal, null); + } + } + } + + private void UpdateObjectValue (object sender, EventArgs e) + { + Runtime.RunInMainThread (() => { + var val = (ObjectValue)sender; + val.ValueChanged -= UpdateObjectValue; + if (!FindValue (val, out var it)) + return; + nodes.Remove (val); + SetValues (TreeIter.Zero, it, null, val, true); + }); + } + void OnEditingCancelled (object s, EventArgs args) { OnEndEditing (); @@ -1855,12 +1886,17 @@ namespace MonoDevelop.Debugger CellRenderer cr; TreePath path; bool closePreviewWindow = true; + bool clickProcessed = false; TreeIter it; if (CanQueryDebugger && evnt.Button == 1 && GetCellAtPos ((int)evnt.X, (int)evnt.Y, out path, out col, out cr) && store.GetIter (out it, path)) { if (cr == crpViewer) { + clickProcessed = true; var val = (ObjectValue)store.GetValue (it, ObjectColumn); - DebuggingService.ShowValueVisualizer (val); + if (DebuggingService.ShowValueVisualizer (val)) { + UpdateParentValue (it); + RefreshRow (it); + } } else if (cr == crtExp && !PreviewWindowManager.IsVisible && ValidObjectForPreviewIcon (it)) { var val = (ObjectValue)store.GetValue (it, ObjectColumn); startPreviewCaret = GetCellRendererArea (path, col, cr); @@ -1880,6 +1916,7 @@ namespace MonoDevelop.Debugger startPreviewCaret.Y += (int)Vadjustment.Value; if (startPreviewCaret.X < evnt.X && startPreviewCaret.X + 16 > evnt.X) { + clickProcessed = true; if (CompactView) { SetPreviewButtonIcon (PreviewButtonIcons.Active, it); } else { @@ -1899,6 +1936,7 @@ namespace MonoDevelop.Debugger var url = crtValue.Text.Trim ('"', '{', '}'); Uri uri; if (url != null && Uri.TryCreate (url, UriKind.Absolute, out uri) && (uri.Scheme == "http" || uri.Scheme == "https")) { + clickProcessed = true; DesktopService.ShowUrl (url); } } @@ -1909,14 +1947,17 @@ namespace MonoDevelop.Debugger base.OnButtonPressEvent (evnt);//Select row, so base.OnButtonPressEvent below starts editing } else if (!editing) { if (cr == crpButton) { + clickProcessed = true; HandleValueButton (it); } else if (cr == crpPin) { + clickProcessed = true; TreeIter pi; if (PinnedWatch != null && !store.IterParent (out pi, it)) RemovePinnedWatch (it); else CreatePinnedWatch (it); } else if (cr == crpLiveUpdate) { + clickProcessed = true; TreeIter pi; if (PinnedWatch != null && !store.IterParent (out pi, it)) { DebuggingService.SetLiveUpdateMode (PinnedWatch, !PinnedWatch.LiveUpdate); @@ -1933,6 +1974,9 @@ namespace MonoDevelop.Debugger PreviewWindowManager.DestroyWindow (); } + if (clickProcessed) + return true; + //HACK: show context menu in release event instead of show event to work around gtk bug if (evnt.TriggersContextMenu ()) { // ShowPopup (evnt); @@ -2148,7 +2192,21 @@ namespace MonoDevelop.Debugger foreach (CellRenderer cr in col.CellRenderers) { int xo, w; col.CellGetPosition (cr, out xo, out w); - if (cr.Visible && x >= xo && x < xo + w) { + var visible = cr.Visible; + if (cr == crpViewer) { + if (store.GetIter (out var it, path)) { + visible = (bool)store.GetValue (it, ViewerButtonVisibleColumn); + } + } else if (cr == evaluateStatusCell) { + if (store.GetIter (out var it, path)) { + visible = (bool)store.GetValue (it, EvaluateStatusIconVisibleColumn); + } + } else if (cr == crpButton) { + if (store.GetIter (out var it, path)) { + visible = (bool)store.GetValue (it, ValueButtonVisibleColumn); + } + } + if (visible && x >= xo && x < xo + w) { cellRenderer = cr; return true; } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ProcessAttacher.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ProcessAttacher.cs new file mode 100644 index 0000000000..9e0eee0805 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ProcessAttacher.cs @@ -0,0 +1,46 @@ +// +// ProcessAttacher.cs +// +// Author: +// David Karlaš <david.karlas@xamarin.com> +// +// Copyright (c) 2017 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Mono.Debugging.Client; + +namespace MonoDevelop.Debugger +{ + public delegate void AttachableProcessesChangedDelegate (ProcessAttacher sender); + + public abstract class ProcessAttacher : IDisposable + { + public abstract ProcessInfo [] GetAttachableProcesses (); + + public event AttachableProcessesChangedDelegate AttachableProcessesChanged; + + protected void OnAttachableProcessesChanged () + { + AttachableProcessesChanged (this); + } + + public abstract void Dispose (); + } +} diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DotNetCoreProjectNodeBuilderExtension.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DotNetCoreProjectNodeBuilderExtension.cs index 29776e99a2..4a7d199a40 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DotNetCoreProjectNodeBuilderExtension.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DotNetCoreProjectNodeBuilderExtension.cs @@ -51,18 +51,10 @@ namespace MonoDevelop.DotNetCore.NodeBuilders if (dotNetCoreProject.HasSdk && !dotNetCoreProject.IsDotNetCoreSdkInstalled ()) { nodeInfo.StatusSeverity = TaskSeverity.Error; - nodeInfo.StatusMessage = GetMessage (dotNetCoreProject); + nodeInfo.StatusMessage = dotNetCoreProject.GetDotNetCoreSdkRequiredMessage (); } } - string GetMessage (DotNetCoreProjectExtension dotNetCoreProject) - { - if (dotNetCoreProject.IsUnsupportedDotNetCoreSdkInstalled ()) - return GettextCatalog.GetString ("The .NET Core SDK installed is not supported. Please install a more recent version. {0}", DotNetCoreNotInstalledDialog.DotNetCoreDownloadUrl); - - return GettextCatalog.GetString (".NET Core SDK is not installed. This is required to build .NET Core projects. {0}", DotNetCoreNotInstalledDialog.DotNetCoreDownloadUrl); - } - public override Type CommandHandlerType { get { return typeof (DotNetCoreProjectNodeCommandHandler); } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj index 60b973988b..3ab9e574d5 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj @@ -40,6 +40,7 @@ <Compile Include="MonoDevelop.DotNetCore.Tests\DotNetCoreProjectTests.cs" /> <Compile Include="MonoDevelop.DotNetCore.Tests\DotNetCoreMSBuildProjectTests.cs" /> <Compile Include="MonoDevelop.DotNetCore.Tests\DotNetCoreVersionTests.cs" /> + <Compile Include="MonoDevelop.DotNetCore.Tests\DotNetCoreSdkTests.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\..\external\guiunit\src\framework\GuiUnit_NET_4_5.csproj"> diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreSdkTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreSdkTests.cs new file mode 100644 index 0000000000..f54ccb7fcb --- /dev/null +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreSdkTests.cs @@ -0,0 +1,73 @@ +// +// DotNetCoreSdkTests.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2017 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using MonoDevelop.Core.Assemblies;
+using NUnit.Framework; +using System.Linq; + +namespace MonoDevelop.DotNetCore.Tests +{ + [TestFixture] + class DotNetCoreSdkTests + { + /// <summary> + /// Checks that a project's target framework is supported based on the install .NET Core SDKs. + /// Also takes into account if Mono includes the .NET Core v1 SDKs + /// </summary> + [TestCase (".NETCoreApp", "1.0", new [] { "1.0.4" }, false, true)] + [TestCase (".NETCoreApp", "1.1", new [] { "1.0.4" }, false, true)] // .NET Core sdk 1.0 supports 1.1 projects. + [TestCase (".NETStandard" ,"1.0", new [] { "1.0.4" }, false, true)] + [TestCase (".NETCoreApp", "1.0", new [] { "1.0.4" }, true, true)] // Mono has .NET Core sdks. + [TestCase (".NETCoreApp", "1.1", new string [0], true, true)] // Mono has .NET Core sdks. + [TestCase (".NETStandard", "1.0", new string [0], true, true)] // Mono has .NET Core sdks. + [TestCase (".NETCoreApp", "2.0", new [] { "1.0.4" }, false, false)] + [TestCase (".NETStandard", "2.0", new [] { "1.0.4" }, false, false)] + [TestCase (".NETCoreApp", "2.0", new [] { "1.0.4", "2.0.0" }, false, true)] + [TestCase (".NETStandard", "2.0", new [] { "1.0.4", "2.0.0" }, false, true)] + [TestCase (".NETCoreApp", "2.0", new [] { "2.0.0-preview2-006497" }, false, true)] // Allow preview versions. + [TestCase (".NETStandard", "2.0", new [] { "2.0.0-preview2-006497" }, false, true)] // Allow preview versions. + [TestCase (".NETFramework", "2.0", new [] { "2.0.0" }, false, false)] // Only .NETCoreApp and .NETStandard are supported. + [TestCase (".NETCoreApp", "1.1", new [] { "2.0.0" }, false, true)] // v2.0 SDK can compile v1 projects + [TestCase (".NETStandard", "1.6", new [] { "2.0.0" }, false, true)] // v2.0 SDK can compile v1 projects + public void IsSupportedTargetFramework ( + string frameworkIdentifier, + string frameworkVersion, + string[] installedSdkVersions, + bool msbuildSdksInstalled, // True if Mono has the .NET Core sdks. + bool expected) + { + string framework = $"{frameworkIdentifier},Version=v{frameworkVersion}"; + var targetFrameworkMoniker = TargetFrameworkMoniker.Parse (framework); + var versions = installedSdkVersions.Select (version => DotNetCoreVersion.Parse (version)) + .OrderByDescending (version => version) + .ToArray (); + + bool actual = DotNetCoreSdk.IsSupported (targetFrameworkMoniker, versions, msbuildSdksInstalled); + + Assert.AreEqual (expected, actual); + } + } +} diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj index c2be14c75e..94374bf34c 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj @@ -425,6 +425,6 @@ <Version>$(TemplatesVersion)</Version> </NuGetPackage> </ItemGroup> - <Copy SourceFiles="..\..\..\packages\%(NuGetPackage.Identity).%(NuGetPackage.Version)\%(NuGetPackage.Identity).%(NuGetPackage.Version).nupkg" DestinationFolder="$(OutputPath)\Templates" /> + <Copy SourceFiles="..\..\..\packages\%(NuGetPackage.Identity).%(NuGetPackage.Version)\%(NuGetPackage.Identity).%(NuGetPackage.Version).nupkg" DestinationFolder="$(OutputPath)\Templates" SkipUnchangedFiles="true" /> </Target> </Project> diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreNotInstalledDialog.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreNotInstalledDialog.cs index 8e2ac57499..8a0fd189c6 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreNotInstalledDialog.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreNotInstalledDialog.cs @@ -34,9 +34,15 @@ namespace MonoDevelop.DotNetCore class DotNetCoreNotInstalledDialog : IDisposable { public static readonly string DotNetCoreDownloadUrl = "https://aka.ms/vs/mac/install-netcore"; + public static readonly string DotNetCore20DownloadUrl = "https://aka.ms/vs/mac/install-netcore2"; + + static readonly string defaultMessage = GettextCatalog.GetString (".NET Core SDK is not installed. This is required to build and run .NET Core projects."); + static readonly string unsupportedMessage = GettextCatalog.GetString ("The .NET Core SDK installed is not supported. Please install a more recent version."); + static readonly string dotNetCore20Message = GettextCatalog.GetString (".NET Core 2.0 SDK is not installed. This is required to build and run .NET Core 2.0 projects."); GenericMessage message; AlertButton downloadButton; + string downloadUrl = DotNetCoreDownloadUrl; public DotNetCoreNotInstalledDialog () { @@ -46,7 +52,7 @@ namespace MonoDevelop.DotNetCore void Build () { message = new GenericMessage { - Text = GettextCatalog.GetString (".NET Core SDK is not installed. This is required to build and run .NET Core projects."), + Text = defaultMessage, DefaultButton = 1, Icon = Stock.Information }; @@ -61,7 +67,7 @@ namespace MonoDevelop.DotNetCore void AlertButtonClicked (object sender, AlertButtonEventArgs e) { if (e.Button == downloadButton) - DesktopService.ShowUrl (DotNetCoreDownloadUrl); + DesktopService.ShowUrl (downloadUrl); } public void Dispose () @@ -71,6 +77,13 @@ namespace MonoDevelop.DotNetCore public void Show () { + if (IsUnsupportedVersion) + Message = unsupportedMessage; + else if (RequiresDotNetCore20) { + Message = dotNetCore20Message; + downloadUrl = DotNetCore20DownloadUrl; + } + MessageService.GenericAlert (message); } @@ -78,5 +91,8 @@ namespace MonoDevelop.DotNetCore get { return message.Text; } set { message.Text = value; } } + + public bool IsUnsupportedVersion { get; set; } + public bool RequiresDotNetCore20 { get; set; } } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs index 6647df387e..2c6dd51f55 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs @@ -228,8 +228,8 @@ namespace MonoDevelop.DotNetCore Project.ParentSolution.ExtendedProperties [ShownDotNetCoreSdkInstalledExtendedPropertyName] = "true"; using (var dialog = new DotNetCoreNotInstalledDialog ()) { - if (unsupportedSdkVersion) - dialog.Message = GettextCatalog.GetString ("The .NET Core SDK installed is not supported. Please install a more recent version."); + dialog.IsUnsupportedVersion = unsupportedSdkVersion; + dialog.RequiresDotNetCore20 = Project.TargetFramework.IsNetStandard20OrNetCore20 (); dialog.Show (); } }); @@ -361,13 +361,23 @@ namespace MonoDevelop.DotNetCore BuildResult CreateDotNetCoreSdkRequiredBuildResult (bool isUnsupportedVersion) { - return CreateBuildError (GetDotNetCoreSdkRequiredBuildErrorMessage (isUnsupportedVersion)); + bool requiresDotNetCoreSdk20 = Project.TargetFramework.IsNetStandard20OrNetCore20 (); + return CreateBuildError (GetDotNetCoreSdkRequiredBuildErrorMessage (isUnsupportedVersion, requiresDotNetCoreSdk20)); } - static string GetDotNetCoreSdkRequiredBuildErrorMessage (bool isUnsupportedVersion) + internal string GetDotNetCoreSdkRequiredMessage () + { + return GetDotNetCoreSdkRequiredBuildErrorMessage ( + IsUnsupportedDotNetCoreSdkInstalled (), + Project.TargetFramework.IsNetStandard20OrNetCore20 ()); + } + + static string GetDotNetCoreSdkRequiredBuildErrorMessage (bool isUnsupportedVersion, bool requiresDotNetCoreSdk20) { if (isUnsupportedVersion) return GettextCatalog.GetString ("The .NET Core SDK installed is not supported. Please install a more recent version. {0}", DotNetCoreNotInstalledDialog.DotNetCoreDownloadUrl); + else if (requiresDotNetCoreSdk20) + return GettextCatalog.GetString (".NET Core 2.0 SDK is not installed. This is required to build .NET Core 2.0 projects. {0}", DotNetCoreNotInstalledDialog.DotNetCore20DownloadUrl); return GettextCatalog.GetString (".NET Core SDK is not installed. This is required to build .NET Core projects. {0}", DotNetCoreNotInstalledDialog.DotNetCoreDownloadUrl); } @@ -475,7 +485,9 @@ namespace MonoDevelop.DotNetCore public bool IsDotNetCoreSdkInstalled () { - return DotNetCoreSdk.IsInstalled || MSBuildSdks.Installed; + if (DotNetCoreSdk.IsInstalled || MSBuildSdks.Installed) + return DotNetCoreSdk.IsSupported (Project.TargetFramework); + return false; } public bool IsUnsupportedDotNetCoreSdkInstalled () diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectReloadMonitor.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectReloadMonitor.cs index 1e875529c0..637d0a6f84 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectReloadMonitor.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectReloadMonitor.cs @@ -76,7 +76,7 @@ namespace MonoDevelop.DotNetCore void OnDotNetCoreProjectReloaded (ProjectReloadedEventArgs e) { DotNetCoreProjectBuilderMaintainer.OnProjectReload (e); - RestorePackagesInProjectHandler.Run (e.NewProject.DotNetProject); + RestorePackagesInProjectHandler.Run (e.NewProject.DotNetProject, restoreTransitiveProjectReferences: true); } async void FileChanged (object sender, FileEventArgs e) diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs index b6530aa427..1eaaf19fc1 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs @@ -27,6 +27,7 @@ using System; using System.Linq; using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; namespace MonoDevelop.DotNetCore { @@ -67,6 +68,55 @@ namespace MonoDevelop.DotNetCore } /// <summary> + /// Checks that the target framework (e.g. .NETCoreApp1.1 or .NETStandard2.0) is supported + /// by the installed SDKs. Takes into account Mono having .NET Core v1 SDKs installed. + /// </summary> + internal static bool IsSupported (TargetFramework framework) + { + return IsSupported (framework.Id, Versions, MSBuildSdks.Installed); + } + + /// <summary> + /// Used by unit tests. + /// </summary> + internal static bool IsSupported ( + TargetFrameworkMoniker projectFramework, + DotNetCoreVersion[] versions, + bool msbuildSdksInstalled) + { + if (!projectFramework.IsNetStandardOrNetCoreApp ()) + return false; + + var projectFrameworkVersion = Version.Parse (projectFramework.Version); + + if (versions.Any (sdkVersion => IsSupported (projectFrameworkVersion, sdkVersion))) + return true; + + // .NET Core 1.x is supported by the MSBuild .NET Core SDKs if they are installed with Mono. + if (projectFrameworkVersion.Major == 1) + return msbuildSdksInstalled; + + return false; + } + + /// <summary> + /// Project framework version is considered supported if the major version of the + /// .NET Core SDK is greater or equal to the major version of the project framework. + /// The fact that a .NET Core SDK is a preview version is ignored in this check. + /// + /// .NET Core SDK 1.0.4 supports .NET Core 1.0 and 1.1 + /// .NET Core SDK 1.0.4 supports .NET Standard 1.0 to 1.6 + /// .NET Core SDK 2.0 supports 1.0, 1.1 and 2.0 + /// .NET Core SDK 2.0 supports .NET Standard 1.0 to 1.6 and 2.0 + /// .NET Core SDK 2.1 supports 1.0, 1.1 and 2.0 + /// .NET Core SDK 2.1 supports .NET Standard 1.0 to 1.6 and 2.0 + /// </summary> + static bool IsSupported (Version projectFrameworkVersion, DotNetCoreVersion sdkVersion) + { + return sdkVersion.Major >= projectFrameworkVersion.Major; + } + + /// <summary> /// This is a workaround to allow F# .NET Core 2.0 projects to be evaluated properly and compile /// without any errors. The better solution would be to ship the new Microsoft.FSharp.NetSdk.props /// and .targets files with Mono so this workaround can be removed. Setting the FSharpPropsShim diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs index 8520f8c928..1a68219abf 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs @@ -33,7 +33,7 @@ namespace MonoDevelop.DotNetCore { public static bool IsNetStandard (this TargetFramework framework) { - return framework.Id.Identifier == ".NETStandard"; + return framework.Id.IsNetStandard (); } public static bool IsNetStandard20 (this TargetFramework framework) @@ -64,7 +64,7 @@ namespace MonoDevelop.DotNetCore public static bool IsNetCoreApp (this TargetFramework framework) { - return framework.Id.Identifier == ".NETCoreApp"; + return framework.Id.IsNetCoreApp (); } public static bool IsNetCoreApp20 (this TargetFramework framework) @@ -84,6 +84,11 @@ namespace MonoDevelop.DotNetCore return framework.Id.IsNetFramework (); } + public static bool IsNetStandard20OrNetCore20 (this TargetFramework framework) + { + return framework.IsNetStandard20 () || framework.IsNetCoreApp (); + } + public static string GetDisplayName (this TargetFramework framework) { if (framework.IsNetCoreApp ()) diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs index 3cd0bdd459..c49a937ebe 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs @@ -61,5 +61,20 @@ namespace MonoDevelop.DotNetCore { return framework.Identifier == ".NETFramework"; } + + public static bool IsNetCoreApp (this TargetFrameworkMoniker framework) + { + return framework.Identifier == ".NETCoreApp"; + } + + public static bool IsNetStandard (this TargetFrameworkMoniker framework) + { + return framework.Identifier == ".NETStandard"; + } + + public static bool IsNetStandardOrNetCoreApp (this TargetFrameworkMoniker framework) + { + return framework.IsNetStandard () || framework.IsNetCoreApp (); + } } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/RestorePackagesInProjectHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/RestorePackagesInProjectHandler.cs index aca0efb247..fbeb69dffa 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/RestorePackagesInProjectHandler.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/RestorePackagesInProjectHandler.cs @@ -43,25 +43,34 @@ namespace MonoDevelop.PackageManagement.Commands info.Enabled = SelectedDotNetProjectHasPackages (); } - public static void Run (DotNetProject project) + public static void Run (DotNetProject project)
+ {
+ Run (project, false);
+ }
+
+ public static void Run (DotNetProject project, bool restoreTransitiveProjectReferences) { try {
ProgressMonitorStatusMessage message = ProgressMonitorStatusMessageFactory.CreateRestoringPackagesInProjectMessage ();
- IPackageAction action = CreateRestorePackagesAction (project); + IPackageAction action = CreateRestorePackagesAction (project, restoreTransitiveProjectReferences); PackageManagementServices.BackgroundPackageActionRunner.Run (message, action);
} catch (Exception ex) {
ShowStatusBarError (ex);
}
}
- static IPackageAction CreateRestorePackagesAction (DotNetProject project) + static IPackageAction CreateRestorePackagesAction (DotNetProject project, bool restoreTransitiveProjectReferences) {
var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (project.ParentSolution);
var nugetProject = solutionManager.GetNuGetProject (new DotNetProjectProxy (project));
var buildIntegratedProject = nugetProject as BuildIntegratedNuGetProject;
if (buildIntegratedProject != null) {
- return new RestoreNuGetPackagesInNuGetIntegratedProject (project, buildIntegratedProject, solutionManager);
+ return new RestoreNuGetPackagesInNuGetIntegratedProject (
+ project,
+ buildIntegratedProject,
+ solutionManager,
+ restoreTransitiveProjectReferences);
}
var nugetAwareProject = project as INuGetAwareProject;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs index f4609d9f98..d6e867e140 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs @@ -320,7 +320,9 @@ namespace MonoDevelop.PackageManagement void ShowPackageInformation (PackageSearchResultViewModel packageViewModel)
{
- this.packageNameLabel.Markup = packageViewModel.GetNameMarkup ();
+ // Use the package id and not the package title to prevent a pango crash if the title
+ // contains Chinese characters.
+ this.packageNameLabel.Markup = packageViewModel.GetIdMarkup ();
this.packageAuthor.Text = packageViewModel.Author;
this.packagePublishedDate.Text = packageViewModel.GetLastPublishedDisplayText ();
this.packageDownloads.Text = packageViewModel.GetDownloadCountDisplayText ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs index 765fa46a29..8da11df3c0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs @@ -98,9 +98,11 @@ namespace MonoDevelop.PackageManagement }
// Package Id.
+ // Use the package id and not the package title to prevent a pango crash if the title
+ // contains Chinese characters.
var packageIdTextLayout = new TextLayout ();
packageIdTextLayout.Font = packageIdTextLayout.Font.WithSize (packageIdFontSize);
- packageIdTextLayout.Markup = packageViewModel.GetNameMarkup ();
+ packageIdTextLayout.Markup = packageViewModel.GetIdMarkup ();
packageIdTextLayout.Trimming = TextTrimming.WordElipsis;
Size packageIdTextSize = packageIdTextLayout.GetSize ();
packageIdTextLayout.Width = packageIdWidth;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeMonoDevelopBuildIntegratedRestorer.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeMonoDevelopBuildIntegratedRestorer.cs new file mode 100644 index 0000000000..c60ab67a26 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeMonoDevelopBuildIntegratedRestorer.cs @@ -0,0 +1,58 @@ +// +// FakeMonoDevelopBuildIntegratedRestorer.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2017 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using NuGet.ProjectManagement.Projects; + +namespace MonoDevelop.PackageManagement.Tests.Helpers +{ + class FakeMonoDevelopBuildIntegratedRestorer : IMonoDevelopBuildIntegratedRestorer + { + public bool LockFileChanged { get; set; } + + public BuildIntegratedNuGetProject ProjectRestored; + + public Task RestorePackages ( + BuildIntegratedNuGetProject project, + CancellationToken cancellationToken) + { + ProjectRestored = project; + return Task.FromResult (0); + } + + public List<BuildIntegratedNuGetProject> ProjectsRestored = new List<BuildIntegratedNuGetProject> (); + + public Task RestorePackages ( + IEnumerable<BuildIntegratedNuGetProject> projects, + CancellationToken cancellationToken) + { + ProjectsRestored.AddRange (projects); + return Task.FromResult (0); + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetProject.cs index b2a0de2557..4b9eaae8f3 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetProject.cs @@ -107,7 +107,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers return Task.FromResult (0); } - public void NotifyProjectReferencesChanged () + public void NotifyProjectReferencesChanged (bool includeTransitiveProjectReferences) { } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionManager.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionManager.cs index 0cf7e37214..b88ace6581 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionManager.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionManager.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using MonoDevelop.Projects; using NuGet.Configuration; using NuGet.PackageManagement; using NuGet.ProjectManagement; @@ -113,14 +114,20 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers throw new NotImplementedException (); } - public Dictionary<IDotNetProject, FakeNuGetProject> NuGetProjects = new Dictionary<IDotNetProject, FakeNuGetProject> (); + public Dictionary<IDotNetProject, NuGetProject> NuGetProjects = new Dictionary<IDotNetProject, NuGetProject> (); + public Dictionary<DotNetProject, NuGetProject> NuGetProjectsUsingDotNetProjects = new Dictionary<DotNetProject, NuGetProject> (); public NuGetProject GetNuGetProject (IDotNetProject project) { - FakeNuGetProject nugetProject = null; + NuGetProject nugetProject = null; if (NuGetProjects.TryGetValue (project, out nugetProject)) return nugetProject; + if (project.DotNetProject != null) { + if (NuGetProjectsUsingDotNetProjects.TryGetValue (project.DotNetProject, out nugetProject)) + return nugetProject; + } + return new FakeNuGetProject (project); } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableDotNetCoreNuGetProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableDotNetCoreNuGetProject.cs index 6380f38036..3ccbecf181 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableDotNetCoreNuGetProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableDotNetCoreNuGetProject.cs @@ -34,6 +34,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public TestableDotNetCoreNuGetProject (DotNetProject project) : base (project, new [] { "netcoreapp1.0" }) { + BuildIntegratedRestorer = new FakeMonoDevelopBuildIntegratedRestorer (); } public bool IsSaved { get; set; } @@ -43,5 +44,14 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers IsSaved = true; return Task.FromResult (0); } + + public FakeMonoDevelopBuildIntegratedRestorer BuildIntegratedRestorer; + public Solution SolutionUsedToCreateBuildIntegratedRestorer; + + protected override IMonoDevelopBuildIntegratedRestorer CreateBuildIntegratedRestorer (Solution solution) + { + SolutionUsedToCreateBuildIntegratedRestorer = solution; + return BuildIntegratedRestorer; + } } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj index 6f3cee0b9a..8f1f0ec86b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj @@ -201,6 +201,8 @@ <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableUninstallNuGetPackagesAction.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\PackageReferenceNuGetProjectTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestablePackageReferenceNuGetProject.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeMonoDevelopBuildIntegratedRestorer.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\RestoreNuGetPackagesInNuGetIntegratedProjectTests.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetCoreNuGetProjectTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetCoreNuGetProjectTests.cs index e9148330f5..69135e9943 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetCoreNuGetProjectTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetCoreNuGetProjectTests.cs @@ -30,6 +30,7 @@ using System.Threading.Tasks; using MonoDevelop.PackageManagement.Tests.Helpers; using MonoDevelop.Projects; using NUnit.Framework; +using NuGet.PackageManagement; using NuGet.Packaging.Core; using NuGet.ProjectManagement; using NuGet.ProjectModel; @@ -44,14 +45,24 @@ namespace MonoDevelop.PackageManagement.Tests TestableDotNetCoreNuGetProject project; FakeNuGetProjectContext context; DependencyGraphCacheContext dependencyGraphCacheContext; + FakeMonoDevelopBuildIntegratedRestorer buildIntegratedRestorer; void CreateNuGetProject (string projectName = "MyProject", string fileName = @"d:\projects\MyProject\MyProject.csproj") { context = new FakeNuGetProjectContext (); - dotNetProject = new DummyDotNetProject (); - dotNetProject.Name = projectName; - dotNetProject.FileName = fileName.ToNativePath (); + dotNetProject = CreateDotNetCoreProject (projectName, fileName); + var solution = new Solution (); + solution.RootFolder.AddItem (dotNetProject); project = new TestableDotNetCoreNuGetProject (dotNetProject); + buildIntegratedRestorer = project.BuildIntegratedRestorer; + } + + static DummyDotNetProject CreateDotNetCoreProject (string projectName = "MyProject", string fileName = @"d:\projects\MyProject\MyProject.csproj") + { + var project = new DummyDotNetProject (); + project.Name = projectName; + project.FileName = fileName.ToNativePath (); + return project; } void AddDotNetProjectPackageReference (string packageId, string version) @@ -86,6 +97,12 @@ namespace MonoDevelop.PackageManagement.Tests return specs.Single (); } + void OnAfterExecuteActions (string packageId, string version, NuGetProjectActionType actionType) + { + var action = new FakeNuGetProjectAction (packageId, version, actionType); + project.OnAfterExecuteActions (new [] { action }); + } + [Test] public async Task GetInstalledPackagesAsync_OnePackageReference_ReturnsOnePackageReference () { @@ -255,5 +272,233 @@ namespace MonoDevelop.PackageManagement.Tests Assert.IsTrue (packageReference.IsFloating ()); Assert.AreEqual ("2.6.0-*", packageReference.AllowedVersions.Float.ToString ()); } + + [Test] + public async Task PostProcessAsync_ProjectAssetsFile_NotifyChangeInAssetsFile () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + dotNetProject.BaseIntermediateOutputPath = @"d:\projects\MyProject\obj".ToNativePath (); + string fileNameChanged = null; + PackageManagementServices.PackageManagementEvents.FileChanged += (sender, e) => { + fileNameChanged = e.Single ().FileName; + }; + + await project.PostProcessAsync (context, CancellationToken.None); + + string expectedFileNameChanged = @"d:\projects\MyProject\obj\project.assets.json".ToNativePath (); + Assert.AreEqual (expectedFileNameChanged, fileNameChanged); + } + + [Test] + public async Task PostProcessAsync_References_NotifyReferencesChangedEventFired () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.Single ().Hint; + }; + + await project.PostProcessAsync (context, CancellationToken.None); + + Assert.AreEqual ("References", modifiedHint); + } + + [Test] + public async Task PostProcessAsync_RestoreRunLockFileNotChanged_NotifyReferencesChangedEventFired () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.Single ().Hint; + }; + OnAfterExecuteActions ("NUnit", "2.6.3", NuGetProjectActionType.Install); + + await project.PostProcessAsync (context, CancellationToken.None); + + Assert.IsNotNull (dotNetProject.ParentSolution); + Assert.AreEqual (dotNetProject.ParentSolution, project.SolutionUsedToCreateBuildIntegratedRestorer); + Assert.AreEqual (project, buildIntegratedRestorer.ProjectRestored); + Assert.AreEqual ("References", modifiedHint); + } + + [Test] + public async Task PostProcessAsync_RestoreRunLockFileNotChanged_NotifyChangeInAssetsFile () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + dotNetProject.BaseIntermediateOutputPath = @"d:\projects\MyProject\obj".ToNativePath (); + string fileNameChanged = null; + PackageManagementServices.PackageManagementEvents.FileChanged += (sender, e) => { + fileNameChanged = e.Single ().FileName; + }; + OnAfterExecuteActions ("NUnit", "2.6.3", NuGetProjectActionType.Install); + + await project.PostProcessAsync (context, CancellationToken.None); + + string expectedFileNameChanged = @"d:\projects\MyProject\obj\project.assets.json".ToNativePath (); + Assert.AreEqual (expectedFileNameChanged, fileNameChanged); + Assert.AreEqual (project, buildIntegratedRestorer.ProjectRestored); + } + + /// <summary> + /// Build restorer would trigger the notification itself. + /// </summary> + [Test] + public async Task PostProcessAsync_RestoreRunLockFileChanged_NotifyReferencesChangedEventNotFired () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.Single ().Hint; + }; + buildIntegratedRestorer.LockFileChanged = true; + OnAfterExecuteActions ("NUnit", "2.6.3", NuGetProjectActionType.Install); + + await project.PostProcessAsync (context, CancellationToken.None); + + Assert.AreEqual (project, buildIntegratedRestorer.ProjectRestored); + Assert.IsNull (modifiedHint); + } + + /// <summary> + /// Build restorer would trigger the notification itself. + /// </summary> + [Test] + public async Task PostProcessAsync_RestoreRunLockFileChanged_NotifyChangeInAssetsFileIsNotMade () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + dotNetProject.BaseIntermediateOutputPath = @"d:\projects\MyProject\obj".ToNativePath (); + string fileNameChanged = null; + PackageManagementServices.PackageManagementEvents.FileChanged += (sender, e) => { + fileNameChanged = e.Single ().FileName; + }; + buildIntegratedRestorer.LockFileChanged = true; + OnAfterExecuteActions ("NUnit", "2.6.3", NuGetProjectActionType.Install); + + await project.PostProcessAsync (context, CancellationToken.None); + + Assert.IsNull (fileNameChanged); + Assert.AreEqual (project, buildIntegratedRestorer.ProjectRestored); + } + + [Test] + public void NotifyProjectReferencesChanged_References_NotifyReferencesChangedEventFired () + { + CreateNuGetProject (); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.Single ().Hint; + }; + + project.NotifyProjectReferencesChanged (false); + + Assert.AreEqual ("References", modifiedHint); + } + + /// <summary> + /// Assembly references are transitive for .NET Core projects so any .NET Core project + /// that references the project having a NuGet package being installed needs to refresh + /// references for the other projects not just itself. + /// </summary> + [Test] + public async Task PostProcessAsync_DotNetCoreProjectReferencesThisProject_NotifyReferencesChangedEventFiredForBothProjects () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + var dotNetProjectWithProjectReference = CreateDotNetCoreProject ("MyProject2", @"d:\projects\MyProject2\MyProject2.csproj"); + dotNetProject.ParentSolution.RootFolder.AddItem (dotNetProjectWithProjectReference); + var projectReference = ProjectReference.CreateProjectReference (dotNetProject); + dotNetProjectWithProjectReference.References.Add (projectReference); + string modifiedHintMainProject = null; + dotNetProject.Modified += (sender, e) => { + modifiedHintMainProject = e.Single ().Hint; + }; + string modifiedHintProjectWithReference = null; + dotNetProjectWithProjectReference.Modified += (sender, e) => { + modifiedHintProjectWithReference = e.Single ().Hint; + }; + + await project.PostProcessAsync (context, CancellationToken.None); + + Assert.AreEqual ("References", modifiedHintMainProject); + Assert.AreEqual ("References", modifiedHintProjectWithReference); + } + + [Test] + public async Task PostProcessAsync_DotNetCoreProjectReferencesThisProjectLockFileNotChanged_NotifyReferencesChangedEventFiredForBothProjects () + { + CreateNuGetProject (); + AddDotNetProjectPackageReference ("NUnit", "2.6.0"); + var dotNetProjectWithProjectReference = CreateDotNetCoreProject ("MyProject2", @"d:\projects\MyProject2\MyProject2.csproj"); + dotNetProject.ParentSolution.RootFolder.AddItem (dotNetProjectWithProjectReference); + var projectReference = ProjectReference.CreateProjectReference (dotNetProject); + dotNetProjectWithProjectReference.References.Add (projectReference); + string modifiedHintMainProject = null; + dotNetProject.Modified += (sender, e) => { + modifiedHintMainProject = e.Single ().Hint; + }; + string modifiedHintProjectWithReference = null; + dotNetProjectWithProjectReference.Modified += (sender, e) => { + modifiedHintProjectWithReference = e.Single ().Hint; + }; + OnAfterExecuteActions ("NUnit", "2.6.3", NuGetProjectActionType.Install); + + await project.PostProcessAsync (context, CancellationToken.None); + + Assert.AreEqual (project, buildIntegratedRestorer.ProjectRestored); + Assert.AreEqual ("References", modifiedHintMainProject); + Assert.AreEqual ("References", modifiedHintProjectWithReference); + } + + [Test] + public void NotifyProjectReferencesChanged_IncludeTransitiveReferences_NotifyReferencesChangedEventFiredForAllProjects () + { + CreateNuGetProject (); + var dotNetProjectWithProjectReference = CreateDotNetCoreProject ("MyProject2", @"d:\projects\MyProject2\MyProject2.csproj"); + dotNetProject.ParentSolution.RootFolder.AddItem (dotNetProjectWithProjectReference); + var projectReference = ProjectReference.CreateProjectReference (dotNetProject); + dotNetProjectWithProjectReference.References.Add (projectReference); + string modifiedHintMainProject = null; + dotNetProject.Modified += (sender, e) => { + modifiedHintMainProject = e.Single ().Hint; + }; + string modifiedHintProjectWithReference = null; + dotNetProjectWithProjectReference.Modified += (sender, e) => { + modifiedHintProjectWithReference = e.Single ().Hint; + }; + + project.NotifyProjectReferencesChanged (true); + + Assert.AreEqual ("References", modifiedHintMainProject); + Assert.AreEqual ("References", modifiedHintProjectWithReference); + } + + [Test] + public void NotifyProjectReferencesChanged_DoNotIncludeTransitiveReferences_NotifyReferencesChangedEventFiredForMainProjectOnly () + { + CreateNuGetProject (); + var dotNetProjectWithProjectReference = CreateDotNetCoreProject ("MyProject2", @"d:\projects\MyProject2\MyProject2.csproj"); + dotNetProject.ParentSolution.RootFolder.AddItem (dotNetProjectWithProjectReference); + var projectReference = ProjectReference.CreateProjectReference (dotNetProject); + dotNetProjectWithProjectReference.References.Add (projectReference); + string modifiedHintMainProject = null; + dotNetProject.Modified += (sender, e) => { + modifiedHintMainProject = e.Single ().Hint; + }; + string modifiedHintProjectWithReference = null; + dotNetProjectWithProjectReference.Modified += (sender, e) => { + modifiedHintProjectWithReference = e.Single ().Hint; + }; + + project.NotifyProjectReferencesChanged (false); + + Assert.AreEqual ("References", modifiedHintMainProject); + Assert.IsNull (modifiedHintProjectWithReference); + } } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs index c92c7b099b..303c4f39d5 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs @@ -25,8 +25,9 @@ // THE SOFTWARE.
using System.Collections.Generic;
-using MonoDevelop.PackageManagement;
+using System.Linq;
using MonoDevelop.PackageManagement.Tests.Helpers;
+using MonoDevelop.Projects;
using NUnit.Framework;
namespace MonoDevelop.PackageManagement.Tests
@@ -56,6 +57,20 @@ namespace MonoDevelop.PackageManagement.Tests existingFiles.Add (fileName.ToNativePath ());
}
+ static DummyDotNetProject CreateDotNetCoreProject (string projectName = "MyProject", string fileName = @"d:\projects\MyProject\MyProject.csproj")
+ {
+ var project = new DummyDotNetProject ();
+ project.Name = projectName;
+ project.FileName = fileName.ToNativePath ();
+ return project;
+ } + + void AddParentSolution (DotNetProject dotNetProject) + { + var solution = new Solution (); + solution.RootFolder.AddItem (dotNetProject); + }
+
[Test]
public void GetPackagesConfigFilePath_ProjectPackagesConfigFileDoesNotExist_ReturnsDefaultPackagesConfigFile ()
{
@@ -162,6 +177,213 @@ namespace MonoDevelop.PackageManagement.Tests Assert.IsTrue (result);
}
+
+ [Test]
+ public void DotNetCoreNotifyReferencesChanged_NoProjectReferencesAllProjects_NotifyReferencesChangedForProject ()
+ {
+ var dotNetProject = CreateDotNetCoreProject ();
+ AddParentSolution (dotNetProject); + string modifiedHint = null;
+ dotNetProject.Modified += (sender, e) => {
+ modifiedHint = e.First ().Hint;
+ };
+
+ dotNetProject.DotNetCoreNotifyReferencesChanged (transitiveOnly: false);
+
+ Assert.AreEqual ("References", modifiedHint);
+ }
+
+ [Test]
+ public void DotNetCoreNotifyReferencesChanged_NoProjectReferencesTransitiveProjectReferencesOnly_NotifyReferencesChangedNotFiredForProject ()
+ {
+ var dotNetProject = CreateDotNetCoreProject ();
+ AddParentSolution (dotNetProject); + string modifiedHint = null;
+ dotNetProject.Modified += (sender, e) => {
+ modifiedHint = e.First ().Hint;
+ };
+
+ dotNetProject.DotNetCoreNotifyReferencesChanged (transitiveOnly: true);
+
+ Assert.IsNull (modifiedHint);
+ } + + [Test] + public void DotNetCoreNotifyReferencesChanged_OneProjectReferencesProject_NotifyReferencesChangedForAllProjects () + { + var dotNetProject = CreateDotNetCoreProject (); + AddParentSolution (dotNetProject); + var referencingProject = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject); + referencingProject.References.Add (ProjectReference.CreateProjectReference (dotNetProject)); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.First ().Hint; + }; + string modifiedHintForReferencingProject = null; + referencingProject.Modified += (sender, e) => { + modifiedHintForReferencingProject = e.First ().Hint; + }; + + dotNetProject.DotNetCoreNotifyReferencesChanged (); + + Assert.AreEqual ("References", modifiedHint); + Assert.AreEqual ("References", modifiedHintForReferencingProject); + } + + [Test] + public void DotNetCoreNotifyReferencesChanged_OneProjectReferencesProjectWithReferencedOutputAssemblyFalse_NotifyReferencesChangedNotFiredForReferencingProject () + { + var dotNetProject = CreateDotNetCoreProject (); + AddParentSolution (dotNetProject); + var referencingProject = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject); + var projectReference = ProjectReference.CreateProjectReference (dotNetProject); + projectReference.ReferenceOutputAssembly = false; + referencingProject.References.Add (projectReference); + string modifiedHintForReferencingProject = null; + referencingProject.Modified += (sender, e) => { + modifiedHintForReferencingProject = e.First ().Hint; + }; + + dotNetProject.DotNetCoreNotifyReferencesChanged (true); + + Assert.IsNull (modifiedHintForReferencingProject); + } + + [Test] + public void DotNetCoreNotifyReferencesChanged_TwoOneProjectReferencesModifiedProject_NotifyReferencesChangedForAllProjects () + { + var dotNetProject = CreateDotNetCoreProject (); + AddParentSolution (dotNetProject); + var referencingProject1 = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject1); + referencingProject1.References.Add (ProjectReference.CreateProjectReference (dotNetProject)); + var referencingProject2 = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject2); + referencingProject2.References.Add (ProjectReference.CreateProjectReference (dotNetProject)); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.First ().Hint; + }; + string modifiedHintForReferencingProject1 = null; + referencingProject1.Modified += (sender, e) => { + modifiedHintForReferencingProject1 = e.First ().Hint; + }; + string modifiedHintForReferencingProject2 = null; + referencingProject2.Modified += (sender, e) => { + modifiedHintForReferencingProject2 = e.First ().Hint; + }; + + dotNetProject.DotNetCoreNotifyReferencesChanged (); + + Assert.AreEqual ("References", modifiedHint); + Assert.AreEqual ("References", modifiedHintForReferencingProject1); + Assert.AreEqual ("References", modifiedHintForReferencingProject2); + } + + [Test] + public void DotNetCoreNotifyReferencesChanged_TwoProjectReferencesChainToModifiedProject_NotifyReferencesChangedForAllProjects () + { + var dotNetProject = CreateDotNetCoreProject (); + AddParentSolution (dotNetProject); + var referencingProject1 = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject1); + referencingProject1.References.Add (ProjectReference.CreateProjectReference (dotNetProject)); + var referencingProject2 = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject2); + referencingProject2.References.Add (ProjectReference.CreateProjectReference (referencingProject1)); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.First ().Hint; + }; + string modifiedHintForReferencingProject1 = null; + referencingProject1.Modified += (sender, e) => { + modifiedHintForReferencingProject1 = e.First ().Hint; + }; + string modifiedHintForReferencingProject2 = null; + referencingProject2.Modified += (sender, e) => { + modifiedHintForReferencingProject2 = e.First ().Hint; + }; + + dotNetProject.DotNetCoreNotifyReferencesChanged (); + + Assert.AreEqual ("References", modifiedHint); + Assert.AreEqual ("References", modifiedHintForReferencingProject1); + Assert.AreEqual ("References", modifiedHintForReferencingProject2); + } + + /// <summary> + /// Same as above but the projects are added to the solution in a different order. + /// </summary> + [Test] + public void DotNetCoreNotifyReferencesChanged_TwoProjectReferencesChainToModifiedProject_NotifyReferencesChangedForAllProjects2 () + { + var dotNetProject = CreateDotNetCoreProject (); + AddParentSolution (dotNetProject); + var referencingProject1 = CreateDotNetCoreProject (); + var referencingProject2 = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject2); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject1); + referencingProject1.References.Add (ProjectReference.CreateProjectReference (dotNetProject)); + referencingProject2.References.Add (ProjectReference.CreateProjectReference (referencingProject1)); + string modifiedHint = null; + dotNetProject.Modified += (sender, e) => { + modifiedHint = e.First ().Hint; + }; + string modifiedHintForReferencingProject1 = null; + referencingProject1.Modified += (sender, e) => { + modifiedHintForReferencingProject1 = e.First ().Hint; + }; + string modifiedHintForReferencingProject2 = null; + referencingProject2.Modified += (sender, e) => { + modifiedHintForReferencingProject2 = e.First ().Hint; + }; + + dotNetProject.DotNetCoreNotifyReferencesChanged (); + + Assert.AreEqual ("References", modifiedHint); + Assert.AreEqual ("References", modifiedHintForReferencingProject1); + Assert.AreEqual ("References", modifiedHintForReferencingProject2); + }
+
+ [Test]
+ public void GetReferencingProjects_ThreeProjectsOneProjectReferencesModifiedProject_OneProjectReturned ()
+ {
+ var dotNetProject = CreateDotNetCoreProject ();
+ AddParentSolution (dotNetProject);
+ var referencedProject = CreateDotNetCoreProject ();
+ dotNetProject.ParentSolution.RootFolder.AddItem (referencedProject);
+ referencedProject.References.Add (ProjectReference.CreateProjectReference (dotNetProject));
+ var otherProject = CreateDotNetCoreProject ();
+ dotNetProject.ParentSolution.RootFolder.AddItem (otherProject);
+
+ var projects = dotNetProject.GetReferencingProjects ().ToList ();
+
+ Assert.AreEqual (1, projects.Count);
+ Assert.AreEqual (projects[0], referencedProject);
+ }
+
+ [Test]
+ public void GetReferencingProjects_TwoProjectReferencesChainToModifiedProject_NotifyReferencesChangedForAllProjects ()
+ {
+ var dotNetProject = CreateDotNetCoreProject ();
+ AddParentSolution (dotNetProject);
+ var referencingProject1 = CreateDotNetCoreProject ();
+ dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject1);
+ referencingProject1.References.Add (ProjectReference.CreateProjectReference (dotNetProject));
+ var referencingProject2 = CreateDotNetCoreProject ();
+ dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject2);
+ referencingProject2.References.Add (ProjectReference.CreateProjectReference (referencingProject1));
+ var otherProject = CreateDotNetCoreProject ();
+ dotNetProject.ParentSolution.RootFolder.AddItem (otherProject);
+
+ var projects = dotNetProject.GetReferencingProjects ().ToList ();
+
+ Assert.AreEqual (2, projects.Count);
+ Assert.That (projects, Contains.Item (referencingProject1));
+ Assert.That (projects, Contains.Item (referencingProject2));
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RestoreNuGetPackagesInNuGetIntegratedProjectTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RestoreNuGetPackagesInNuGetIntegratedProjectTests.cs new file mode 100644 index 0000000000..bf48dc9bdd --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RestoreNuGetPackagesInNuGetIntegratedProjectTests.cs @@ -0,0 +1,151 @@ +// +// RestoreNuGetPackagesInNuGetIntegratedProjectTests.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2017 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using MonoDevelop.PackageManagement.Tests.Helpers; +using MonoDevelop.Projects; +using NUnit.Framework; +namespace MonoDevelop.PackageManagement.Tests +{ + [TestFixture] + class RestoreNuGetPackagesInNuGetIntegratedProjectTests + { + RestoreNuGetPackagesInNuGetIntegratedProject action; + FakeSolutionManager solutionManager; + FakeSolution fakeSolution; + DotNetProject dotNetProject; + FakeDotNetProject fakeDotNetProject; + TestableDotNetCoreNuGetProject nugetProject; + FakeMonoDevelopBuildIntegratedRestorer buildIntegratedRestorer; + + void CreateProject () + { + solutionManager = new FakeSolutionManager (); + fakeSolution = new FakeSolution (); + CreateNuGetProject (); + fakeDotNetProject = new FakeDotNetProject (dotNetProject.FileName); + fakeDotNetProject.ParentSolution = fakeSolution; + fakeDotNetProject.DotNetProject = dotNetProject; + fakeSolution.Projects.Add (fakeDotNetProject); + } + + void CreateAction (bool restoreTransitiveProjectReferences = false) + { + action = new RestoreNuGetPackagesInNuGetIntegratedProject ( + fakeDotNetProject, + nugetProject, + solutionManager, + buildIntegratedRestorer, + restoreTransitiveProjectReferences); + } + + void CreateNuGetProject (string projectName = "MyProject", string fileName = @"d:\projects\MyProject\MyProject.csproj") + { + dotNetProject = CreateDotNetCoreProject (projectName, fileName); + var solution = new Solution (); + solution.RootFolder.AddItem (dotNetProject); + nugetProject = new TestableDotNetCoreNuGetProject (dotNetProject); + buildIntegratedRestorer = nugetProject.BuildIntegratedRestorer; + } + + TestableDotNetCoreNuGetProject CreateNuGetProject (DotNetProject project) + { + var dotNetProjectProxy = new FakeDotNetProject (); + dotNetProjectProxy.DotNetProject = project; + fakeSolution.Projects.Add (dotNetProjectProxy); + + var dotNetCoreNuGetProject = new TestableDotNetCoreNuGetProject (project); + dotNetCoreNuGetProject.BuildIntegratedRestorer = null; + + solutionManager.NuGetProjectsUsingDotNetProjects.Add (project, dotNetCoreNuGetProject); + + return dotNetCoreNuGetProject; + } + + static DummyDotNetProject CreateDotNetCoreProject (string projectName = "MyProject", string fileName = @"d:\projects\MyProject\MyProject.csproj") + { + var project = new DummyDotNetProject (); + project.Name = projectName; + project.FileName = fileName.ToNativePath (); + return project; + } + + [Test] + public void Execute_BuildIntegratedRestorer_PackagesRestoredForProject () + { + CreateProject (); + CreateAction (); + + action.Execute (); + + Assert.AreEqual (nugetProject, buildIntegratedRestorer.ProjectRestored); + } + + [Test] + public void Execute_Events_PackagesRestoredEventFired () + { + CreateProject (); + CreateAction (); + bool packagesRestoredEventFired = false; + PackageManagementServices.PackageManagementEvents.PackagesRestored += (sender, e) => { + packagesRestoredEventFired = true; + }; + + action.Execute (); + + Assert.IsTrue (packagesRestoredEventFired); + } + + [Test] + public void Execute_ReferenceStatus_IsRefreshed () + { + CreateProject (); + CreateAction (); + + action.Execute (); + + Assert.IsTrue (fakeDotNetProject.IsReferenceStatusRefreshed); + } + + [Test] + public void IncludeTransitiveProjectReferences_ThreeProjectsOneReferencedAnother_TwoProjectsRestored () + { + CreateProject (); + var referencingProject = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (referencingProject); + referencingProject.References.Add (ProjectReference.CreateProjectReference (dotNetProject)); + var otherProject = CreateDotNetCoreProject (); + dotNetProject.ParentSolution.RootFolder.AddItem (otherProject); + var referencingNuGetProject = CreateNuGetProject (referencingProject); + CreateAction (true); + + action.Execute (); + + Assert.AreEqual (2, buildIntegratedRestorer.ProjectsRestored.Count); + Assert.AreEqual (buildIntegratedRestorer.ProjectsRestored[0], nugetProject); + Assert.AreEqual (buildIntegratedRestorer.ProjectsRestored[1], referencingNuGetProject); + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml index 3b548d5dcf..e870fa461b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml @@ -113,7 +113,7 @@ <Extension path="/MonoDevelop/Ide/GlobalOptionsDialog">
<Section id="NuGetPackageManagement" _label="NuGet" insertafter="VersionControl">
- <Section id="General" _label="General" fill="true" class="MonoDevelop.PackageManagement.Gui.PackageManagementOptionsPanel" icon="md-prefs-package" />
+ <Section id="NuGetGeneral" _label="General" fill="true" class="MonoDevelop.PackageManagement.Gui.PackageManagementOptionsPanel" icon="md-prefs-package" />
<Section id="PackageSources" _label="Sources" fill="true" class="MonoDevelop.PackageManagement.Gui.PackageSourcesOptionsPanel" icon="md-prefs-package-source" />
</Section>
</Extension>
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj index ecc1b8ec8f..42514317d9 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj @@ -402,6 +402,7 @@ <Compile Include="MonoDevelop.PackageManagement\PackageActionType.cs" /> <Compile Include="MonoDevelop.PackageManagement\PendingPackageActionsHandler.cs" /> <Compile Include="MonoDevelop.PackageManagement\MonoDevelopMSBuildNuGetProject.cs" /> + <Compile Include="MonoDevelop.PackageManagement\IMonoDevelopBuildIntegratedRestorer.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDevelop.PackageManagement.addin.xml" /> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetCoreNuGetProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetCoreNuGetProject.cs index d4cdbb10fa..bd1900e7ec 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetCoreNuGetProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetCoreNuGetProject.cs @@ -270,7 +270,7 @@ namespace MonoDevelop.PackageManagement } Runtime.RunInMainThread (() => { - DotNetProject.NotifyModified ("References"); + DotNetProject.DotNetCoreNotifyReferencesChanged (); }); packageManagementEvents.OnFileChanged (project.GetNuGetAssetsFilePath ()); @@ -281,8 +281,7 @@ namespace MonoDevelop.PackageManagement async Task RestorePackages (INuGetProjectContext nuGetProjectContext, CancellationToken token) { var packageRestorer = await Runtime.RunInMainThread (() => { - var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (project.ParentSolution); - return new MonoDevelopBuildIntegratedRestorer (solutionManager); + return CreateBuildIntegratedRestorer (project.ParentSolution); }); var restoreTask = packageRestorer.RestorePackages (this, token); @@ -293,7 +292,7 @@ namespace MonoDevelop.PackageManagement if (!packageRestorer.LockFileChanged) { // Need to refresh the references since the restore did not. await Runtime.RunInMainThread (() => { - DotNetProject.NotifyModified ("References"); + DotNetProject.DotNetCoreNotifyReferencesChanged (); packageManagementEvents.OnFileChanged (project.GetNuGetAssetsFilePath ()); }); } @@ -301,6 +300,12 @@ namespace MonoDevelop.PackageManagement await base.PostProcessAsync (nuGetProjectContext, token); } + protected virtual IMonoDevelopBuildIntegratedRestorer CreateBuildIntegratedRestorer (Solution solution) + { + var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (project.ParentSolution); + return new MonoDevelopBuildIntegratedRestorer (solutionManager); + } + public void OnBeforeUninstall (IEnumerable<NuGetProjectAction> actions) { } @@ -310,12 +315,16 @@ namespace MonoDevelop.PackageManagement restoreRequired = actions.Any (action => action.NuGetProjectActionType == NuGetProjectActionType.Install); } - public void NotifyProjectReferencesChanged () + public void NotifyProjectReferencesChanged (bool includeTransitiveProjectReferences) { Runtime.AssertMainThread (); DotNetProject.RefreshProjectBuilder (); - DotNetProject.NotifyModified ("References"); + + if (includeTransitiveProjectReferences) + DotNetProject.DotNetCoreNotifyReferencesChanged (); + else + DotNetProject.NotifyModified ("References"); } /// <summary> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs index fb79aee86b..4d230bb4e3 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs @@ -216,5 +216,97 @@ namespace MonoDevelop.PackageManagement return File.Exists (propsFileName) &&
File.Exists (targetsFileName);
}
+
+ /// <summary>
+ /// If a NuGet package is installed into a .NET Core project then all .NET Core projects that
+ /// reference this project need to have their reference information updated. This allows the
+ /// assemblies from the NuGet package to be made available to the other projects since .NET
+ /// Core projects support transitive references. This method calls NotifyModified for each
+ /// project that references it, as well as for the project itself, passing the hint 'References'
+ /// which will cause the type system to refresh its reference information, which will be taken
+ /// from MSBuild.
+ ///
+ /// All projects that reference .NET Core projects will have their references refreshed. If a
+ /// .NET Framework project (non SDK), has PackageReferences and references a .NET Standard project
+ /// (SDK project) then NuGet dependencies from the .NET Standard project are available to the
+ /// .NET Framework project transitively without needing the NuGet package to be installed into
+ /// the .NET Framework project. So refreshing the references of any project that references a
+ /// .NET Core project will ensure assemblies from NuGet packages are available after installing
+ /// a new NuGet package into the referenced project.
+ /// </summary>
+ /// <param name="project">.NET Core project</param>
+ /// <param name="transitiveOnly">If false then the project passed will also have its
+ /// references refreshed. Otherwise only the projects that reference the project will
+ /// have their references refreshed.</param>
+ public static void DotNetCoreNotifyReferencesChanged (this DotNetProject project, bool transitiveOnly = false)
+ {
+ if (!transitiveOnly)
+ project.NotifyModified ("References");
+
+ foreach (var referencingProject in project.GetReferencingProjects ()) {
+ referencingProject.NotifyModified ("References");
+ }
+ }
+
+ /// <summary>
+ /// Returns all projects that directly or indirectly referencing the specified project.
+ /// </summary>
+ public static IEnumerable<DotNetProject> GetReferencingProjects (this DotNetProject project)
+ {
+ var projects = new List<DotNetProject> ();
+ var traversedProjects = new Dictionary<string, bool> (StringComparer.OrdinalIgnoreCase);
+ traversedProjects.Add (project.ItemId, true);
+
+ foreach (var currentProject in project.ParentSolution.GetAllDotNetProjects ()) {
+ if (!traversedProjects.ContainsKey (currentProject.ItemId))
+ GetReferencingProjects (project, currentProject, traversedProjects, projects);
+ }
+
+ return projects;
+ }
+
+ static bool GetReferencingProjects (
+ DotNetProject mainProject,
+ DotNetProject project,
+ Dictionary<string, bool> traversedProjects,
+ List<DotNetProject> referencingProjects)
+ {
+ foreach (var projectReference in project.References.Where (IncludeProjectReference)) {
+ var resolvedProject = projectReference.ResolveProject (mainProject.ParentSolution) as DotNetProject;
+ if (resolvedProject == null)
+ continue;
+
+ if (resolvedProject == mainProject) {
+ traversedProjects [project.ItemId] = true;
+ referencingProjects.Add (project);
+ return true;
+ }
+
+ if (traversedProjects.TryGetValue (resolvedProject.ItemId, out bool referencesProject)) {
+ if (referencesProject) {
+ traversedProjects [project.ItemId] = referencesProject;
+ referencingProjects.Add (project);
+ return true;
+ }
+ continue;
+ }
+
+ if (GetReferencingProjects (mainProject, resolvedProject, traversedProjects, referencingProjects)) {
+ traversedProjects [project.ItemId] = true;
+ referencingProjects.Add (project);
+ return true;
+ }
+ }
+
+ traversedProjects [project.ItemId] = false;
+
+ return false;
+ }
+
+ static bool IncludeProjectReference (ProjectReference projectReference)
+ {
+ return projectReference.ReferenceType == ReferenceType.Project &&
+ projectReference.ReferenceOutputAssembly;
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IBuildIntegratedNuGetProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IBuildIntegratedNuGetProject.cs index b14d19a7ba..666e49130f 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IBuildIntegratedNuGetProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IBuildIntegratedNuGetProject.cs @@ -37,7 +37,13 @@ namespace MonoDevelop.PackageManagement void OnBeforeUninstall (IEnumerable<NuGetProjectAction> actions); void OnAfterExecuteActions (IEnumerable<NuGetProjectAction> actions); Task PostProcessAsync (INuGetProjectContext nuGetProjectContext, CancellationToken token); - void NotifyProjectReferencesChanged (); + + /// <summary> + /// Notifies the project references changed. + /// </summary> + /// <param name="includeTransitiveProjectReferences">If set to <c>true</c> also notify references + /// have changed in all projects that transitively reference this project.</param> + void NotifyProjectReferencesChanged (bool includeTransitiveProjectReferences); } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IMonoDevelopBuildIntegratedRestorer.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IMonoDevelopBuildIntegratedRestorer.cs new file mode 100644 index 0000000000..8c693b321e --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IMonoDevelopBuildIntegratedRestorer.cs @@ -0,0 +1,46 @@ +// +// IMonoDevelopBuildIntegratedRestorer.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2017 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using System.Threading;
+using System.Threading.Tasks; +using NuGet.ProjectManagement.Projects; + +namespace MonoDevelop.PackageManagement +{ + interface IMonoDevelopBuildIntegratedRestorer + { + Task RestorePackages ( + BuildIntegratedNuGetProject project, + CancellationToken cancellationToken); + + Task RestorePackages ( + IEnumerable<BuildIntegratedNuGetProject> projects, + CancellationToken cancellationToken); + + bool LockFileChanged { get; } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopBuildIntegratedRestorer.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopBuildIntegratedRestorer.cs index c59a3bdb82..977892b125 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopBuildIntegratedRestorer.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopBuildIntegratedRestorer.cs @@ -44,7 +44,7 @@ using NuGet.Protocol.Core.Types; namespace MonoDevelop.PackageManagement
{
- internal class MonoDevelopBuildIntegratedRestorer
+ internal class MonoDevelopBuildIntegratedRestorer : IMonoDevelopBuildIntegratedRestorer
{
IPackageManagementEvents packageManagementEvents;
List<SourceRepository> sourceRepositories;
@@ -98,8 +98,10 @@ namespace MonoDevelop.PackageManagement LockFileChanged = true; await Runtime.RunInMainThread (() => { FileService.NotifyFilesChanged (changedLocks); - foreach (var project in affectedProjects) { - NotifyProjectReferencesChanged (project); + foreach (var project in affectedProjects) {
+ // Restoring the entire solution so do not refresh references for
+ // transitive project references since they should be refreshed anyway. + NotifyProjectReferencesChanged (project, includeTransitiveProjectReferences: false); } }); }
@@ -114,12 +116,17 @@ namespace MonoDevelop.PackageManagement var changedLock = await RestorePackagesInternal (project, cancellationToken); if (projectToReload != null) {
- await ReloadProject (projectToReload, changedLock);
+ // Need to ensure transitive project references are refreshed if only the single
+ // project is reloaded since they will still be out of date.
+ await ReloadProject (projectToReload, changedLock, refreshTransitiveReferences: true);
} else if (changedLock != null) { LockFileChanged = true;
await Runtime.RunInMainThread (() => { - FileService.NotifyFileChanged (changedLock); - NotifyProjectReferencesChanged (project); + FileService.NotifyFileChanged (changedLock);
+
+ // Restoring a single project so ensure references are refreshed for
+ // transitive project references. + NotifyProjectReferencesChanged (project, includeTransitiveProjectReferences: true); }); } } @@ -152,11 +159,13 @@ namespace MonoDevelop.PackageManagement return null; } - static void NotifyProjectReferencesChanged (BuildIntegratedNuGetProject project) + static void NotifyProjectReferencesChanged (
+ BuildIntegratedNuGetProject project,
+ bool includeTransitiveProjectReferences) { var buildIntegratedProject = project as IBuildIntegratedNuGetProject; if (buildIntegratedProject != null) {
- buildIntegratedProject.NotifyProjectReferencesChanged (); + buildIntegratedProject.NotifyProjectReferencesChanged (includeTransitiveProjectReferences); } }
@@ -190,7 +199,7 @@ namespace MonoDevelop.PackageManagement return null;
}
- Task ReloadProject (DotNetProject projectToReload, string changedLock)
+ Task ReloadProject (DotNetProject projectToReload, string changedLock, bool refreshTransitiveReferences = false)
{
return Runtime.RunInMainThread (async () => {
if (changedLock != null) {
@@ -198,6 +207,9 @@ namespace MonoDevelop.PackageManagement FileService.NotifyFileChanged (changedLock);
}
await projectToReload.ReevaluateProject (new ProgressMonitor ());
+
+ if (refreshTransitiveReferences)
+ projectToReload.DotNetCoreNotifyReferencesChanged (transitiveOnly: true);
});
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageReferenceNuGetProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageReferenceNuGetProject.cs index 5e5f23db73..3cd19824ce 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageReferenceNuGetProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageReferenceNuGetProject.cs @@ -273,7 +273,7 @@ namespace MonoDevelop.PackageManagement { } - public void NotifyProjectReferencesChanged () + public void NotifyProjectReferencesChanged (bool includeTransitiveProjectReferences) { Runtime.AssertMainThread (); diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs index 9a6d0d9f06..2005caeaf0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs @@ -167,6 +167,11 @@ namespace MonoDevelop.PackageManagement get { return viewModel.DownloadCount >= 0; }
}
+ public string GetIdMarkup ()
+ {
+ return GetBoldText (Id);
+ }
+
public string GetNameMarkup ()
{
return GetBoldText (Name);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectJsonBuildIntegratedNuGetProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectJsonBuildIntegratedNuGetProject.cs index 02ef5caddd..9c3086648a 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectJsonBuildIntegratedNuGetProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProjectJsonBuildIntegratedNuGetProject.cs @@ -123,7 +123,7 @@ namespace MonoDevelop.PackageManagement packageManagementEvents.OnPackageUninstalled (dotNetProject, eventArgs);
}
- public void NotifyProjectReferencesChanged ()
+ public void NotifyProjectReferencesChanged (bool includeTransitiveProjectReferences)
{
Runtime.AssertMainThread ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreNuGetPackagesInNuGetIntegratedProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreNuGetPackagesInNuGetIntegratedProject.cs index 7b796c7b1c..e5cef02523 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreNuGetPackagesInNuGetIntegratedProject.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RestoreNuGetPackagesInNuGetIntegratedProject.cs @@ -24,6 +24,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MonoDevelop.Core;
@@ -34,21 +36,42 @@ namespace MonoDevelop.PackageManagement {
internal class RestoreNuGetPackagesInNuGetIntegratedProject : IPackageAction
{
- DotNetProject project;
+ IDotNetProject project;
BuildIntegratedNuGetProject nugetProject;
- MonoDevelopBuildIntegratedRestorer packageRestorer;
+ IMonoDevelopSolutionManager solutionManager;
+ IMonoDevelopBuildIntegratedRestorer packageRestorer;
IPackageManagementEvents packageManagementEvents;
+ List<BuildIntegratedNuGetProject> referencingProjects;
public RestoreNuGetPackagesInNuGetIntegratedProject (
DotNetProject project,
BuildIntegratedNuGetProject nugetProject,
- IMonoDevelopSolutionManager solutionManager)
+ IMonoDevelopSolutionManager solutionManager,
+ bool restoreTransitiveProjectReferences = false)
+ : this (
+ new DotNetProjectProxy (project),
+ nugetProject,
+ solutionManager,
+ new MonoDevelopBuildIntegratedRestorer (solutionManager),
+ restoreTransitiveProjectReferences)
+ {
+ }
+
+ public RestoreNuGetPackagesInNuGetIntegratedProject (
+ IDotNetProject project,
+ BuildIntegratedNuGetProject nugetProject,
+ IMonoDevelopSolutionManager solutionManager,
+ IMonoDevelopBuildIntegratedRestorer packageRestorer,
+ bool restoreTransitiveProjectReferences)
{
this.project = project;
this.nugetProject = nugetProject;
+ this.solutionManager = solutionManager;
+ this.packageRestorer = packageRestorer;
packageManagementEvents = PackageManagementServices.PackageManagementEvents;
- - packageRestorer = new MonoDevelopBuildIntegratedRestorer (solutionManager); +
+ if (restoreTransitiveProjectReferences)
+ IncludeTransitiveProjectReferences (); }
public PackageActionType ActionType {
@@ -75,12 +98,44 @@ namespace MonoDevelop.PackageManagement async Task ExecuteAsync (CancellationToken cancellationToken)
{
- await packageRestorer.RestorePackages (nugetProject, cancellationToken);
+ if (referencingProjects == null)
+ await packageRestorer.RestorePackages (nugetProject, cancellationToken);
+ else
+ await RestoreMultiplePackages (cancellationToken);
await Runtime.RunInMainThread (() => project.RefreshReferenceStatus ());
packageManagementEvents.OnPackagesRestored ();
}
+
+ /// <summary>
+ /// Execute will restore packages for all projects that transitively reference the project
+ /// passed to the constructor of this restore action if this method is passed.
+ /// </summary>
+ void IncludeTransitiveProjectReferences ()
+ {
+ var projects = project.DotNetProject.GetReferencingProjects ();
+ if (!projects.Any ())
+ return;
+
+ referencingProjects = new List<BuildIntegratedNuGetProject> ();
+ foreach (var referencingProject in projects) {
+ var projectProxy = new DotNetProjectProxy (referencingProject);
+ var currentNuGetProject = solutionManager.GetNuGetProject (projectProxy) as BuildIntegratedNuGetProject;
+ if (currentNuGetProject != null) {
+ referencingProjects.Add (currentNuGetProject);
+ }
+ }
+ }
+
+ Task RestoreMultiplePackages (CancellationToken cancellationToken)
+ {
+ var projects = new List<BuildIntegratedNuGetProject> ();
+ projects.Add (nugetProject);
+ projects.AddRange (referencingProjects);
+
+ return packageRestorer.RestorePackages (projects, cancellationToken);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs index 0008cbeaf2..3f6f091de5 100644 --- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs +++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs @@ -54,6 +54,9 @@ namespace MonoDevelop.Packaging.Gui void SetupAccessibility () { + packageDescriptionPaddingLabel.Accessible.Role = Atk.Role.Filler; + packageReleaseNotesPaddingLabel.Accessible.Role = Atk.Role.Filler; + packageIdTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.ID", GettextCatalog.GetString ("ID"), GettextCatalog.GetString ("Enter the ID of the NuGet package")); @@ -133,6 +136,7 @@ namespace MonoDevelop.Packaging.Gui GettextCatalog.GetString ("Release Notes"), GettextCatalog.GetString ("Enter the release notes for this NuGet package")); packageReleaseNotesTextView.SetAccessibilityLabelRelationship (packageReleaseNotesLabel); + } internal static System.Action<bool> OnProjectHasMetadataChanged; diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/MSBuildGlobalPropertyProvider.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/MSBuildGlobalPropertyProvider.cs index a8d71b8ddf..8d7d050b1d 100644 --- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/MSBuildGlobalPropertyProvider.cs +++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/MSBuildGlobalPropertyProvider.cs @@ -33,7 +33,7 @@ namespace MonoDevelop.Packaging { class MSBuildGlobalPropertyProvider : IMSBuildGlobalPropertyProvider { - Dictionary<string, string> properties; + Lazy<Dictionary<string, string>> properties = new Lazy<Dictionary<string, string>> (CreateProperties); #pragma warning disable 67 public event EventHandler GlobalPropertiesChanged; @@ -41,13 +41,17 @@ namespace MonoDevelop.Packaging public IDictionary<string, string> GetGlobalProperties () { - if (properties == null) { - string addinDirectory = Path.GetDirectoryName (GetType ().Assembly.Location); - string targetsDirectory = Path.Combine (addinDirectory, "Targets"); + return properties.Value; + } + + static Dictionary<string, string> CreateProperties () + { + string addinDirectory = Path.GetDirectoryName (typeof (MSBuildGlobalPropertyProvider).Assembly.Location); + string targetsDirectory = Path.Combine (addinDirectory, "Targets"); + + var properties = new Dictionary<string, string> (); + properties.Add ("NuGetAuthoringPath", targetsDirectory); - properties = new Dictionary<string, string> (); - properties.Add ("NuGetAuthoringPath", targetsDirectory); - } return properties; } } diff --git a/main/src/addins/MonoDevelop.Packaging/PostBuild.proj b/main/src/addins/MonoDevelop.Packaging/PostBuild.proj index 0cbc3eba24..881103530a 100644 --- a/main/src/addins/MonoDevelop.Packaging/PostBuild.proj +++ b/main/src/addins/MonoDevelop.Packaging/PostBuild.proj @@ -7,6 +7,6 @@ <_MyNuGetPackage Include="$(MSBuildProjectDirectory)\..\..\..\packages\NuGet.Build.Packaging.$(_BuildPackagingVersion)\NuGet.Build.Packaging.$(_BuildPackagingVersion).nupkg" /> </ItemGroup> <Target Name="_MyPostBuildTarget"> - <Copy SourceFiles="@(_MyNuGetPackage)" DestinationFolder="$(OutputPath)\packages" /> + <Copy SourceFiles="@(_MyNuGetPackage)" DestinationFolder="$(OutputPath)\packages" SkipUnchangedFiles="true" /> </Target> </Project>
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs index 5a3e11c048..bf095d965d 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs @@ -38,6 +38,7 @@ using System.Linq; using MonoDevelop.Core; using Pango; using MonoDevelop.Ide.Editor.Highlighting; +using Gdk; namespace MonoDevelop.Refactoring { @@ -113,10 +114,25 @@ namespace MonoDevelop.Refactoring } catch (OperationCanceledException) {} return new List<DiffHunk> (); }); - if (diff.Count > 0 && !token.IsCancellationRequested) - ShowPopup (rect, PopupPosition.Left); + if (diff.Count > 0 && !token.IsCancellationRequested) { + var pos = PopupPosition.Left; + if (Platform.IsMac) { + var screenRect = GtkUtil.ToScreenCoordinates (IdeApp.Workbench.RootWindow, IdeApp.Workbench.RootWindow.GdkWindow, rect.ToGdkRectangle ()); + var geometry = Screen.GetUsableMonitorGeometry (Screen.GetMonitorAtPoint (screenRect.X, screenRect.Y)); + var request = SizeRequest (); + if (screenRect.X - geometry.X < request.Width) { + pos = PopupPosition.Top; + if (geometry.Bottom - screenRect.Bottom < request.Height) + pos = PopupPosition.Bottom; + } else { + pos = PopupPosition.Right; + } + } + ShowPopup (rect, pos); + } } + protected override void OnDestroyed () { popupSrc.Cancel (); diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/CompletionOptionsPanel.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/CompletionOptionsPanel.cs index 1b93094ec8..e03bfce0aa 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/CompletionOptionsPanel.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/CompletionOptionsPanel.cs @@ -65,9 +65,9 @@ namespace MonoDevelop.SourceEditor.OptionPanels includeCodeSnippetsCheckbutton.Active = IdeApp.Preferences.IncludeCodeSnippetsInCompletionList; automaticCompletionModeCheckbutton.Active = !IdeApp.Preferences.ForceSuggestionMode; - insertParenthesesCheckbutton.Active = IdeApp.Preferences.AddParenthesesAfterCompletion; - openingRadiobutton.Active = IdeApp.Preferences.AddOpeningOnly; - bothRadiobutton.Active = !IdeApp.Preferences.AddOpeningOnly; + insertParenthesesCheckbutton.Visible = false; + openingRadiobutton.Visible = false; + bothRadiobutton.Visible = false; InsertParensToggled (this, EventArgs.Empty); AutomaticCompletionToggled (this, EventArgs.Empty); @@ -97,9 +97,6 @@ namespace MonoDevelop.SourceEditor.OptionPanels IdeApp.Preferences.IncludeKeywordsInCompletionList.Value = includeKeywordsCheckbutton.Active; IdeApp.Preferences.IncludeCodeSnippetsInCompletionList.Value = includeCodeSnippetsCheckbutton.Active; IdeApp.Preferences.ForceSuggestionMode.Value = !automaticCompletionModeCheckbutton.Active; - - IdeApp.Preferences.AddParenthesesAfterCompletion.Value = insertParenthesesCheckbutton.Active; - IdeApp.Preferences.AddOpeningOnly.Value = openingRadiobutton.Active; } #endregion diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskStrip.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskStrip.cs index 9174d68d10..cfef8d4174 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskStrip.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskStrip.cs @@ -130,6 +130,8 @@ namespace MonoDevelop.SourceEditor.QuickTasks Events |= EventMask.ButtonPressMask; Accessible.Name = "MainWindow.QuickTaskStrip"; + Accessible.SetShouldIgnore (false); + Accessible.SetRole (AtkCocoa.Roles.AXRuler); Accessible.SetLabel (GettextCatalog.GetString ("Quick Task Strip")); Accessible.Description = GettextCatalog.GetString ("An overview of the current file's messages, warnings and errors"); diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.Wrappers/SemanticHighlightingSyntaxMode.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.Wrappers/SemanticHighlightingSyntaxMode.cs index 948f9b1838..fb40caca1c 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.Wrappers/SemanticHighlightingSyntaxMode.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.Wrappers/SemanticHighlightingSyntaxMode.cs @@ -81,7 +81,6 @@ namespace MonoDevelop.SourceEditor.Wrappers } bool isDisposed; - Queue<Tuple<IDocumentLine, HighlightingSegmentTree>> lineSegments = new Queue<Tuple<IDocumentLine, HighlightingSegmentTree>> (); public SemanticHighlightingSyntaxMode (ExtensibleTextEditor editor, ISyntaxHighlighting syntaxMode, SemanticHighlighting semanticHighlighting) { @@ -113,9 +112,6 @@ namespace MonoDevelop.SourceEditor.Wrappers Application.Invoke ((o, args) => { if (isDisposed) return; - UnregisterLineSegmentTrees (); - lineSegments.Clear (); - var margin = editor.TextViewMargin; if (margin == null) return; @@ -124,26 +120,12 @@ namespace MonoDevelop.SourceEditor.Wrappers }); } - void UnregisterLineSegmentTrees () - { - if (isDisposed) - return; - foreach (var kv in lineSegments) { - try { - kv.Item2.RemoveListener (); - } catch (Exception) { - } - } - } - public void Dispose() { if (isDisposed) return; // Unregister before setting isDisposed=true, as that causes the method to bail out early. - UnregisterLineSegmentTrees (); isDisposed = true; - lineSegments = null; semanticHighlighting.SemanticHighlightingUpdated -= SemanticHighlighting_SemanticHighlightingUpdated; } @@ -153,54 +135,35 @@ namespace MonoDevelop.SourceEditor.Wrappers { if (line == null) throw new ArgumentNullException (nameof (line)); + if (!DefaultSourceEditorOptions.Instance.EnableSemanticHighlighting) { return await syntaxMode.GetHighlightedLineAsync (line, cancellationToken); } var syntaxLine = await syntaxMode.GetHighlightedLineAsync (line, cancellationToken).ConfigureAwait (false); - if (syntaxLine.Segments.Count == 0) + if (syntaxLine.Segments.Count == 0) { return syntaxLine; - lock (lineSegments) { - var segments = new List<ColoredSegment> (syntaxLine.Segments); - int endOffset = segments [segments.Count - 1].EndOffset; - try { - Tuple<IDocumentLine, HighlightingSegmentTree> tree = null; - - // This code should not have any lambda capture linq, as it is a hot loop. - int lineOffset = line.Offset; - foreach (var segment in lineSegments) {
- if (segment.Item1.Offset == lineOffset) {
- tree = segment;
- break;
- }
- }
- if (tree == null) { - tree = Tuple.Create (line, new HighlightingSegmentTree ()); - tree.Item2.InstallListener (editor.Document); - foreach (var seg2 in semanticHighlighting.GetColoredSegments (new TextSegment (lineOffset, line.Length))) { - tree.Item2.AddStyle (seg2, seg2.ColorStyleKey); - } - while (lineSegments.Count > MaximumCachedLineSegments) { - var removed = lineSegments.Dequeue (); - try { - removed.Item2.RemoveListener (); - } catch (Exception) { } - } - lineSegments.Enqueue (tree); - } - foreach (var treeseg in tree.Item2.GetSegmentsOverlapping (line)) { - var inLineStartOffset = Math.Max (0, treeseg.Offset - lineOffset); - var inLineEndOffset = Math.Min (line.Length, treeseg.EndOffset - lineOffset); - if (inLineEndOffset <= inLineStartOffset) - continue; - var semanticSegment = new ColoredSegment (inLineStartOffset, inLineEndOffset - inLineStartOffset, syntaxLine.Segments [0].ScopeStack.Push (treeseg.Style)); - SyntaxHighlighting.ReplaceSegment (segments, semanticSegment); + } + var segments = new List<ColoredSegment> (syntaxLine.Segments); + int endOffset = segments [segments.Count - 1].EndOffset; + try { + // This code should not have any lambda capture linq, as it is a hot loop. + int lineOffset = line.Offset; + + foreach (var treeseg in semanticHighlighting.GetColoredSegments (new TextSegment (lineOffset, line.Length))) { + var inLineStartOffset = Math.Max (0, treeseg.Offset - lineOffset); + var inLineEndOffset = Math.Min (line.Length, treeseg.EndOffset - lineOffset); + + if (inLineEndOffset <= inLineStartOffset) { + continue; } - } catch (Exception e) { - LoggingService.LogError ("Error in semantic highlighting: " + e); - return syntaxLine; + var semanticSegment = new ColoredSegment (inLineStartOffset, inLineEndOffset - inLineStartOffset, treeseg.ScopeStack); + SyntaxHighlighting.ReplaceSegment (segments, semanticSegment); } - return new HighlightedLine (line, segments); + } catch (Exception e) { + LoggingService.LogError ("Error in semantic highlighting: " + e); + return syntaxLine; } + return new HighlightedLine (line, segments); } async Task<ScopeStack> ISyntaxHighlighting.GetScopeStackAsync (int offset, CancellationToken cancellationToken) diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/EditActions.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/EditActions.cs index 564f7a772d..976c8c6893 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/EditActions.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/EditActions.cs @@ -75,21 +75,23 @@ namespace MonoDevelop.SourceEditor { if (!data.IsSomethingSelected && MonoDevelop.Ide.Editor.DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket) { if (data.Caret.Offset > 0) { - var stack = await data.Document.SyntaxMode.GetScopeStackAsync (data.Caret.Offset, CancellationToken.None); - if (stack.Any (s => s.Contains ("string"))) { - DeleteActions.Backspace (data); - return; - } - char ch = data.Document.GetCharAt (data.Caret.Offset - 1); + DeleteActions.Backspace (data); + if (data.Caret.Offset > 0) { + var stack = await data.Document.SyntaxMode.GetScopeStackAsync (data.Caret.Offset - 1, CancellationToken.None); + if (stack.Any (s => s.Contains ("string") || s.Contains ("comment"))) { + return; + } + } + int idx = open.IndexOf (ch); - if (idx >= 0) { int nextCharOffset = GetNextNonWsCharOffset (data, data.Caret.Offset); if (nextCharOffset >= 0 && closing[idx] == data.Document.GetCharAt (nextCharOffset)) { data.Remove (data.Caret.Offset, nextCharOffset - data.Caret.Offset + 1); } } + return; } } DeleteActions.Backspace (data); diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorWidget.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorWidget.cs index 579854ddc2..70bfadff65 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorWidget.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorWidget.cs @@ -236,6 +236,7 @@ namespace MonoDevelop.SourceEditor scrolledBackground = new EventBox (); scrolledBackground.Accessible.SetShouldIgnore (true); scrolledWindow = new CompactScrolledWindow (); + scrolledWindow.CanFocus = false; scrolledWindow.ButtonPressEvent += PrepareEvent; scrolledWindow.Accessible.SetShouldIgnore (true); scrolledBackground.Add (scrolledWindow); diff --git a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs index dd598d13c6..234deb1883 100644 --- a/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs +++ b/main/src/addins/MonoDevelop.WebReferences/MonoDevelop.WebReferences.Dialogs/WebReferenceDialog.cs @@ -7,6 +7,7 @@ using System.Threading; using Gtk; using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.WebBrowser; using MonoDevelop.WebReferences; @@ -149,7 +150,7 @@ namespace MonoDevelop.WebReferences.Dialogs #endregion #region Member Variables - const string homeUrl = "http://www.w3schools.com/xml/tempconvert.asmx"; + const string homeUrl = "https://www.w3schools.com/xml/tempconvert.asmx?WSDL"; WebServiceDiscoveryResult selectedService; // protected Gtk.Alignment frmBrowserAlign; #endregion @@ -491,7 +492,15 @@ namespace MonoDevelop.WebReferences.Dialogs btnOK.Sensitive = isWebService; tlbNavigate.Visible = WebBrowserService.CanGetWebBrowser; tbxReferenceName.Sensitive = isWebService; - comboModel.Sensitive = !project.IsPortableLibrary; + if (project.IsPortableLibrary) + comboModel.Sensitive = false; + else if (IsWcfSupported ()) + comboModel.Sensitive = true; + else { + // Select web references instead of WCF. + comboModel.Active = 1; + comboModel.Sensitive = false; + } break; case DialogState.CreateConfig: @@ -595,6 +604,15 @@ namespace MonoDevelop.WebReferences.Dialogs } } + /// <summary> + /// PCL or projects that target .NET Framework are considered to support WCF. + /// </summary> + bool IsWcfSupported () + { + return project.TargetFramework.Id.Identifier == TargetFrameworkMoniker.ID_NET_FRAMEWORK || + project.IsPortableLibrary; + } + protected void OnBtnBackClicked (object sender, EventArgs e) { switch (state) { diff --git a/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Properties/PerformanceDiagnostics.addin.xml b/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Properties/PerformanceDiagnostics.addin.xml index d6ac4b04ff..4f6d2f7c0a 100644 --- a/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Properties/PerformanceDiagnostics.addin.xml +++ b/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Properties/PerformanceDiagnostics.addin.xml @@ -27,7 +27,7 @@ <Section id="PerformanceDiagnostics" _label="Performance Diagnostics" insertafter="VersionControl"> - <Section id="General" + <Section id="PerformanceDiagnosticsGeneral" _label="General" fill="true" class="PerformanceDiagnosticsAddIn.GlobalOptionsPanel" diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4PreprocessedTemplateCSharp.xft.xml b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4PreprocessedTemplateCSharp.xft.xml index cbd768e485..ca1f305f0d 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4PreprocessedTemplateCSharp.xft.xml +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4PreprocessedTemplateCSharp.xft.xml @@ -16,7 +16,7 @@ <!-- Template Content --> <TemplateFiles> <File name="${Name}.tt" CustomTool="TextTemplatingFilePreprocessor"> - <![CDATA[<#@ template language="C#" #> + <![CDATA[<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4TemplateCSharp.xft.xml b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4TemplateCSharp.xft.xml index c57eab6a4c..a15503a6d0 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4TemplateCSharp.xft.xml +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Templates/T4TemplateCSharp.xft.xml @@ -15,7 +15,7 @@ <!-- Template Content --> <TemplateFiles> <File name="${Name}.tt" CustomTool="TextTemplatingFileGenerator"> - <![CDATA[<#@ template language="C#" #> + <![CDATA[<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> diff --git a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextLinkEditMode.cs b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextLinkEditMode.cs index f5a563ae55..ad4d1e382b 100644 --- a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextLinkEditMode.cs +++ b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextLinkEditMode.cs @@ -219,12 +219,21 @@ namespace Mono.TextEditor handler (this, e); } - TextLink closedLink = null; + TextLink closedLink = null, currentSelectedLink = null; void HandlePositionChanged (object sender, DocumentLocationEventArgs e) { int caretOffset = Editor.Caret.Offset - baseOffset; TextLink link = links.Find (l => !l.PrimaryLink.IsInvalid () && l.PrimaryLink.Offset <= caretOffset && caretOffset <= l.PrimaryLink.EndOffset); + + if (link != currentSelectedLink) { + foreach (var l in textLinkMarkers) { + Editor.Document.CommitLineUpdate (l.LineSegment); + } + currentSelectedLink = link; + } + + if (link != null && link.Count > 0 && link.IsEditable) { if (closedLink == link) return; @@ -277,6 +286,7 @@ namespace Mono.TextEditor Editor.Document.CommitUpdateAll (); this.undoDepth = Editor.Document.GetCurrentUndoDepth (); ShowHelpWindow (); + currentSelectedLink = null; } public bool HasChangedText { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.AddIns/FalseCondition.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.AddIns/FalseCondition.cs new file mode 100644 index 0000000000..cdeb0dc46c --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.AddIns/FalseCondition.cs @@ -0,0 +1,48 @@ +// +// FalseCondition.cs +// +// Author: +// Lluis Sanchez <llsan@microsoft.com> +// +// Copyright (c) 2017 Microsoft +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Mono.Addins; + +namespace MonoDevelop.Core.AddIns +{ + /// <summary> + /// An extension point condition that always evaluates to false + /// </summary> + public class FalseCondition : ConditionType + { + public static readonly FalseCondition Instance = new FalseCondition (); + + FalseCondition () + { + } + + public override bool Evaluate (NodeElement conditionNode) + { + return false; + } + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.AddIns/TrueCondition.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.AddIns/TrueCondition.cs new file mode 100644 index 0000000000..0ea239feca --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.AddIns/TrueCondition.cs @@ -0,0 +1,48 @@ +// +// TrueCondition.cs +// +// Author: +// Lluis Sanchez <llsan@microsoft.com> +// +// Copyright (c) 2017 Microsoft +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Mono.Addins; + +namespace MonoDevelop.Core.AddIns +{ + /// <summary> + /// An extension point condition that always evaluates to True + /// </summary> + public class TrueCondition : ConditionType + { + public static readonly TrueCondition Instance = new TrueCondition (); + + TrueCondition () + { + } + + public override bool Evaluate (NodeElement conditionNode) + { + return true; + } + } +} diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj index 9aa335506e..a360e71054 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj @@ -1,11 +1,9 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <Import Project="..\..\..\MonoDevelop.props" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProductVersion>8.0.30703</ProductVersion> - <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{7525BB88-6142-4A26-93B9-A30C6983390A}</ProjectGuid> <OutputType>Library</OutputType> <AssemblyName>MonoDevelop.Core</AssemblyName> @@ -99,29 +97,9 @@ <MSBuild_OSS_BinDir Condition="'$(OS)' == 'Unix' and '$(MSBuild_OSS_BinDir)' == '' and Exists('$(MSBuildToolsPath)\..\..\..\msbuild\15.0\bin\MSBuild.dll')">$(MSBuildToolsPath)\..\..\..\msbuild\15.0\bin\</MSBuild_OSS_BinDir> </PropertyGroup> <ItemGroup> - <Reference Include="System" /> - <Reference Include="Mono.Posix" /> - <Reference Include="System.Composition.AttributedModel, Version=1.0.31.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>..\..\..\packages\System.Composition.AttributedModel.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath> - </Reference> - <Reference Include="System.Composition.Hosting, Version=1.0.31.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>..\..\..\packages\System.Composition.Hosting.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll</HintPath> - </Reference> - <Reference Include="System.Composition.Runtime, Version=1.0.31.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>..\..\..\packages\System.Composition.Runtime.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll</HintPath> - </Reference> - <Reference Include="System.Composition.TypedParts, Version=1.0.31.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>..\..\..\packages\System.Composition.TypedParts.1.0.31\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll</HintPath> + <Reference Include="ICSharpCode.SharpZipLib"> + <HintPath>..\..\..\packages\JetBrains.SharpZipLib.Stripped.0.87.20170615.10\lib\net40\ICSharpCode.SharpZipLib.dll</HintPath> </Reference> - <Reference Include="System.Xml" /> - <Reference Include="System.Runtime.Remoting" /> - <Reference Include="System.Configuration" /> - <Reference Include="System.Core" /> - <Reference Include="monodoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Web" /> - <Reference Include="System.ServiceModel" /> - <Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.Build"> <HintPath>$(MSBuild_OSS_BinDir)Microsoft.Build.dll</HintPath> <Private>False</Private> @@ -134,24 +112,41 @@ <HintPath>$(MSBuild_OSS_BinDir)Microsoft.Build.Utilities.Core.dll</HintPath> <Private>False</Private> </Reference> - <Reference Include="ICSharpCode.SharpZipLib"> - <HintPath>..\..\..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath> + <Reference Include="Microsoft.CodeAnalysis"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Common.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.dll</HintPath> + <Private>false</Private> </Reference> - <Reference Include="mscorlib" /> - <Reference Include="System.ComponentModel.Composition" /> - <Reference Include="System.Numerics" /> - <Reference Include="Microsoft.CodeAnalysis.Elfie"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Elfie.1.0.0-rc9\lib\net45\Microsoft.CodeAnalysis.Elfie.dll</HintPath> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="Mono.Cecil"> + <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Mdb"> + <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Mdb.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Pdb"> + <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Pdb.dll</HintPath> </Reference> - <Reference Include="System.Composition.Convention"> - <HintPath>..\..\..\packages\Microsoft.Composition.1.0.30\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath> + <Reference Include="Mono.Cecil.Rocks"> + <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Rocks.dll</HintPath> </Reference> + <Reference Include="monodoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> + <Reference Include="Mono.Posix" /> + <Reference Include="mscorlib" /> + <Reference Include="Newtonsoft.Json"> + <HintPath>..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="System" /> <Reference Include="System.AppContext"> <HintPath>..\..\..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath> </Reference> + <Reference Include="System.Collections.Immutable"> + <HintPath>..\..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> + </Reference> + <Reference Include="System.Configuration" /> <Reference Include="System.Console"> <HintPath>..\..\..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath> </Reference> + <Reference Include="System.Core" /> <Reference Include="System.Diagnostics.FileVersionInfo"> <HintPath>..\..\..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll</HintPath> </Reference> @@ -161,11 +156,22 @@ <Reference Include="System.IO.Compression"> <HintPath>..\..\..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath> </Reference> + <Reference Include="System.IO.FileSystem"> + <HintPath>..\..\..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath> + </Reference> <Reference Include="System.IO.FileSystem.Primitives"> <HintPath>..\..\..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath> </Reference> - <Reference Include="System.IO.FileSystem"> - <HintPath>..\..\..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath> + <Reference Include="System.Runtime.Remoting" /> + <!-- NOTE: NuGet installs the PCL version of System.Reflection.Metadata by default but it is windows-specific. Use netstandard version instead. --> + <Reference Include="System.Reflection.Metadata"> + <HintPath>..\..\..\packages\System.Reflection.Metadata.1.4.2\lib\netstandard1.1\System.Reflection.Metadata.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.InteropServices.RuntimeInformation"> + <HintPath>..\..\..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Algorithms"> + <HintPath>..\..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath> </Reference> <Reference Include="System.Security.Cryptography.Encoding"> <HintPath>..\..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath> @@ -173,12 +179,10 @@ <Reference Include="System.Security.Cryptography.Primitives"> <HintPath>..\..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath> </Reference> - <Reference Include="System.Security.Cryptography.Algorithms"> - <HintPath>..\..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath> - </Reference> <Reference Include="System.Security.Cryptography.X509Certificates"> <HintPath>..\..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> </Reference> + <Reference Include="System.ServiceModel" /> <Reference Include="System.Text.Encoding.CodePages"> <HintPath>..\..\..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll</HintPath> </Reference> @@ -186,8 +190,10 @@ <HintPath>..\..\..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath> </Reference> <Reference Include="System.ValueTuple"> - <HintPath>..\..\..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath> + <HintPath>..\..\..\packages\System.ValueTuple.4.3.1\lib\netstandard1.0\System.ValueTuple.dll</HintPath> </Reference> + <Reference Include="System.Xml" /> + <Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.ReaderWriter"> <HintPath>..\..\..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath> </Reference> @@ -200,67 +206,7 @@ <Reference Include="System.Xml.XPath.XDocument"> <HintPath>..\..\..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll</HintPath> </Reference> - <Reference Include="System.Runtime.InteropServices.RuntimeInformation"> - <HintPath>..\..\..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath> - </Reference> - <Reference Include="System.Collections.Immutable"> - <HintPath>..\..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> - </Reference> - <!-- NOTE: NuGet installs the PCL version of System.Reflection.Metadata by default but it is windows-specific. Use netstandard version instead. --> - <Reference Include="System.Reflection.Metadata"> - <HintPath>..\..\..\packages\System.Reflection.Metadata.1.4.2\lib\netstandard1.1\System.Reflection.Metadata.dll</HintPath> - </Reference> - <Reference Include="Newtonsoft.Json"> - <HintPath>..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> - </Reference> - <Reference Include="Mono.Cecil"> - <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.dll</HintPath> - </Reference> - <Reference Include="Mono.Cecil.Mdb"> - <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Mdb.dll</HintPath> - </Reference> - <Reference Include="Mono.Cecil.Pdb"> - <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Pdb.dll</HintPath> - </Reference> - <Reference Include="Mono.Cecil.Rocks"> - <HintPath>..\..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Rocks.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Common.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.CSharp"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.VisualBasic"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.Workspaces.Desktop"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.Workspaces"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.Workspaces.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.Features"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Features.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.Features.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.CSharp.Features"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Features.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Features.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.VisualBasic.Features"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Features.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.Features.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.EditorFeatures"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.EditorFeatures.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.EditorFeatures.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.EditorFeatures.Text"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.EditorFeatures.Text.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.EditorFeatures.Text.dll</HintPath> - </Reference> + <Reference Include="System.Web" /> </ItemGroup> <ItemGroup> <Compile Include="MonoDevelop.Core\StringParserService.cs" /> @@ -749,6 +695,8 @@ <Compile Include="MonoDevelop.Core\StringInternPool.cs" /> <Compile Include="MonoDevelop.Core\Hash.cs" /> <Compile Include="MonoDevelop.Core\StringTable.cs" /> + <Compile Include="MonoDevelop.Core.AddIns\FalseCondition.cs" /> + <Compile Include="MonoDevelop.Core.AddIns\TrueCondition.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringInternPool.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringInternPool.cs index d0f9b6f8a0..e7cd62fd7b 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringInternPool.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringInternPool.cs @@ -56,5 +56,20 @@ namespace MonoDevelop.Core {
return table.Add (chars);
}
+
+ public static string AddShared (StringBuilder chars)
+ {
+ return StringTable.AddShared (chars);
+ }
+
+ public static string AddShared (string chars)
+ {
+ return StringTable.AddShared (chars);
+ }
+
+ public static string AddShared (string chars, int start, int len)
+ {
+ return StringTable.AddShared (chars, start, len);
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringTable.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringTable.cs index 8ff7a5e8cd..c2a60d4010 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringTable.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringTable.cs @@ -536,6 +536,33 @@ namespace MonoDevelop.Core return AddSharedSlow(hashCode, chars);
}
+ internal static string AddShared (string chars)
+ {
+ var hashCode = Hash.GetFNVHashCode (chars);
+
+ string shared = FindSharedEntry (chars, hashCode);
+ if (shared != null) {
+ return shared;
+ }
+
+ AddSharedSlow (hashCode, chars);
+ return chars;
+ }
+
+ internal static string AddShared (string chars, int start, int len)
+ {
+ var hashCode = Hash.GetFNVHashCode (chars, start, len);
+
+ string shared = FindSharedEntry (chars, start, len, hashCode);
+ if (shared != null) {
+ return shared;
+ }
+
+ string text = chars.Substring (start, len);
+ AddSharedSlow (hashCode, text);
+ return text;
+ }
+
private static string AddSharedSlow(int hashCode, StringBuilder builder)
{
string text = builder.ToString();
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs index 31bd453d1a..8d47e18ad6 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs @@ -933,8 +933,7 @@ namespace MonoDevelop.Projects.MSBuild MSBuildItemEvaluated CreateEvaluatedItem (MSBuildEvaluationContext context, ProjectInfo pinfo, MSBuildProject project, MSBuildItem sourceItem, string include, string evaluatedFile = null, string recursiveDir = null) { - lock (EngineManager.Pool) - include = EngineManager.Pool.Add (include);
+ include = StringInternPool.AddShared (include);
var it = new MSBuildItemEvaluated (project, sourceItem.Name, sourceItem.Include, include); var md = new Dictionary<string,IMSBuildPropertyEvaluated> (); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEngineManager.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEngineManager.cs index 1a425b759b..1a48a53aca 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEngineManager.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEngineManager.cs @@ -34,8 +34,6 @@ namespace MonoDevelop.Projects.MSBuild object localLock = new object (); bool disposed; - internal Core.StringInternPool Pool { get; } = new Core.StringInternPool (); - public MSBuildEngine GetEngine (bool supportsMSBuild) { /* if (supportsMSBuild) { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs index 6560a0a12e..55ada7b308 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs @@ -458,9 +458,7 @@ namespace MonoDevelop.Projects.MSBuild while (i != -1); sb.Append (str, last, str.Length - last); - lock (project.Pool) { - return project.Pool.Add (sb); - } + return StringInternPool.AddShared (sb); } finally { evaluationSbs.Enqueue (sb); } @@ -500,15 +498,12 @@ namespace MonoDevelop.Projects.MSBuild i += 2; int j = FindClosingChar (str, i, ')'); if (j == -1) { - lock (project.Pool) - val = project.Pool.Add (str, start, str.Length - start); + val = StringInternPool.AddShared (str, start, str.Length - start); i = str.Length; return false; } - string prop; - lock (project.Pool) - prop = project.Pool.Add (str, i, j - i).Trim (); + string prop = StringInternPool.AddShared (str, i, j - i).Trim (); i = j + 1; bool res = false; @@ -532,9 +527,7 @@ namespace MonoDevelop.Projects.MSBuild } } if (!res) - lock (project.Pool) { - val = project.Pool.Add (str, start, j - start + 1); - } + val = StringInternPool.AddShared (str, start, j - start + 1); return res; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProject.cs index 08cf608024..8ea842408d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProject.cs @@ -1104,8 +1104,6 @@ namespace MonoDevelop.Projects.MSBuild internal Dictionary<string, string> GlobalProperties { get { return globalProperties; } } - - internal StringInternPool Pool => engineManager.Pool; } static class XmlUtil diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs index f7b32d777f..b7fe15428d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs @@ -93,6 +93,13 @@ namespace MonoDevelop.Projects.MSBuild projectInstance = engine.CreateProjectInstance (info.Project); try { + // Set properties defined by global property providers, and then + // properties explicitly set to this instance + + foreach (var gpp in MSBuildProjectService.GlobalPropertyProviders) { + foreach (var prop in gpp.GetGlobalProperties ()) + engine.SetGlobalProperty (projectInstance, prop.Key, prop.Value); + } foreach (var prop in globalProperties) engine.SetGlobalProperty (projectInstance, prop.Key, prop.Value); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs index d8d1e99616..3e5c6d0d25 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs @@ -94,6 +94,15 @@ namespace MonoDevelop.Projects.MSBuild } } + internal static IEnumerable<IMSBuildGlobalPropertyProvider> GlobalPropertyProviders { + get { + if (customGlobalPropertyProviders != null) + return globalPropertyProviders.Concat (customGlobalPropertyProviders); + else + return globalPropertyProviders; + } + } + static MSBuildProjectService () { Services.ProjectService.DataContextChanged += delegate { @@ -200,6 +209,21 @@ namespace MonoDevelop.Projects.MSBuild customProjectItemTypes.Remove (name); } + static List<IMSBuildGlobalPropertyProvider> customGlobalPropertyProviders; + + internal static void RegisterGlobalPropertyProvider (IMSBuildGlobalPropertyProvider provider) + { + if (customGlobalPropertyProviders == null) + customGlobalPropertyProviders = new List<IMSBuildGlobalPropertyProvider> (); + customGlobalPropertyProviders.Add (provider); + } + + internal static void UnregisterGlobalPropertyProvider (IMSBuildGlobalPropertyProvider provider) + { + if (customGlobalPropertyProviders != null) + customGlobalPropertyProviders.Remove (provider); + } + /// <summary> /// Registers a custom project import search path. This path will be used as a fallback when evaluating /// an import and targets file is not found using the value assigned by MSBuild to the property. diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildWhitespace.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildWhitespace.cs index 276e548582..114802419b 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildWhitespace.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildWhitespace.cs @@ -203,9 +203,6 @@ namespace MonoDevelop.Projects.MSBuild } } - // PERF: Keep a global pool for whitespace in MSBuild. - // There are not many variations on a properly formatted project so the pool is small. - readonly static StringInternPool whitespacePool = new StringInternPool (); public static object ConsumeUntilNewLine (ref object ws) { if (ws == null) @@ -219,11 +216,8 @@ namespace MonoDevelop.Projects.MSBuild if (n == s.Length - 1) break; // Default case, consume the whole string int len = n + 1; - string res; - lock (whitespacePool) { - res = whitespacePool.Add (s, 0, len); - ws = whitespacePool.Add (s, len, s.Length - len); - } + string res = StringInternPool.AddShared (s, 0, len); + ws = StringInternPool.AddShared (s, len, s.Length - len); return res; } } @@ -243,10 +237,7 @@ namespace MonoDevelop.Projects.MSBuild return res; } } - string result; - lock (whitespacePool) { - result = whitespacePool.Add (sb); - } + string result = StringInternPool.AddShared (sb); ws = null; return result; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs index 7461135756..447484027d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs @@ -274,7 +274,7 @@ namespace MonoDevelop.Projects.SharedAssetsProjects return ProjectFeatures.None; } - protected override bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) + protected override bool OnFastCheckNeedsBuild (ConfigurationSelector configuration, TargetEvaluationContext context) { return false; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/OperationContext.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/OperationContext.cs index 96594b3302..41f0d3f92d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/OperationContext.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/OperationContext.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; using System.Collections.Generic; +using MonoDevelop.Core.Execution; namespace MonoDevelop.Projects { @@ -56,7 +57,13 @@ namespace MonoDevelop.Projects customData = new Dictionary<object, object> (other.customData); else customData = null; + ExecutionTarget = other.ExecutionTarget; } + + /// <summary> + /// Execution target for which the operation is being executed + /// </summary> + public ExecutionTarget ExecutionTarget { get; set; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs index a1333466c8..866af7a0df 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs @@ -1067,7 +1067,12 @@ namespace MonoDevelop.Projects /// </param> public Task<TargetEvaluationResult> RunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration, TargetEvaluationContext context = null) { - return ProjectExtension.OnRunTarget (monitor, target, configuration, context ?? new TargetEvaluationContext ()); + // Initialize the evaluation context. This initialization is shared with FastCheckNeedsBuild. + // Extenders will override OnConfigureTargetEvaluationContext to add custom properties and do other + // initializations required by MSBuild. + context = ProjectExtension.OnConfigureTargetEvaluationContext (target, configuration, context ?? new TargetEvaluationContext ()); + + return ProjectExtension.OnRunTarget (monitor, target, configuration, context); } public bool SupportsTarget (string target) @@ -1086,6 +1091,24 @@ namespace MonoDevelop.Projects } /// <summary> + /// Initialize the evaluation context that is going to be used to execute an MSBuild target. + /// </summary> + /// <returns>The updated context.</returns> + /// <param name="target">Target.</param> + /// <param name="configuration">Configuration.</param> + /// <param name="context">Context.</param> + /// <remarks> + /// This method can be overriden to add custom properties and do other initializations on the evaluation + /// context. The method is always called before executing OnRunTarget and other methods that do + /// target evaluations. The method can modify the provided context instance and return it, or it can + /// create a new instance. + /// </remarks> + protected virtual TargetEvaluationContext OnConfigureTargetEvaluationContext (string target, ConfigurationSelector configuration, TargetEvaluationContext context) + { + return context; + } + + /// <summary> /// Runs a build or execution target. /// </summary> /// <returns> @@ -1687,7 +1710,7 @@ namespace MonoDevelop.Projects if (UsingMSBuildEngine (configuration)) { var result = await RunMSBuildTarget (monitor, "Build", configuration, context); if (!result.BuildResult.Failed) - SetFastBuildCheckClean (configuration); + SetFastBuildCheckClean (configuration, context); return result; } @@ -1720,16 +1743,31 @@ namespace MonoDevelop.Projects bool disableFastUpToDateCheck; - //the configuration of the last build that completed successfully - //null if any file in the project has since changed + // The configuration of the last build that completed successfully, + // null if any file in the project has since changed string fastUpToDateCheckGoodConfig; + + // The global properties used in the last build + IPropertySet fastUpToDateCheckGlobalProperties; + + // Timestamp of the last build DateTime fastUpToDateTimestamp; public bool FastCheckNeedsBuild (ConfigurationSelector configuration) { - return ProjectExtension.OnFastCheckNeedsBuild (configuration); + return FastCheckNeedsBuild (configuration, new TargetEvaluationContext ()); } - + + public bool FastCheckNeedsBuild (ConfigurationSelector configuration, TargetEvaluationContext context) + { + // Initialize the evaluation context. This initialization is shared with RunTarget. + // Extenders will override OnConfigureTargetEvaluationContext to add custom properties and do other + // initializations required by MSBuild. + context = ProjectExtension.OnConfigureTargetEvaluationContext ("Build", configuration, context ?? new TargetEvaluationContext ()); + return ProjectExtension.OnFastCheckNeedsBuild (configuration, context); + } + + [Obsolete ("Use OnFastCheckNeedsBuild (configuration, TargetEvaluationContext)")] protected virtual bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) { if (disableFastUpToDateCheck || fastUpToDateCheckGoodConfig == null) @@ -1738,15 +1776,52 @@ namespace MonoDevelop.Projects if (cfg == null || cfg.Id != fastUpToDateCheckGoodConfig) return true; + return false; + } + + /// <summary> + /// Checks if this project needs to be built. + /// </summary> + /// <returns><c>true</c>, if the project is dirty and needs to be rebuilt, <c>false</c> otherwise.</returns> + /// <param name="configuration">Build configuration.</param> + /// <param name="context">Evaluation context.</param> + /// <remarks> + /// This method can be overriden to provide custom logic for checking if a project needs to be built, either + /// due to changes in the content or in the configuration. + /// </remarks> + protected virtual bool OnFastCheckNeedsBuild (ConfigurationSelector configuration, TargetEvaluationContext context) + { + // Chain the new OnFastCheckNeedsBuild override to the old one, so that extensions + // using the old API keep working +#pragma warning disable 618 + if (ProjectExtension.OnFastCheckNeedsBuild (configuration)) + return true; +#pragma warning restore 618 + // Shouldn't need to build, but if a dependency was changed since this project build flag was reset, // the project needs to be rebuilt foreach (var dep in GetReferencedItems (configuration).OfType<Project> ()) { - if (dep.FastCheckNeedsBuild (configuration) || dep.fastUpToDateTimestamp >= fastUpToDateTimestamp) { + if (dep.FastCheckNeedsBuild (configuration, context) || dep.fastUpToDateTimestamp >= fastUpToDateTimestamp) { fastUpToDateCheckGoodConfig = null; return true; } } + + // Check if global properties have changed + + var cachedCount = fastUpToDateCheckGlobalProperties != null ? fastUpToDateCheckGlobalProperties.GetProperties ().Count () : 0; + + if (cachedCount != context.GlobalProperties.GetProperties ().Count ()) + return true; + + if (cachedCount == 0) + return false; + + foreach (var p in context.GlobalProperties.GetProperties ()) { + if (fastUpToDateCheckGlobalProperties.GetValue (p.Name) != p.Value) + return true; + } return false; } @@ -1755,10 +1830,11 @@ namespace MonoDevelop.Projects fastUpToDateCheckGoodConfig = null; } - void SetFastBuildCheckClean (ConfigurationSelector configuration) + void SetFastBuildCheckClean (ConfigurationSelector configuration, TargetEvaluationContext context) { var cfg = GetConfiguration (configuration); fastUpToDateCheckGoodConfig = cfg != null ? cfg.Id : null; + fastUpToDateCheckGlobalProperties = context.GlobalProperties; fastUpToDateTimestamp = DateTime.Now; } @@ -3862,6 +3938,11 @@ namespace MonoDevelop.Projects Project.OnWriteRunConfiguration (monitor, runConfig, properties); } + internal protected override TargetEvaluationContext OnConfigureTargetEvaluationContext (string target, ConfigurationSelector configuration, TargetEvaluationContext context) + { + return Project.OnConfigureTargetEvaluationContext (target, configuration, context); + } + internal protected override Task<TargetEvaluationResult> OnRunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration, TargetEvaluationContext context) { return Project.DoRunTarget (monitor, target, configuration, context); @@ -3978,10 +4059,17 @@ namespace MonoDevelop.Projects Project.OnPrepareForEvaluation (project); } +#pragma warning disable 672, 618 internal protected override bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) { return Project.OnFastCheckNeedsBuild (configuration); } +#pragma warning restore 672, 618 + + internal protected override bool OnFastCheckNeedsBuild (ConfigurationSelector configuration, TargetEvaluationContext context) + { + return Project.OnFastCheckNeedsBuild (configuration, context); + } internal protected override Task<ProjectFile []> OnGetSourceFiles (ProgressMonitor monitor, ConfigurationSelector configuration) { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs index 5d32a28e6a..3544528240 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs @@ -85,6 +85,19 @@ namespace MonoDevelop.Projects next.OnWriteRunConfiguration (monitor, config, properties); } + /// <summary> + /// Called to initialize a TargetEvaluationContext instance required by RunTarget() + /// and other methods that invoke MSBuild targets + /// </summary> + /// <returns>The initialized evaluation context (it can be just the provided context)</returns> + /// <param name="target">The MSBuild target that is going to be invoked</param> + /// <param name="configuration">Build configuration</param> + /// <param name="context">Execution context</param> + internal protected virtual TargetEvaluationContext OnConfigureTargetEvaluationContext (string target, ConfigurationSelector configuration, TargetEvaluationContext context) + { + return next.OnConfigureTargetEvaluationContext (target, configuration, context); + } + internal protected virtual Task<TargetEvaluationResult> OnRunTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration, TargetEvaluationContext context) { return next.OnRunTarget (monitor, target, configuration, context); @@ -218,11 +231,27 @@ namespace MonoDevelop.Projects } } + [Obsolete ("Use OnFastCheckNeedsBuild (ConfigurationSelector,TargetEvaluationContext)")] internal protected virtual bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) { return next.OnFastCheckNeedsBuild (configuration); } + /// <summary> + /// Checks if this project needs to be built. + /// </summary> + /// <returns><c>true</c>, if the project is dirty and needs to be rebuilt, <c>false</c> otherwise.</returns> + /// <param name="configuration">Build configuration.</param> + /// <param name="context">Evaluation context.</param> + /// <remarks> + /// This method can be overriden to provide custom logic for checking if a project needs to be built, either + /// due to changes in the content or in the configuration. + /// </remarks> + internal protected virtual bool OnFastCheckNeedsBuild (ConfigurationSelector configuration, TargetEvaluationContext context) + { + return next.OnFastCheckNeedsBuild (configuration, context); + } + #endregion #region Events diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs index afccbde274..1c77c88439 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObject.cs @@ -38,6 +38,7 @@ using System.Runtime.Remoting.Messaging; using MonoDevelop.Core.StringParsing; using System.Threading; using System.Collections.Immutable; +using MonoDevelop.Core.AddIns; namespace MonoDevelop.Projects @@ -67,9 +68,7 @@ namespace MonoDevelop.Projects if (!initializeCalled) { initializeCalled = true; - extensionContext = AddinManager.CreateExtensionContext (); - extensionContext.RegisterCondition ("ItemType", new ItemTypeCondition (GetType ())); - ExtensionContext.RegisterCondition ("AppliesTo", new AppliesToCondition (this)); + extensionContext = CreateExtensionContext (this); OnInitialize (); InitializeExtensionChain (); @@ -435,7 +434,23 @@ namespace MonoDevelop.Projects static void LoadExtensions () { - modelExtensions = AddinManager.GetExtensionNodes<ProjectModelExtensionNode> (ProjectService.ProjectModelExtensionsPath).Concat (customNodes).ToArray (); + // Create a context for loading the default extensions. The context is necessary because + // the conditions declared in the extension point must always be present. + var extensionContext = CreateExtensionContext (null); + modelExtensions = extensionContext.GetExtensionNodes<ProjectModelExtensionNode> (ProjectService.ProjectModelExtensionsPath).Concat (customNodes).ToArray (); + } + + static ExtensionContext CreateExtensionContext (WorkspaceObject targetObject) + { + var extensionContext = AddinManager.CreateExtensionContext (); + if (targetObject == null) { + extensionContext.RegisterCondition ("ItemType", FalseCondition.Instance); + extensionContext.RegisterCondition ("AppliesTo", FalseCondition.Instance); + } else { + extensionContext.RegisterCondition ("ItemType", new ItemTypeCondition (targetObject.GetType ())); + extensionContext.RegisterCondition ("AppliesTo", new AppliesToCondition (targetObject)); + } + return extensionContext; } /// <summary> diff --git a/main/src/core/MonoDevelop.Core/packages.config b/main/src/core/MonoDevelop.Core/packages.config index 9062608930..e5b2ea5b94 100644 --- a/main/src/core/MonoDevelop.Core/packages.config +++ b/main/src/core/MonoDevelop.Core/packages.config @@ -23,7 +23,7 @@ <package id="Microsoft.VisualStudio.Text.UI" version="15.0.26201" targetFramework="net45" /> <package id="Mono.Cecil" version="0.10.0-beta5" targetFramework="net45" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" /> - <package id="SharpZipLib" version="0.86.0" targetFramework="net45" /> + <package id="JetBrains.SharpZipLib.Stripped" version="0.87.20170615.10" targetFramework="net461" /> <package id="System.AppContext" version="4.3.0" targetFramework="net461" /> <package id="System.Collections" version="4.3.0" targetFramework="net461" /> <package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net461" /> @@ -67,7 +67,7 @@ <package id="System.Threading.Tasks" version="4.3.0" targetFramework="net461" /> <package id="System.Threading.Tasks.Parallel" version="4.3.0" targetFramework="net461" /> <package id="System.Threading.Thread" version="4.3.0" targetFramework="net461" /> - <package id="System.ValueTuple" version="4.3.0" targetFramework="net461" /> + <package id="System.ValueTuple" version="4.3.1" targetFramework="net461" /> <package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net461" /> <package id="System.Xml.XDocument" version="4.3.0" targetFramework="net461" /> <package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="net461" /> diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml index 54e1362133..6fe92d0bc0 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml @@ -828,6 +828,9 @@ <Command id = "MonoDevelop.Ide.Commands.HelpCommands.DumpA11yTreeDelayed" defaultHandler = "MonoDevelop.Ide.Commands.DumpA11yTreeDelayedHandler" _label = "Dump Accessibility Tree (10s)" /> + <Command id = "MonoDevelop.Ide.Commands.HelpCommands.MarkLog" + defaultHandler = "MonoDevelop.Ide.Commands.MarkLogHandler" + _label = "Mark Log" /> </Category> <!-- SearchCommands --> diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml index e122cf42f1..993e0046f2 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml @@ -288,6 +288,7 @@ <CommandItem id = "MonoDevelop.Ide.Commands.HelpCommands.DumpUITree" /> <CommandItem id = "MonoDevelop.Ide.Commands.HelpCommands.DumpA11yTree" /> <CommandItem id = "MonoDevelop.Ide.Commands.HelpCommands.DumpA11yTreeDelayed" /> + <CommandItem id = "MonoDevelop.Ide.Commands.HelpCommands.MarkLog" /> </ItemSet> <Condition id = "Platform" value = "!mac"> <SeparatorItem id = "SeparatorAbout" /> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs index 9f8bd48c01..35c99558f2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelper.cs @@ -126,8 +126,10 @@ namespace MonoDevelop.Components.AtkCocoaHelper AXCell, AXColumn, AXGroup, + AXGrowArea, AXImage, AXLink, + AXList, AXMenuButton, AXPopUpButton, AXRadioButton, @@ -533,6 +535,7 @@ namespace MonoDevelop.Components.AtkCocoaHelper string Identifier { get; set; } string Help { get; set; } bool Hidden { get; set; } + int Index { get; set; } // For Navigable Static Text Func<string> Contents { set; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperMac.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperMac.cs index dc0ddd15ec..6dedc4b8d9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperMac.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperMac.cs @@ -855,6 +855,26 @@ namespace MonoDevelop.Components.AtkCocoaHelper p.GetVisibleCharacterRange = value; } } + + public int Index { + get { + var p = realProxyElement; + if (p == null) { + throw new Exception ("Not proxy element"); + } + + return (int) p.AccessibilityIndex; + } + + set { + var p = realProxyElement; + if (p == null) { + throw new Exception ("Not a proxy element"); + } + + p.AccessibilityIndex = value; + } + } } class RealAccessibilityElementProxy : NSAccessibilityElement, INSAccessibility diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperNoOp.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperNoOp.cs index c73624c21d..6843a55a72 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperNoOp.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AtkCocoaHelper/AtkCocoaHelperNoOp.cs @@ -219,6 +219,14 @@ namespace MonoDevelop.Components.AtkCocoaHelper } } + public int Index { + get { + return 0; + } + set { + } + } + public Gtk.Widget GtkParent { get; set; } public Gdk.Rectangle FrameInGtkParent { get; set; } public Gdk.Rectangle FrameInParent { get; set; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingSet.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingSet.cs index e649670aa1..0e98831e68 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingSet.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingSet.cs @@ -100,7 +100,12 @@ namespace MonoDevelop.Components.Commands public bool Equals (KeyBindingSet other) { - if (parent != other && bindings.Count != other.bindings.Count) + // TODO: full IEquatable<KeyBindingSet> implementation + // the current solutions is just enough to detect whether a custom set equals a predefined one + // and is not a real equality check. See KeyBindingsPanel.SelectCurrentScheme(). + if (other == null) + return false; + if (parent != null && parent != other && !parent.Equals (other.parent)) return false; foreach (KeyValuePair<string, string> binding in bindings) { string accel; @@ -214,9 +219,21 @@ namespace MonoDevelop.Components.Commands case "binding": command = reader.GetAttribute (commandAttr); binding = reader.GetAttribute (shortcutAttr); + + if (string.IsNullOrEmpty (command)) + continue; + + if (!string.IsNullOrEmpty (binding)) + binding = KeyBindingManager.FixChordSeparators (binding); + + string pbind; + if (parent?.bindings != null && parent.bindings.TryGetValue (command, out pbind)) { + if (binding == pbind) + continue; + } else if (string.IsNullOrEmpty (binding)) + continue; - if (!string.IsNullOrEmpty (command)) - bindings.Add (command, KeyBindingManager.FixChordSeparators(binding)); + bindings.Add (command, binding); break; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs index 2e383f3b5e..5356ff36ae 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs @@ -165,6 +165,7 @@ namespace MonoDevelop.Components.Docking Styles.Changed += UpdateStyle; Accessible.Name = "DockbarItem"; + Accessible.Role = Atk.Role.PushButton; } void IAnimatable.BatchBegin () { } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs index 25e57dc339..4a4aa06711 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs @@ -27,6 +27,7 @@ using System; #if MAC using AppKit; +using CoreGraphics; using Foundation; using MonoDevelop.Ide; #endif @@ -64,7 +65,6 @@ namespace MonoDevelop.Components } - static CoreGraphics.CGPoint lastOpenPositon; public static void ShowContextMenu (Gtk.Widget parent, int x, int y, NSMenu menu, bool selectFirstItem = false) { if (parent == null) @@ -96,11 +96,9 @@ namespace MonoDevelop.Components if (selectFirstItem) { var pt = new CoreGraphics.CGPoint (x, y); - lastOpenPositon = pt; menu.PopUpMenu (menu.ItemAt (0), pt, nsview); } else { var pt = new CoreGraphics.CGPoint (x, nswindow.Frame.Height - y - titleBarOffset); - lastOpenPositon = pt; var tmp_event = NSEvent.MouseEvent (NSEventType.LeftMouseDown, pt, 0, 0, @@ -123,10 +121,11 @@ namespace MonoDevelop.Components ShowContextMenu (parent, x, y, menu); } - static NSMenuItem CreateMenuItem (ContextMenuItem item) + static void AddMenuItem (NSLocationAwareMenu menu, ContextMenuItem item) { if (item.IsSeparator) { - return NSMenuItem.SeparatorItem; + menu.AddItem (NSMenuItem.SeparatorItem); + return; } var menuItem = new NSMenuItem (item.Label.Replace ("_",""), (s, e) => item.Click ()); @@ -144,60 +143,20 @@ namespace MonoDevelop.Components } if (item.SubMenu != null && item.SubMenu.Items.Count > 0) { - menuItem.Submenu = FromMenu (item.SubMenu, null); + var subMenu = FromMenu (item.SubMenu, null); + subMenu.Parent = menu; + menuItem.Submenu = subMenu; } - return menuItem; + menu.AddItem (menuItem); } - class ContextMenuDelegate : NSObject + static NSLocationAwareMenu FromMenu (ContextMenu menu, Action closeHandler) { - ContextMenu menu; - ContextMenuItem oldItem; - public ContextMenuDelegate (ContextMenu menu) - { - this.menu = menu; - } - - public Action CloseHandler { get; set; } - - [Export ("menuDidClose:")] - void MenuDidClose (NSMenu menu) - { - if (menu.Supermenu != null) - return; - if (CloseHandler != null) { - CloseHandler (); - } - this.menu.FireClosedEvent (); - } - - [Export ("menu:willHighlightItem:")] - void MenuWillHighlightItem (NSMenu menu, NSMenuItem willHighlightItem) - { - if (oldItem != null) { - oldItem.FireDeselectedEvent (); - oldItem = null; - } - if (willHighlightItem == null) - return; - int index = (int)menu.IndexOf (willHighlightItem); - if (index < 0) - return; - oldItem = this.menu.Items [index]; - - oldItem.FireSelectedEvent (new Xwt.Rectangle (lastOpenPositon.X, lastOpenPositon.Y, menu.Size.Width, menu.Size.Height)); - } - } - - static NSMenu FromMenu (ContextMenu menu, Action closeHandler) - { - var result = new NSMenu () { AutoEnablesItems = false }; - result.WeakDelegate = new ContextMenuDelegate (menu) { CloseHandler = closeHandler }; + var result = new NSLocationAwareMenu (menu, closeHandler) { AutoEnablesItems = false }; foreach (var menuItem in menu.Items) { - var item = CreateMenuItem (menuItem); - result.AddItem (item); + AddMenuItem (result, menuItem); } return result; @@ -209,6 +168,77 @@ namespace MonoDevelop.Components { return (NSImage)macToolkit.GetNativeImage (image); } + + class NSLocationAwareMenu : NSMenu + { + public CGPoint Location { get; private set; } + public NSLocationAwareMenu Parent { get; set; } + + public NSLocationAwareMenu (ContextMenu menu, Action closeHandler) + { + WeakDelegate = new ContextMenuDelegate (menu) { CloseHandler = closeHandler }; + } + + public override bool PopUpMenu (NSMenuItem item, CGPoint location, NSView view) + { + Location = location; + var parentMenu = item?.ParentItem?.Menu as NSLocationAwareMenu; + if (parentMenu != null) { + Location = new CGPoint ( + Location.X + parentMenu.Location.X, + Location.Y + parentMenu.Location.Y); + } + return base.PopUpMenu (item, location, view); + } + + class ContextMenuDelegate : NSObject + { + ContextMenu menu; + ContextMenuItem oldItem; + public ContextMenuDelegate (ContextMenu menu) + { + this.menu = menu; + } + + public Action CloseHandler { get; set; } + + [Export ("menuDidClose:")] + void MenuDidClose (NSMenu menu) + { + if (menu.Supermenu != null) + return; + if (CloseHandler != null) { + CloseHandler (); + } + this.menu.FireClosedEvent (); + } + + [Export ("menu:willHighlightItem:")] + void MenuWillHighlightItem (NSMenu menu, NSMenuItem willHighlightItem) + { + if (oldItem != null) { + oldItem.FireDeselectedEvent (); + oldItem = null; + } + if (willHighlightItem == null) + return; + int index = (int)menu.IndexOf (willHighlightItem); + if (index < 0) + return; + oldItem = this.menu.Items [index]; + nfloat x = 0, y = 0; + var locationAwareMenu = menu as NSLocationAwareMenu; + if (locationAwareMenu != null) { + while (locationAwareMenu.Parent != null) + locationAwareMenu = locationAwareMenu.Parent; + x = locationAwareMenu.Location.X; + y = locationAwareMenu.Location.Y; + menu = locationAwareMenu; + } + oldItem.FireSelectedEvent (new Xwt.Rectangle (x, y, menu.Size.Width, menu.Size.Height)); + } + } + } } #endif }
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs index 376556e212..707aba213a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs @@ -42,6 +42,7 @@ namespace MonoDevelop.Components { severity = TaskSeverity.Information; imageView = new Xwt.ImageView (); + imageView.Accessible.Role = Xwt.Accessibility.Role.Filler; UpdateIcon (); Content = imageView; CanGetFocus = true; @@ -66,6 +67,8 @@ namespace MonoDevelop.Components set { message = value; UpdatePopover (); + + this.Accessible.Label = value; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs index 842770df79..e331af12ef 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs @@ -52,6 +52,7 @@ namespace MonoDevelop.Components Add (box); image = new ImageView (); + image.Accessible.Role = Atk.Role.Filler; image.NoShowAll = true; box.PackStart (image, false, false, 0); label = new Label (); @@ -170,6 +171,7 @@ namespace MonoDevelop.Components } else { if (arrow == null ) { arrow = new Arrow (Gtk.ArrowType.Down, ShadowType.Out); + arrow.Accessible.Role = Atk.Role.Filler; arrow.Show (); ((HBox)label.Parent).PackEnd (arrow, false, false, 0); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs index 29a8b3ca9c..91df3fbd5e 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs @@ -27,6 +27,7 @@ using System; using Gtk; +using MonoDevelop.Components.AtkCocoaHelper; namespace MonoDevelop.Components { class MiniButton: Gtk.EventBox @@ -41,6 +42,10 @@ namespace MonoDevelop.Components { Events |= Gdk.EventMask.EnterNotifyMask | Gdk.EventMask.LeaveNotifyMask; Clickable = true; + + Accessible.Role = Atk.Role.PushButton; + var actionHandler = new ActionDelegate (this); + actionHandler.PerformPress += PerformPress; } public MiniButton (Gtk.Widget label): this () @@ -102,7 +107,12 @@ namespace MonoDevelop.Components if (Clicked != null) Clicked (this, EventArgs.Empty); } - + + void PerformPress (object sender, EventArgs args) + { + OnClicked (); + } + protected override bool OnButtonPressEvent (Gdk.EventButton evnt) { if (!ClickOnRelease && Clickable && evnt.Button == 1 && !evnt.TriggersContextMenu ()) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs index 868f98a924..58e65dba0a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs @@ -78,6 +78,7 @@ namespace MonoDevelop.Components get { if (accessible == null) { accessible = AccessibilityElementProxy.ButtonElementProxy (); + accessible.SetRole (AtkCocoa.Roles.AXPopUpButton); accessible.Identifier = "Breadcrumb"; accessible.PerformPress += OnPerformShowMenu; @@ -183,6 +184,8 @@ namespace MonoDevelop.Components Accessible.Name = "PathBar"; Accessible.SetLabel (GettextCatalog.GetString ("Breadcrumb Bar")); Accessible.Description = GettextCatalog.GetString ("Jump to definitions in the current file"); + Accessible.SetRole (AtkCocoa.Roles.AXList); + Accessible.SetOrientation (Orientation.Horizontal); CanFocus = true; @@ -302,6 +305,7 @@ namespace MonoDevelop.Components Gdk.Rectangle rect = new Gdk.Rectangle (x, y, width, height); entry.Accessible.FrameInGtkParent = rect; + entry.Accessible.FrameInParent = rect; } protected override bool OnExposeEvent (EventExpose evnt) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs index 5db69245bb..ab2b4d2d2b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs @@ -128,6 +128,7 @@ namespace MonoDevelop.Components var proxies = new AtkCocoaHelper.AccessibilityElementProxy [tabs.Count]; foreach (var tab in tabs) { proxies [i] = tab.Accessible; + tab.Accessible.Index = i; i++; } @@ -204,7 +205,7 @@ namespace MonoDevelop.Components { requisition.Height = (int)Math.Ceiling (tabSizes.Max (p => p.Y)); } - + protected override bool OnExposeEvent (Gdk.EventExpose evnt) { using (var cr = Gdk.CairoHelper.Create (evnt.Window)) { @@ -212,16 +213,21 @@ namespace MonoDevelop.Components cr.SetSourceColor (Styles.SubTabBarBackgroundColor.ToCairoColor ()); cr.Fill (); + Tab active = null; for (int i = tabs.Count; i --> 0;) { - if (i == ActiveTab) + if (i == ActiveTab) { + active = tabs [i]; continue; + } var tab = tabs[i]; var bounds = GetBounds (tab); tab.HoverPosition = tab == hoverTab ? new Cairo.PointD (mx - bounds.X, my) : new Cairo.PointD (-1, -1); tab.Draw (cr, bounds); } - - tabs[ActiveTab].Draw (cr, GetBounds (tabs[ActiveTab])); + + if (active != null) { + active.Draw (cr, GetBounds (active)); + } } return base.OnExposeEvent (evnt); @@ -291,7 +297,9 @@ namespace MonoDevelop.Components protected override void OnActivate () { - ActiveTab = focusedTab; + if (focusedTab >= 0 && focusedTab < tabs.Count) { + ActiveTab = focusedTab; + } base.OnActivate (); } } @@ -360,7 +368,6 @@ namespace MonoDevelop.Components Gdk.Rectangle gdkRect = new Gdk.Rectangle ((int)allocation.X, (int)allocation.Y, (int)allocation.Width, (int)allocation.Height); Accessible.FrameInGtkParent = gdkRect; // If Y != 0, then we need to flip the y axis - Accessible.FrameInParent = gdkRect; } } @@ -399,8 +406,10 @@ namespace MonoDevelop.Components this.TabPosition = tabPosition; Accessible = AccessibilityElementProxy.ButtonElementProxy (); + Accessible.SetRole (AtkCocoa.Roles.AXRadioButton, "tab"); Accessible.Title = label; Accessible.GtkParent = parent; + Accessible.Identifier = "Tabstrip.Tab"; Accessible.PerformPress += OnTabPressed; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/HelpCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/HelpCommands.cs index 7f0d57ede9..bdd66ebf1c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/HelpCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/HelpCommands.cs @@ -32,6 +32,7 @@ using System.Timers; using MonoDevelop.Ide.Gui.Dialogs; using MonoDevelop.Ide.Gui; using MonoDevelop.Components.Commands; +using MonoDevelop.Core; namespace MonoDevelop.Ide.Commands { @@ -176,4 +177,12 @@ namespace MonoDevelop.Ide.Commands } #endif } + + class MarkLogHandler : CommandHandler + { + protected override void Run () + { + LoggingService.LogInfo ("\n\n--- --- --- --- MARK --- --- --- ---\n\n"); + } + } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs index 3fae99b2eb..7a1eca14b3 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs @@ -336,6 +336,10 @@ namespace MonoDevelop.Ide.Commands protected override void Run () { + // Already in 2-column mode? + if (DockNotebook.ActiveNotebook?.Container?.SplitCount > 0) + return; + IdeApp.Workbench.LockActiveWindowChangeEvent (); var container = DockNotebook.ActiveNotebook.Container; var tab = DockNotebook.ActiveNotebook.CurrentTab; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/Formats/OldFormat.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/Formats/OldFormat.cs index 151d7a4a2a..09675a6a12 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/Formats/OldFormat.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/Formats/OldFormat.cs @@ -196,6 +196,22 @@ namespace MonoDevelop.Ide.Editor.Highlighting settings.Add (new ThemeSetting ("Variable", new List<string> { "variable" }, ConvertChunkStyle (colorScheme.UserVariableUsage))); settings.Add (new ThemeSetting ("variable.other", new List<string> { "variable.other" }, ConvertChunkStyle (colorScheme.ScriptKeyword))); settings.Add (new ThemeSetting ("Keyword", new List<string> { "keyword - (source.c keyword.operator | source.c++ keyword.operator | source.objc keyword.operator | source.objc++ keyword.operator), keyword.operator.word" }, ConvertChunkStyle (colorScheme.KeywordOther))); + settings.Add (new ThemeSetting ("Keyword (Access)", new List<string> { "keyword.other.access" }, ConvertChunkStyle (colorScheme.KeywordAccessors))); + settings.Add (new ThemeSetting ("Keyword (Types)", new List<string> { "keyword.other.type" }, ConvertChunkStyle (colorScheme.KeywordTypes))); + settings.Add (new ThemeSetting ("Keyword (Operator)", new List<string> { "keyword.operator" }, ConvertChunkStyle (colorScheme.KeywordOperators))); + settings.Add (new ThemeSetting ("Keyword (Selection)", new List<string> { "keyword.other.selection" }, ConvertChunkStyle (colorScheme.KeywordSelection))); + settings.Add (new ThemeSetting ("Keyword (Itarator)", new List<string> { "keyword.other.iteration" }, ConvertChunkStyle (colorScheme.KeywordIteration))); + settings.Add (new ThemeSetting ("Keyword (Jump)", new List<string> { "keyword.other.jump" }, ConvertChunkStyle (colorScheme.KeywordJump))); + settings.Add (new ThemeSetting ("Keyword (Context)", new List<string> { "keyword.other.context" }, ConvertChunkStyle (colorScheme.KeywordContext))); + settings.Add (new ThemeSetting ("Keyword (Exception)", new List<string> { "keyword.other.exception" }, ConvertChunkStyle (colorScheme.KeywordException))); + settings.Add (new ThemeSetting ("Keyword (Modifier)", new List<string> { "keyword.other.modifiers" }, ConvertChunkStyle (colorScheme.KeywordModifiers))); + settings.Add (new ThemeSetting ("Keyword (Void)", new List<string> { "keyword.other.void" }, ConvertChunkStyle (colorScheme.KeywordVoid))); + settings.Add (new ThemeSetting ("Keyword (Namespace)", new List<string> { "keyword.other.namespace" }, ConvertChunkStyle (colorScheme.KeywordNamespace))); + settings.Add (new ThemeSetting ("Keyword (Property)", new List<string> { "keyword.other.property" }, ConvertChunkStyle (colorScheme.KeywordProperty))); + settings.Add (new ThemeSetting ("Keyword (Declaration)", new List<string> { "keyword.other.declaration" }, ConvertChunkStyle (colorScheme.KeywordDeclaration))); + settings.Add (new ThemeSetting ("Keyword (Parameter)", new List<string> { "keyword.other.parameter" }, ConvertChunkStyle (colorScheme.KeywordParameter))); + settings.Add (new ThemeSetting ("Keyword (Operator)", new List<string> { "keyword.other.access" }, ConvertChunkStyle (colorScheme.KeywordOperatorDeclaration))); + settings.Add (new ThemeSetting ("storage", new List<string> { "storage" }, ConvertChunkStyle (colorScheme.KeywordOther))); settings.Add (new ThemeSetting ("storage.type", new List<string> { "storage.type" }, ConvertChunkStyle (colorScheme.KeywordOther))); settings.Add (new ThemeSetting ("punctuation", new List<string> { "punctuation" }, ConvertChunkStyle (colorScheme.Punctuation))); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/syntaxes/CSharp/C#.sublime-syntax b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/syntaxes/CSharp/C#.sublime-syntax index dfafc3a212..7ec0cfc9b4 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/syntaxes/CSharp/C#.sublime-syntax +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/syntaxes/CSharp/C#.sublime-syntax @@ -94,8 +94,38 @@ contexts: pop: true keywords: - match: '@\w+\b' - - match: '\b(this|base|as|is|new|sizeof|typeof|stackalloc|else|if|switch|case|default|do|for|foreach|in|while|break|continue|goto|return|yield|partial|global|where|__arglist|__makeref|__reftype|__refvalue|by|descending|from|group|into|orderby|select|let|ascending|join|on|equals|try|throw|catch|finally|abstract|async|await|const|event|extern|override|readonly|sealed|static|virtual|volatile|public|protected|private|internal|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ushort|ulong|object|string|var|dynamic|void|namespace|using|get|set|add|remove|value|class|interface|delegate|enum|struct|params|ref|out|explicit|implicit|operator|checked|unchecked|fixed|unsafe|lock)\b' - scope: keyword.source.cs + - match: '\b(this|base)\b' + scope: keyword.other.access.source.cs + - match: '\b(as|is|new|sizeof|typeof|stackalloc)\b' + scope: keyword.operator.source.cs + - match: '\b(else|if|switch|case|default)\b' + scope: keyword.other.selection.source.cs + - match: '\b(do|for|foreach|in|while)\b' + scope: keyword.other.iteration.source.cs + - match: '\b(break|continue|goto|return)\b' + scope: keyword.other.jump.source.cs + - match: '\b(yield|partial|global|where|__arglist|__makeref|__reftype|__refvalue|by|descending|from|group|into|orderby|select|let|ascending|join|on|equals)\b' + scope: keyword.other.context.source.cs + - match: '\b(try|throw|catch|finally)\b' + scope: keyword.other.exception.source.cs + - match: '\b(abstract|async|await|const|event|extern|override|readonly|sealed|static|virtual|volatile|public|protected|private|internal)\b' + scope: keyword.other.modifiers.source.cs + - match: '\b(bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ushort|ulong|object|string|var|dynamic)\b' + scope: keyword.other.type.source.cs + - match: '\b(void)\b' + scope: keyword.other.void.source.cs + - match: '\b(namespace|using)\b' + scope: keyword.other.namespace.source.cs + - match: '\b(get|set|add|remove|value)\b' + scope: keyword.other.property.source.cs + - match: '\b(class|interface|delegate|enum|struct)\b' + scope: keyword.other.declaration.source.cs + - match: '\b(params|ref|out)\b' + scope: keyword.other.parameter.source.cs + - match: '\b(explicit|implicit|operator)\b' + scope: keyword.operator.declaration.source.cs + - match: '\b(checked|unchecked|fixed|unsafe|lock)\b' + scope: keyword.other.source.cs - match: '\b(true|false|null)\b' scope: constant.language.source.cs numbers: diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/GruvboxStyle.json b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/GruvboxStyle.json index d78fa1c2e6..cf06ce46e1 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/GruvboxStyle.json +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/GruvboxStyle.json @@ -71,10 +71,10 @@ { "name": "Debugger Current Line Marker", "color": "#69684c", "bordercolor": "#69684c" }, { "name": "Debugger Stack Line Marker", "color": "#5c6b4d", "bordercolor": "#5c6b4d" }, - { "name": "Primary Link", "color": "foreground", "secondcolor": "#7f4a81" }, - { "name": "Primary Link(Highlighted)", "color": "foreground", "secondcolor": "#b167b3" }, - { "name": "Secondary Link", "color": "foreground", "secondcolor": "#262228" }, - { "name": "Secondary Link(Highlighted)", "color": "foreground", "secondcolor": "#4e4552" }, + { "name": "Primary Link", "color": "#7f4a81", "secondcolor": "#7f4a81" }, + { "name": "Primary Link(Highlighted)", "color": "#b167b3", "secondcolor": "#b167b3" }, + { "name": "Secondary Link", "color": "#262228", "secondcolor": "#262228" }, + { "name": "Secondary Link(Highlighted)", "color": "#4e4552", "secondcolor": "#4e4552" }, { "name": "Message Bubble Error Marker", "color": "#b28d37" }, { "name": "Message Bubble Error Tag", "color": "#e3a6a1", "secondcolor": "black" }, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/MonokaiStyle.json b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/MonokaiStyle.json index f750cb5951..f37696bc33 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/MonokaiStyle.json +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/MonokaiStyle.json @@ -79,10 +79,10 @@ { "name": "Debugger Current Line Marker", "color": "#69684c", "bordercolor": "#69684c" }, { "name": "Debugger Stack Line Marker", "color": "#618336", "bordercolor": "#618336" }, - { "name": "Primary Link", "color": "monokai-white", "secondcolor": "#7f4a81" }, - { "name": "Primary Link(Highlighted)", "color": "monokai-white", "secondcolor": "#b167b3" }, - { "name": "Secondary Link", "color": "monokai-white", "secondcolor": "#262228" }, - { "name": "Secondary Link(Highlighted)", "color": "monokai-white", "secondcolor": "#4e4552" }, + { "name": "Primary Link", "color": "#4f4a81", "secondcolor": "#4f4a81" }, + { "name": "Primary Link(Highlighted)", "color": "#4147b3", "secondcolor": "#4147b3" }, + { "name": "Secondary Link", "color": "#262228", "secondcolor": "#262228" }, + { "name": "Secondary Link(Highlighted)", "color": "#4e4552", "secondcolor": "#4e4552" }, { "name": "Message Bubble Error Marker", "color": "#b28d37" }, { "name": "Message Bubble Error Tag", "color": "#e3a6a1", "secondcolor": "black" }, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/NightshadeStyle.json b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/NightshadeStyle.json index 383b3f67b6..21fdf806e2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/NightshadeStyle.json +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/NightshadeStyle.json @@ -91,10 +91,10 @@ { "name": "Debugger Current Line Marker", "color": "#69684c", "bordercolor": "#69684c" }, { "name": "Debugger Stack Line Marker", "color": "#4a6429", "bordercolor": "#4a6429" }, - { "name": "Primary Link", "color": "chocolate1", "secondcolor": "chocolate3" }, - { "name": "Primary Link(Highlighted)", "color": "chocolate1", "secondcolor": "chocolate2" }, - { "name": "Secondary Link", "color": "white", "secondcolor": "aluminium6" }, - { "name": "Secondary Link(Highlighted)", "color": "aluminium1", "secondcolor": "aluminium5" }, + { "name": "Primary Link", "color": "chocolate3", "secondcolor": "chocolate3" }, + { "name": "Primary Link(Highlighted)", "color": "chocolate2", "secondcolor": "chocolate2" }, + { "name": "Secondary Link", "color": "aluminium6", "secondcolor": "aluminium6" }, + { "name": "Secondary Link(Highlighted)", "color": "aluminium5", "secondcolor": "aluminium5" }, { "name": "Message Bubble Error Marker", "color": "#b28d37" }, { "name": "Message Bubble Error Tag", "color": "#e3a6a1", "secondcolor": "black" }, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/OblivionStyle.json b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/OblivionStyle.json index 68223e0c50..3af8b35d14 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/OblivionStyle.json +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/OblivionStyle.json @@ -83,10 +83,10 @@ { "name": "Debugger Current Line Marker", "color": "#69684c", "bordercolor": "#69684c" }, { "name": "Debugger Stack Line Marker", "color": "#5f7247", "bordercolor": "#5f7247" }, - { "name": "Primary Link", "color": "chocolate1", "secondcolor": "chocolate3" }, - { "name": "Primary Link(Highlighted)", "color": "chocolate1", "secondcolor": "chocolate2" }, - { "name": "Secondary Link", "color": "white", "secondcolor": "aluminium6" }, - { "name": "Secondary Link(Highlighted)", "color": "aluminium1", "secondcolor": "aluminium5" }, + { "name": "Primary Link", "color": "chocolate3", "secondcolor": "chocolate3" }, + { "name": "Primary Link(Highlighted)", "color": "chocolate2", "secondcolor": "chocolate2" }, + { "name": "Secondary Link", "color": "aluminium6", "secondcolor": "aluminium6" }, + { "name": "Secondary Link(Highlighted)", "color": "aluminium5", "secondcolor": "aluminium5" }, { "name": "Message Bubble Error Marker", "color": "#b28d37" }, { "name": "Message Bubble Error Tag", "color": "#e3a6a1", "secondcolor": "black" }, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedDarkStyle.json b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedDarkStyle.json index ca411840d2..cc513b6a86 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedDarkStyle.json +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedDarkStyle.json @@ -77,6 +77,11 @@ { "name": "Debugger Current Line Marker", "color": "#69684c", "bordercolor": "#69684c" }, { "name": "Debugger Stack Line Marker", "color": "#54653f", "bordercolor": "#54653f" }, + { "name": "Primary Link", "color": "base2", "secondcolor": "base2" }, + { "name": "Primary Link(Highlighted)", "color": "base2", "secondcolor": "base2" }, + { "name": "Secondary Link", "color": "base02", "secondcolor": "base02" }, + { "name": "Secondary Link(Highlighted)", "color": "base02", "secondcolor": "base02" }, + { "name": "Message Bubble Error Marker", "color": "#b28d37" }, { "name": "Message Bubble Error Tag", "color": "#e3a6a1", "secondcolor": "black" }, { "name": "Message Bubble Error Counter", "color": "black", "secondcolor": "#e3a6a1" }, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedLightStyle.json b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedLightStyle.json index 293e2d814e..926f48db6c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedLightStyle.json +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/themes/SolarizedLightStyle.json @@ -68,6 +68,11 @@ { "name": "Debugger Stack Line Marker", "color": "#c9e1a9", "bordercolor": "#c9e1a9" }, + { "name": "Primary Link", "color": "base02", "secondcolor": "base02" }, + { "name": "Primary Link(Highlighted)", "color": "base02", "secondcolor": "base02" }, + { "name": "Secondary Link", "color": "base2", "secondcolor": "base2" }, + { "name": "Secondary Link(Highlighted)", "color": "base2", "secondcolor": "base2" }, + { "name": "Message Bubble Error Marker", "color": "#b28d37" }, { "name": "Message Bubble Error Tag", "color": "#e3a6a1", "secondcolor": "black" }, { "name": "Message Bubble Error Counter", "color": "black", "secondcolor": "#e3a6a1" }, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs index 3083309e5f..bc6396245c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs @@ -24,7 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; +using System; using System.Linq; using System.Threading; using System.Text; @@ -35,6 +35,7 @@ using Gtk; using System.Collections.Generic; using MonoDevelop.Ide.Gui.Content; using System.Threading.Tasks; +using MonoDevelop.Components.AtkCocoaHelper; namespace MonoDevelop.Ide.FindInFiles { @@ -235,8 +236,40 @@ namespace MonoDevelop.Ide.FindInFiles UpdateSensitivity (); return true; }); + SetupAccessibility (); } - + + void SetupAccessibility () + { + comboboxentryFind.SetCommonAccessibilityAttributes ("FindInFilesDialog.comboboxentryFind", + "Find", + GettextCatalog.GetString ("Enter string to find")); + comboboxentryFind.SetAccessibilityLabelRelationship (labelFind); + searchentryFileMask.SetCommonAccessibilityAttributes ("FindInFilesDialog.searchentryFileMask", + "File Mask", + GettextCatalog.GetString ("Enter the file mask")); + searchentryFileMask.SetAccessibilityLabelRelationship (labelFileMask); + } + + void SetupAccessibilityForReplace () + { + comboboxentryReplace.SetCommonAccessibilityAttributes ("FindInFilesDialog.comboboxentryReplace", + "Replace", + GettextCatalog.GetString ("Enter string to replace")); + comboboxentryReplace.SetAccessibilityLabelRelationship (labelReplace); + } + + + void SetupAccessibilityForPath () + { + comboboxentryPath.SetCommonAccessibilityAttributes ("FindInFilesDialog.comboboxentryPath", + "Path", + GettextCatalog.GetString ("Enter the Path")); + comboboxentryPath.SetAccessibilityLabelRelationship (labelPath); + } + + + static void TableAddRow (Table table, uint row, Widget column1, Widget column2) { uint rows = table.NRows; @@ -326,7 +359,8 @@ namespace MonoDevelop.Ide.FindInFiles LoadHistory ("MonoDevelop.FindReplaceDialogs.ReplaceHistory", comboboxentryReplace); comboboxentryReplace.Show (); labelReplace.Show (); - + SetupAccessibilityForReplace (); + TableAddRow (tableFindAndReplace, 1, labelReplace, comboboxentryReplace); buttonReplace = new Button () { @@ -396,6 +430,8 @@ namespace MonoDevelop.Ide.FindInFiles hboxPath.PackStart (comboboxentryPath); labelPath.MnemonicWidget = comboboxentryPath; + + SetupAccessibilityForPath (); buttonBrowsePaths = new Button { Label = "..." }; buttonBrowsePaths.Clicked += ButtonBrowsePathsClicked; @@ -679,10 +715,10 @@ namespace MonoDevelop.Ide.FindInFiles } protected override void OnDestroyed () - {
+ { if (resultPad != null) { var resultWidget = resultPad.Control.GetNativeWidget<SearchResultWidget> (); - if (resultWidget.ResultCount > 0) {
+ if (resultWidget.ResultCount > 0) { resultPad.Window.Activate (true); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs index 937fe4b9cc..49fbb50511 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/ItemOptionsDialog.cs @@ -31,6 +31,7 @@ using MonoDevelop.Components; using MonoDevelop.Projects.Extensions; using MonoDevelop.Ide.Gui.Dialogs; using MonoDevelop.Projects; +using MonoDevelop.Core.AddIns; namespace MonoDevelop.Ide.Gui.Dialogs { @@ -56,17 +57,9 @@ namespace MonoDevelop.Ide.Gui.Dialogs extensionContext.RegisterCondition ("ProjectTypeId", new ProjectTypeIdCondition ((Project)DataObject)); extensionContext.RegisterCondition ("SupportsTarget", new SupportsTargetCondition ((Project)DataObject)); } else { - extensionContext.RegisterCondition ("AppliesTo", new FalseCondition ()); - extensionContext.RegisterCondition ("FlavorType", new FalseCondition ()); - extensionContext.RegisterCondition ("ProjectTypeId", new FalseCondition ()); - } - } - - class FalseCondition: ConditionType - { - public override bool Evaluate (NodeElement conditionNode) - { - return false; + extensionContext.RegisterCondition ("AppliesTo", FalseCondition.Instance); + extensionContext.RegisterCondition ("FlavorType", FalseCondition.Instance); + extensionContext.RegisterCondition ("ProjectTypeId", FalseCondition.Instance); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/DotNetCompileTargetSelector.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/DotNetCompileTargetSelector.cs new file mode 100644 index 0000000000..2d4c1ed5f8 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/DotNetCompileTargetSelector.cs @@ -0,0 +1,53 @@ +// +// DotNetCompileTargetSelector.cs +// +// Author: +// Jason Imison <jaimison@microsoft.com> +// +// Copyright (c) 2017 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Gtk; +using MonoDevelop.Core; +using MonoDevelop.Projects; + +namespace MonoDevelop.Ide.Gui.OptionPanels +{ + public class DotNetCompileTargetSelector : ComboBox + { + public DotNetCompileTargetSelector () + { + var store = new ListStore (typeof (string)); + store.AppendValues (GettextCatalog.GetString ("Executable")); + store.AppendValues (GettextCatalog.GetString ("Library")); + store.AppendValues (GettextCatalog.GetString ("Executable with GUI")); + store.AppendValues (GettextCatalog.GetString ("Module")); + this.Model = store; + var cr = new CellRendererText (); + this.PackStart (cr, true); + this.AddAttribute (cr, "text", 0); + } + + public CompileTarget CompileTarget { + get { return (CompileTarget)this.Active; } + set { this.Active = (int)value; } + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs index f7538ac892..0e5eead727 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs @@ -631,17 +631,10 @@ namespace MonoDevelop.Ide.Gui.Pads var descriptionCol = view.AppendColumn (GettextCatalog.GetString ("Description"), descriptionCellRenderer); descriptionCol.SetCellDataFunc (descriptionCellRenderer, new Gtk.TreeCellDataFunc (DescriptionDataFunc)); descriptionCol.Resizable = true; - descriptionCellRenderer.WrapMode = Pango.WrapMode.Word; descriptionCellRenderer.PreferedMaxWidth = IdeApp.Workbench.RootWindow.Allocation.Width / 3; + descriptionCellRenderer.WrapWidth = descriptionCellRenderer.PreferedMaxWidth; + descriptionCellRenderer.WrapMode = Pango.WrapMode.Word; - descriptionCol.AddNotification("width", delegate - { - if (descriptionCellRenderer.WrapWidth == descriptionCol.Width) - return; - descriptionCellRenderer.WrapWidth = descriptionCol.Width; - descriptionCol.QueueResize (); - }); - col = view.AppendColumn (GettextCatalog.GetString ("File"), view.TextRenderer); col.SetCellDataFunc (view.TextRenderer, new Gtk.TreeCellDataFunc (FileDataFunc)); col.Resizable = true; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/MonoDevelopStatusBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/MonoDevelopStatusBar.cs index 669aa6dcdb..4f211b52ec 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/MonoDevelopStatusBar.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/MonoDevelopStatusBar.cs @@ -35,6 +35,7 @@ using System.Collections.Generic; using MonoDevelop.Components.Docking; using MonoDevelop.Ide.Gui.Dialogs; using MonoDevelop.Components; +using MonoDevelop.Components.AtkCocoaHelper; using MonoDevelop.Components.MainToolbar; namespace MonoDevelop.Ide @@ -52,13 +53,19 @@ namespace MonoDevelop.Ide Spacing = 0; HasResizeGrip = true; + Accessible.Role = Atk.Role.Filler; + HeaderBox hb = new HeaderBox (1, 0, 0, 0); + hb.Accessible.Role = Atk.Role.Filler; hb.StyleSet += (o, args) => { hb.BorderColor = Styles.DockSeparatorColor.ToGdkColor (); hb.BackgroundColor = Styles.DockBarBackground.ToGdkColor (); }; var mainBox = new HBox (); - mainBox.PackStart (new Label (""), true, true, 0); + mainBox.Accessible.Role = Atk.Role.Filler; + var alignment = new Alignment (0f, 0f, 0f, 0f); + alignment.Accessible.Role = Atk.Role.Filler; + mainBox.PackStart (alignment, true, true, 0); hb.Add (mainBox); hb.ShowAll (); PackStart (hb, true, true, 0); @@ -67,15 +74,26 @@ namespace MonoDevelop.Ide if (FeedbackService.Enabled) { CustomFrame fr = new CustomFrame (0, 0, 1, 0); + fr.Accessible.Role = Atk.Role.Filler; var px = Xwt.Drawing.Image.FromResource ("feedback-16.png"); HBox b = new HBox (false, 3); - b.PackStart (new Xwt.ImageView (px).ToGtkWidget ()); - b.PackStart (new Gtk.Label ("Feedback")); + b.Accessible.Role = Atk.Role.Filler; + + var im = new Xwt.ImageView (px).ToGtkWidget (); + im.Accessible.Role = Atk.Role.Filler; + b.PackStart (im); + var label = new Gtk.Label (GettextCatalog.GetString ("Feedback")); + label.Accessible.Role = Atk.Role.Filler; + b.PackStart (label); Gtk.Alignment al = new Gtk.Alignment (0f, 0f, 1f, 1f); + al.Accessible.Role = Atk.Role.Filler; al.RightPadding = 5; al.LeftPadding = 3; al.Add (b); feedbackButton = new MiniButton (al); + feedbackButton.Accessible.SetLabel (GettextCatalog.GetString ("Feedback")); + feedbackButton.Accessible.Description = GettextCatalog.GetString ("Click to send feedback to the development team"); + //feedbackButton.BackroundColor = new Gdk.Color (200, 200, 255); fr.Add (feedbackButton); mainBox.PackStart (fr, false, false, 0); @@ -99,6 +117,7 @@ namespace MonoDevelop.Ide // Dock area CustomFrame dfr = new CustomFrame (0, 0, 1, 0); + dfr.Accessible.Role = Atk.Role.Filler; dfr.StyleSet += (o, args) => { dfr.BorderColor = Styles.DockSeparatorColor.ToGdkColor (); }; @@ -113,6 +132,7 @@ namespace MonoDevelop.Ide // Resize grip + resizeGrip.Accessible.SetRole (AtkCocoa.Roles.AXGrowArea); resizeGrip.WidthRequest = ResizeGripWidth; resizeGrip.HeightRequest = 0; resizeGrip.VisibleWindow = false; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs index 08f596c6aa..b887e4d0da 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs @@ -354,11 +354,42 @@ namespace MonoDevelop.Ide.Gui static IEnumerable<Gtk.Widget> GetFocussableWidgets (Gtk.Widget widget) { var c = widget as Container; - if (widget.CanFocus) + + if (widget.CanFocus) { yield return widget; + } + if (c != null) { - foreach (var f in c.FocusChain.SelectMany (GetFocussableWidgets).Where (y => y != null)) + foreach (var f in c.FocusChain.SelectMany (GetFocussableWidgets).Where (y => y != null)) { yield return f; + } + } + + if (c?.Children?.Length != 0) { + foreach (var f in c.Children) { + var container = f as Container; + if (container != null) { + foreach (var child in GetFocussableChildren (container)) { + yield return child; + } + } + } + } + } + + static IEnumerable<Gtk.Widget> GetFocussableChildren (Gtk.Container container) + { + if (container.CanFocus) { + yield return container; + } + + foreach (var f in container.Children) { + var c = f as Container; + if (c != null) { + foreach (var child in GetFocussableChildren (c)) { + yield return child; + } + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs index 509e56c695..a1c6bb1584 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs @@ -369,6 +369,12 @@ namespace MonoDevelop.Ide.Gui if (result == AlertButton.Cancel) return false; + if (result == AlertButton.CloseWithoutSave) { + doc.Window.ViewContent.DiscardChanges (); + await doc.Window.CloseWindow (true); + continue; + } + await doc.Save (); if (doc.IsDirty) { doc.Select (); @@ -385,8 +391,8 @@ namespace MonoDevelop.Ide.Gui (object)(doc.Window.ViewContent.IsUntitled ? doc.Window.ViewContent.UntitledName : System.IO.Path.GetFileName (doc.Window.ViewContent.ContentName))), - "", - AlertButton.Cancel, doc.Window.ViewContent.IsUntitled ? AlertButton.SaveAs : AlertButton.Save); + GettextCatalog.GetString ("If you don't save, all changes will be permanently lost."), + AlertButton.CloseWithoutSave, AlertButton.Cancel, doc.Window.ViewContent.IsUntitled ? AlertButton.SaveAs : AlertButton.Save); } public void CloseAllDocuments (bool leaveActiveDocumentOpen) @@ -579,7 +585,6 @@ namespace MonoDevelop.Ide.Gui if (info.Options.HasFlag (OpenDocumentOptions.BringToFront)) { doc.Select (); - doc.Window.SelectWindow (); NavigationHistoryService.LogActiveDocument (); } return doc; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanelWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanelWidget.cs index 0094dea3de..7f0ed03eca 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanelWidget.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/BaseDirectoryPanelWidget.cs @@ -1,4 +1,4 @@ -// BaseDirectoryPanel.cs +// BaseDirectoryPanel.cs // // Author: // Lluis Sanchez Gual <lluis@novell.com> @@ -44,9 +44,15 @@ namespace MonoDevelop.Ide.Projects.OptionPanels var a = folderentry.EntryAccessible; a.SetTitleUIElement (label3.Accessible); label3.Accessible.SetTitleFor (a); + SetupAccessibility (); + } + + private void SetupAccessibility () + { folderentry.SetEntryAccessibilityAttributes ("BaseDirectory.FolderEntry", - GettextCatalog.GetString ("Root Directory"), - GettextCatalog.GetString ("Entry the root directory for the project")); + GettextCatalog.GetString ("Root Directory"), + GettextCatalog.GetString ("Entry the root directory for the project")); + folderentry.SetAccessibilityLabelRelationship (label3); } public string BaseDirectory { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineBuildOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineBuildOptions.cs index 9cf84eca7b..0f2da9d00d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineBuildOptions.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineBuildOptions.cs @@ -27,6 +27,8 @@ using System; using MonoDevelop.Components; using MonoDevelop.Ide.Gui.Dialogs; using MonoDevelop.Projects; +using MonoDevelop.Components.AtkCocoaHelper; +using MonoDevelop.Core; namespace MonoDevelop.Ide.Projects.OptionPanels { @@ -54,6 +56,16 @@ namespace MonoDevelop.Ide.Projects.OptionPanels Build (); this.solution = solution; folderEntry.Path = solution.OutputDirectory; + SetupAccessibility (); + } + + private void SetupAccessibility () + { + + folderEntry.SetCommonAccessibilityAttributes ("CombineBuildOptions.folderEntry", + "", + GettextCatalog.GetString ("Enter the output directory")); + folderEntry.SetAccessibilityLabelRelationship (this.label73); } public void Store() diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineInformationPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineInformationPanel.cs index 766f937ea7..10e3e684b9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineInformationPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CombineInformationPanel.cs @@ -34,6 +34,8 @@ using MonoDevelop.Core; using MonoDevelop.Ide.Gui.Dialogs; using Gtk; using MonoDevelop.Components; +using MonoDevelop.Components.AtkCocoaHelper; + namespace MonoDevelop.Ide.Projects.OptionPanels { @@ -63,7 +65,16 @@ namespace MonoDevelop.Ide.Projects.OptionPanels versEntry.Text = solution.Version; descView.Buffer.Text = solution.Description; - } + SetupAccessibility (); + } + + void SetupAccessibility () + { + versEntry.SetCommonAccessibilityAttributes ("CombineInformationPanel.versEntry", + "", + GettextCatalog.GetString ("Enter the version")); + versEntry.SetAccessibilityLabelRelationship (versLabel); + } public void Store (Solution solution) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/GeneralProjectOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/GeneralProjectOptions.cs index 1cd80fb20f..98fa93ede2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/GeneralProjectOptions.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/GeneralProjectOptions.cs @@ -42,13 +42,12 @@ namespace MonoDevelop.Ide.Projects.OptionPanels { return widget = new GeneralProjectOptionsWidget (ConfiguredProject, ParentDialog); } - + public override void ApplyChanges() { widget.Store (); } } - partial class GeneralProjectOptionsWidget : Gtk.Bin { Project project; @@ -57,12 +56,9 @@ namespace MonoDevelop.Ide.Projects.OptionPanels public GeneralProjectOptionsWidget (Project project, OptionsDialog dialog) { Build (); - this.project = project; this.dialog = dialog; - nameLabel.UseUnderline = true; - descriptionLabel.UseUnderline = true; projectNameEntry.Text = project.Name; @@ -76,7 +72,6 @@ namespace MonoDevelop.Ide.Projects.OptionPanels defaultNamespaceLabel.Visible = false; projectDefaultNamespaceEntry.Visible = false; } - entryVersion.Text = project.Version; checkSolutionVersion.Active = project.SyncVersionWithSolution; entryVersion.Sensitive = !project.SyncVersionWithSolution; @@ -86,6 +81,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels void SetAccessibilityAttributes () { + label55.Accessible.Role = Atk.Role.Filler; informationHeaderLabel.Accessible.SetTitleFor (table11.Accessible); table11.Accessible.SetTitleUIElement (informationHeaderLabel.Accessible); @@ -117,7 +113,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels GettextCatalog.GetString ("Enter the default namespace for the project")); defaultNamespaceLabel.Accessible.SetTitleFor (projectDescriptionTextView.Accessible); } - + public void Store () { if (projectNameEntry.Text != project.Name) { @@ -125,7 +121,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels if (project.ParentSolution != null) dialog.ModifiedObjects.Add (project.ParentSolution); } - + project.Description = projectDescriptionTextView.Buffer.Text; if (project is DotNetProject) { ((DotNetProject)project).DefaultNamespace = projectDefaultNamespaceEntry.Text; @@ -151,4 +147,3 @@ namespace MonoDevelop.Ide.Projects.OptionPanels } } - diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/OutputOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/OutputOptionsPanel.cs index afb3211a3f..8e9ea17f25 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/OutputOptionsPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/OutputOptionsPanel.cs @@ -94,6 +94,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels void SetupAccessibility () { + label91.Accessible.Role = Atk.Role.Filler; assemblyNameEntry.SetCommonAccessibilityAttributes ("OutputOptionsPanel.AssemblyEntry", GettextCatalog.GetString ("Assembly Name"), GettextCatalog.GetString ("Enter the name of the output assembly")); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/LanguageCellRenderer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/LanguageCellRenderer.cs index cf30a4f59d..e2454a959f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/LanguageCellRenderer.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/LanguageCellRenderer.cs @@ -93,7 +93,7 @@ namespace MonoDevelop.Ide.Projects return; } - if (!Template.AvailableLanguages.Any () || !IsTemplateRowSelected (widget, flags)) { + if (!RenderRecentTemplate && (!Template.AvailableLanguages.Any () || !IsTemplateRowSelected (widget, flags))) { return; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs index d906a3910a..b1309458b6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs @@ -57,7 +57,7 @@ namespace MonoDevelop.Ide.Projects const string UseGitPropertyName = "Dialogs.NewProjectDialog.UseGit";
const string CreateGitIgnoreFilePropertyName = "Dialogs.NewProjectDialog.CreateGitIgnoreFile";
- const string CreateProjectSubDirectoryPropertyName = "MonoDevelop.Core.Gui.Dialogs.NewProjectDialog.AutoCreateProjectSubdir";
+ internal const string CreateProjectSubDirectoryPropertyName = "MonoDevelop.Core.Gui.Dialogs.NewProjectDialog.AutoCreateProjectSubdir";
const string NewSolutionLastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.LastSelectedCategoryPath";
const string NewSolutionLastSelectedTemplatePropertyName = "Dialogs.NewProjectDialog.LastSelectedTemplate";
const string NewProjectLastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.AddNewProjectLastSelectedCategoryPath";
@@ -193,7 +193,8 @@ namespace MonoDevelop.Ide.Projects SetDefaultLocation ();
SetDefaultGitSettings ();
SelectedLanguage = PropertyService.Get (SelectedLanguagePropertyName, "C#");
- projectConfiguration.CreateProjectDirectoryInsideSolutionDirectory = PropertyService.Get (CreateProjectSubDirectoryPropertyName, true);
+ if (IsNewSolution)
+ projectConfiguration.CreateProjectDirectoryInsideSolutionDirectory = PropertyService.Get (CreateProjectSubDirectoryPropertyName, true);
}
void UpdateDefaultSettings ()
@@ -268,7 +269,7 @@ namespace MonoDevelop.Ide.Projects PropertyService.Set (CreateGitIgnoreFilePropertyName, projectConfiguration.CreateGitIgnoreFile);
}
- INewProjectDialogBackend CreateNewProjectDialog ()
+ protected virtual INewProjectDialogBackend CreateNewProjectDialog ()
{
return new GtkNewProjectDialogBackend ();
}
@@ -315,11 +316,25 @@ namespace MonoDevelop.Ide.Projects void LoadTemplateCategories ()
{
Predicate<SolutionTemplate> templateMatch = GetTemplateFilter ();
- templateCategories = IdeApp.Services.TemplatingService.GetProjectTemplateCategories (templateMatch).ToList ();
+ templateCategories = TemplatingService.GetProjectTemplateCategories (templateMatch).ToList ();
if (IsNewSolution)
- recentTemplates = IdeApp.Services.TemplatingService.RecentTemplates.GetTemplates (templateCategories).Where (t => t.IsMatch (SolutionTemplateVisibility.NewSolution)).ToList ();
+ recentTemplates = TemplatingService.RecentTemplates.GetTemplates (templateCategories).Where (t => t.IsMatch (SolutionTemplateVisibility.NewSolution)).ToList ();
else
- recentTemplates = IdeApp.Services.TemplatingService.RecentTemplates.GetTemplates (templateCategories).ToList ();
+ recentTemplates = TemplatingService.RecentTemplates.GetTemplates (templateCategories).ToList ();
+ }
+
+ // Allow testing of the controller by allowing tests to specify the
+ // TemplatingService. IdeApp.Services is not initialized during unit tests.
+ TemplatingService templatingService;
+
+ internal TemplatingService TemplatingService {
+ get {
+ if (templatingService != null)
+ return templatingService;
+
+ return IdeApp.Services.TemplatingService;
+ }
+ set { templatingService = value; }
}
Predicate<SolutionTemplate> GetTemplateFilter ()
@@ -480,7 +495,7 @@ namespace MonoDevelop.Ide.Projects // Fallback to checking all templates that match the template id in the same category
// and support the condition.
- SolutionTemplate matchedTemplate = IdeApp.Services.TemplatingService.GetTemplate (
+ SolutionTemplate matchedTemplate = TemplatingService.GetTemplate (
templateCategories,
currentTemplate => IsTemplateMatch (currentTemplate, SelectedTemplate, language, finalConfigurationPage.Parameters),
category => true,
@@ -746,7 +761,7 @@ namespace MonoDevelop.Ide.Projects DisposeExistingNewItems ();
try {
- result = await IdeApp.Services.TemplatingService.ProcessTemplate (template, projectConfiguration, ParentFolder);
+ result = await TemplatingService.ProcessTemplate (template, projectConfiguration, ParentFolder);
if (!result.WorkspaceItems.Any ())
return false;
} catch (UserException ex) {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs index 1e511e3a34..b183a357c2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/FileTemplate.cs @@ -38,6 +38,7 @@ using System.Xml; using Gtk; using Mono.Addins; using MonoDevelop.Core; +using MonoDevelop.Core.AddIns; using MonoDevelop.Ide.Codons; using MonoDevelop.Ide.Gui; using MonoDevelop.Projects; @@ -220,9 +221,9 @@ namespace MonoDevelop.Ide.Templates extensionContext.RegisterCondition ("FlavorType", new FlavorTypeCondition (project)); extensionContext.RegisterCondition ("ProjectTypeId", new ProjectTypeIdCondition (project)); } else { - extensionContext.RegisterCondition ("AppliesTo", new TrueCondition ()); - extensionContext.RegisterCondition ("FlavorType", new TrueCondition ()); - extensionContext.RegisterCondition ("ProjectTypeId", new TrueCondition ()); + extensionContext.RegisterCondition ("AppliesTo", TrueCondition.Instance); + extensionContext.RegisterCondition ("FlavorType", TrueCondition.Instance); + extensionContext.RegisterCondition ("ProjectTypeId", TrueCondition.Instance); } var list = new List<FileTemplate> (); @@ -236,14 +237,6 @@ namespace MonoDevelop.Ide.Templates return list; } - class TrueCondition : ConditionType - { - public override bool Evaluate (NodeElement conditionNode) - { - return true; - } - } - internal static FileTemplate GetFileTemplateByID (string templateID) { var node = AddinManager.GetExtensionNodes<ProjectTemplateCodon> (EXTENSION_PATH) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/MicrosoftTemplateEngineProjectTemplatingProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/MicrosoftTemplateEngineProjectTemplatingProvider.cs index 1b1854e247..5cf26b9d36 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/MicrosoftTemplateEngineProjectTemplatingProvider.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/MicrosoftTemplateEngineProjectTemplatingProvider.cs @@ -44,6 +44,7 @@ using Microsoft.TemplateEngine.Abstractions; using MonoDevelop.Ide.CodeFormatting; using MonoDevelop.Core.StringParsing; using MonoDevelop.Core.Text; +using MonoDevelop.Projects.Policies; namespace MonoDevelop.Ide.Templates { @@ -147,6 +148,9 @@ namespace MonoDevelop.Ide.Templates var parameters = GetParameters (solutionTemplate, config); var templateInfo = solutionTemplate.templateInfo; var workspaceItems = new List<IWorkspaceFileObject> (); + + var filesBeforeCreation = Directory.GetFiles (config.ProjectLocation, "*", SearchOption.AllDirectories); + var result = await templateCreator.InstantiateAsync ( templateInfo, config.ProjectName, @@ -174,10 +178,10 @@ namespace MonoDevelop.Ide.Templates } //TODO: Once templates support "D396686C-DE0E-4DE6-906D-291CD29FC5DE" use that to load projects - foreach (var path in Directory.GetFiles (config.ProjectLocation, "*.*proj", SearchOption.AllDirectories)) { - if (path.EndsWith (".csproj", StringComparison.OrdinalIgnoreCase) || path.EndsWith (".fsproj", StringComparison.OrdinalIgnoreCase) || path.EndsWith (".vbproj", StringComparison.OrdinalIgnoreCase)) { - workspaceItems.Add (await MonoDevelop.Projects.Services.ProjectService.ReadSolutionItem (new Core.ProgressMonitor (), path)); - } + foreach (var path in result.ResultInfo.PrimaryOutputs) { + var fullPath = Path.Combine (config.ProjectLocation, path.Path); + if (Services.ProjectService.IsSolutionItemFile (fullPath)) + workspaceItems.Add (await MonoDevelop.Projects.Services.ProjectService.ReadSolutionItem (new Core.ProgressMonitor (), fullPath)); } var metadata = new Dictionary<string, string> (); @@ -215,7 +219,8 @@ namespace MonoDevelop.Ide.Templates // Format all source files generated during the project creation foreach (var p in workspaceItems.OfType<Project> ()) { foreach (var file in p.Files) - await FormatFile (p, file.FilePath); + if (!filesBeforeCreation.Contains ((string)file.FilePath, FilePath.PathComparer)) //Format only newly created files + await FormatFile (parentFolder?.Policies ?? p.Policies, file.FilePath); } processResult.SetFilesToOpen (filesToOpen); return processResult; @@ -249,7 +254,7 @@ namespace MonoDevelop.Ide.Templates .Where (parameter => parameter.IsValid); } - async Task FormatFile (Project p, FilePath file) + async Task FormatFile (PolicyContainer policies, FilePath file) { string mime = DesktopService.GetMimeTypeForUri (file); if (mime == null) @@ -259,7 +264,7 @@ namespace MonoDevelop.Ide.Templates if (formatter != null) { try { var content = await TextFileUtility.ReadAllTextAsync (file); - var formatted = formatter.FormatText (p.Policies, content.Text); + var formatted = formatter.FormatText (policies, content.Text); if (formatted != null) TextFileUtility.WriteText (file, formatted, content.Encoding); } catch (Exception ex) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs index 0b917b754f..22a3df9eaa 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs @@ -82,7 +82,7 @@ namespace MonoDevelop.Ide.Templates cinfo.ProjectName = config.ProjectName;
cinfo.SolutionName = config.SolutionName;
cinfo.ParentFolder = parentFolder;
- cinfo.ActiveConfiguration = IdeApp.Workspace.ActiveConfiguration;
+ cinfo.ActiveConfiguration = IdeApp.Workspace?.ActiveConfiguration ?? ConfigurationSelector.Default;
cinfo.Parameters = config.Parameters;
return cinfo;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TemplateImageProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TemplateImageProvider.cs index fb699a2907..9558d8849b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TemplateImageProvider.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/TemplateImageProvider.cs @@ -52,7 +52,11 @@ namespace MonoDevelop.Ide.Templates Image LoadImageFromResource (string imageId)
{
- return IdeApp.Services.TemplatingService.LoadTemplateImage (imageId);
+ if (IdeApp.IsInitialized)
+ return IdeApp.Services.TemplatingService.LoadTemplateImage (imageId);
+
+ // Should only happen when running unit tests.
+ return null;
}
public void Dispose ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj index f439777a80..9a8a810544 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj @@ -1,10 +1,8 @@ -<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <Import Project="..\..\..\MonoDevelop.props" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProductVersion>8.0.30703</ProductVersion> - <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{27096E7F-C91C-4AC6-B289-6897A701DF21}</ProjectGuid> <OutputType>Library</OutputType> <AssemblyName>MonoDevelop.Ide</AssemblyName> @@ -102,21 +100,10 @@ <NoWarn>1591;1573</NoWarn> </PropertyGroup> <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.Drawing" /> - <Reference Include="System.Xml" /> - <Reference Include="System.Data" /> - <Reference Include="System.Web.Services" /> - <Reference Include="Mono.Posix" /> - <Reference Include="System.Runtime.Remoting" /> - <Reference Include="monodoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> - <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> - <SpecificVersion>False</SpecificVersion> - </Reference> <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> <SpecificVersion>False</SpecificVersion> </Reference> - <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> <SpecificVersion>False</SpecificVersion> </Reference> <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> @@ -125,29 +112,68 @@ <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> <SpecificVersion>False</SpecificVersion> </Reference> - <Reference Include="System.Core" /> - <Reference Include="Mono.Cairo" /> - <Reference Include="System.Web" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Design" /> - <Reference Include="System.Windows.Forms" /> - <Reference Include="System.Runtime.Serialization" /> - <Reference Include="System.Threading.Tasks.Dataflow, Version=4.6.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> - <HintPath>..\..\..\packages\System.Threading.Tasks.Dataflow.4.7.0\lib\netstandard1.0\System.Threading.Tasks.Dataflow.dll</HintPath> - <Private>True</Private> + <Reference Include="ICSharpCode.SharpZipLib"> + <HintPath>..\..\..\packages\JetBrains.SharpZipLib.Stripped.0.87.20170615.10\lib\net40\ICSharpCode.SharpZipLib.dll</HintPath> </Reference> - <Reference Include="Xamarin.Mac" Condition=" '$(Configuration)' == 'DebugMac' Or '$(Configuration)' == 'ReleaseMac' "> - <HintPath>..\..\..\external\Xamarin.Mac.dll</HintPath> + <Reference Include="Microsoft.CodeAnalysis"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Common.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp.Features"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Features.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Features.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Workspaces.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.EditorFeatures"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.EditorFeatures.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.EditorFeatures.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.EditorFeatures.Text"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.EditorFeatures.Text.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.EditorFeatures.Text.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Elfie"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Elfie.1.0.0-rc9\lib\net45\Microsoft.CodeAnalysis.Elfie.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Features"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Features.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.Features.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.VisualBasic"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.VisualBasic.Features"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Features.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.Features.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.2.3.0-beta1\lib\netstandard1.3\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Workspaces"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.Workspaces.dll</HintPath> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Workspaces.Desktop"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TemplateEngine.Abstractions"> + <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Abstractions.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Abstractions.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TemplateEngine.Core"> + <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Core.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Core.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TemplateEngine.Core.Contracts"> + <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Core.Contracts.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Core.Contracts.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TemplateEngine.Edge"> + <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Edge.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Edge.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TemplateEngine.Orchestrator.RunnableProjects"> + <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Orchestrator.RunnableProjects.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Orchestrator.RunnableProjects.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TemplateEngine.Utils"> + <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Utils.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Utils.dll</HintPath> </Reference> - <Reference Include="System.Windows" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> - <Reference Include="PresentationCore" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> - <Reference Include="PresentationFramework" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> - <Reference Include="WindowsBase" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> - <Reference Include="WindowsFormsIntegration" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> - <Reference Include="System.Xaml" /> <Reference Include="Microsoft.VisualStudio.Composition, Version=15.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <HintPath>..\..\..\packages\Microsoft.VisualStudio.Composition.15.3.38\lib\net45\Microsoft.VisualStudio.Composition.dll</HintPath> - <Private>True</Private> </Reference> <Reference Include="Microsoft.VisualStudio.CoreUtility"> <HintPath>..\..\..\packages\Microsoft.VisualStudio.CoreUtility.15.0.26201\lib\net45\Microsoft.VisualStudio.CoreUtility.dll</HintPath> @@ -165,71 +191,67 @@ <HintPath>..\..\..\packages\Microsoft.VisualStudio.Validation.15.3.15\lib\net45\Microsoft.VisualStudio.Validation.dll</HintPath> <Private>True</Private> </Reference> - <Reference Include="System.ComponentModel.Composition" /> - <Reference Include="ICSharpCode.SharpZipLib"> - <HintPath>..\..\..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath> - <Private>False</Private> - </Reference> - <Reference Include="System.Collections.Immutable"> - <HintPath>..\..\..\build\bin\System.Collections.Immutable.dll</HintPath> - </Reference> - <Reference Include="System.Reflection.Metadata"> - <HintPath>..\..\..\build\bin\System.Reflection.Metadata.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis"> - <HintPath>..\..\..\build\bin\Microsoft.CodeAnalysis.dll</HintPath> - <Private>False</Private> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.Workspaces"> - <HintPath>..\..\..\build\bin\Microsoft.CodeAnalysis.Workspaces.dll</HintPath> - <Private>False</Private> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.Workspaces.Desktop"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.Workspaces.Desktop.dll</HintPath> + <Reference Include="Mono.Cairo" /> + <Reference Include="Mono.Posix" /> + <Reference Include="monodoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> + <Reference Include="mscorlib" /> + <Reference Include="Newtonsoft.Json"> + <HintPath>..\..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> <Private>False</Private> </Reference> - <Reference Include="Microsoft.CodeAnalysis.EditorFeatures.Text"> - <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.EditorFeatures.Text.2.3.0-beta1\lib\net46\Microsoft.CodeAnalysis.EditorFeatures.Text.dll</HintPath> - <Private>False</Private> + <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> </Reference> - <Reference Include="ICSharpCode.SharpZipLib"> - <HintPath>..\..\..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath> + <Reference Include="PresentationCore" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="PresentationFramework" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="System" /> + <Reference Include="System.Collections.Immutable"> + <HintPath>..\..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> </Reference> + <Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.Composition.AttributedModel"> <HintPath>..\..\..\packages\System.Composition.AttributedModel.1.0.31\lib\netstandard1.0\System.Composition.AttributedModel.dll</HintPath> </Reference> + <Reference Include="System.Composition.Convention"> + <HintPath>..\..\..\packages\Microsoft.Composition.1.0.30\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath> + </Reference> + <Reference Include="System.Composition.Hosting"> + <HintPath>..\..\..\packages\System.Composition.Hosting.1.0.31\lib\netstandard1.0\System.Composition.Hosting.dll</HintPath> + </Reference> <Reference Include="System.Composition.Runtime"> <HintPath>..\..\..\packages\System.Composition.Runtime.1.0.31\lib\netstandard1.0\System.Composition.Runtime.dll</HintPath> </Reference> - <Reference Include="YamlDotNet"> - <HintPath>..\..\..\packages\YamlDotNet.Signed.4.0.1-pre291\lib\net35\YamlDotNet.dll</HintPath> - </Reference> - <Reference Include="Microsoft.CodeAnalysis.Features"> - <HintPath>..\..\..\build\bin\Microsoft.CodeAnalysis.Features.dll</HintPath> - <Private>False</Private> + <Reference Include="System.Composition.TypedParts"> + <HintPath>..\..\..\packages\System.Composition.TypedParts.1.0.31\lib\netstandard1.0\System.Composition.TypedParts.dll</HintPath> </Reference> + <Reference Include="System.Core" /> + <Reference Include="System.Data" /> + <Reference Include="System.Design" /> + <Reference Include="System.Drawing" /> <Reference Include="System.IO.Compression" /> - <Reference Include="Microsoft.TemplateEngine.Abstractions"> - <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Abstractions.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Abstractions.dll</HintPath> - </Reference> - <Reference Include="Microsoft.TemplateEngine.Core.Contracts"> - <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Core.Contracts.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Core.Contracts.dll</HintPath> - </Reference> - <Reference Include="Microsoft.TemplateEngine.Utils"> - <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Utils.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Utils.dll</HintPath> - </Reference> - <Reference Include="Microsoft.TemplateEngine.Core"> - <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Core.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Core.dll</HintPath> + <Reference Include="System.Reflection.Metadata"> + <HintPath>..\..\..\packages\System.Reflection.Metadata.1.4.2\lib\netstandard1.1\System.Reflection.Metadata.dll</HintPath> </Reference> - <Reference Include="Microsoft.TemplateEngine.Orchestrator.RunnableProjects"> - <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Orchestrator.RunnableProjects.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Orchestrator.RunnableProjects.dll</HintPath> + <Reference Include="System.Runtime.Remoting" /> + <Reference Include="System.Runtime.Serialization" /> + <Reference Include="System.Threading.Tasks.Dataflow, Version=4.6.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <HintPath>..\..\..\packages\System.Threading.Tasks.Dataflow.4.7.0\lib\netstandard1.0\System.Threading.Tasks.Dataflow.dll</HintPath> + <Private>True</Private> </Reference> - <Reference Include="Microsoft.TemplateEngine.Edge"> - <HintPath>..\..\..\packages\Microsoft.TemplateEngine.Edge.1.0.0-beta2-20170523-241\lib\net45\Microsoft.TemplateEngine.Edge.dll</HintPath> + <Reference Include="System.Web" /> + <Reference Include="System.Web.Services" /> + <Reference Include="System.Windows" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xaml" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="WindowsBase" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="WindowsFormsIntegration" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="Xamarin.Mac" Condition=" '$(Configuration)' == 'DebugMac' Or '$(Configuration)' == 'ReleaseMac' "> + <HintPath>..\..\..\external\Xamarin.Mac.dll</HintPath> </Reference> - <Reference Include="Newtonsoft.Json"> - <HintPath>..\..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> - <Private>False</Private> + <Reference Include="YamlDotNet"> + <HintPath>..\..\..\packages\YamlDotNet.Signed.4.0.1-pre291\lib\net35\YamlDotNet.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> @@ -9437,6 +9459,7 @@ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\RoslynClassificationHighlighting.cs" /> <Compile Include="MonoDevelop.Ide.Projects\LanguageCellRenderer.cs" /> <Compile Include="MonoDevelop.Components\RestartPanel.cs" /> + <Compile Include="MonoDevelop.Ide.Gui.OptionPanels\DotNetCompileTargetSelector.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> @@ -9533,6 +9556,6 @@ </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Target Name="AfterBuild"> - <Copy SourceFiles="@(Data)" DestinationFolder="..\..\..\build\data\%(Data.RelativeDir)" /> + <Copy SourceFiles="@(Data)" DestinationFolder="..\..\..\build\data\%(Data.RelativeDir)" SkipUnchangedFiles="true" /> </Target> </Project> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs index b898615c52..004851fad1 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs @@ -139,8 +139,6 @@ namespace MonoDevelop.Ide public readonly ConfigurationProperty<bool> AddImportedItemsToCompletionList = ConfigurationProperty.Create ("AddImportedItemsToCompletionList", false); public readonly ConfigurationProperty<bool> IncludeKeywordsInCompletionList = ConfigurationProperty.Create ("IncludeKeywordsInCompletionList", true); public readonly ConfigurationProperty<bool> IncludeCodeSnippetsInCompletionList = ConfigurationProperty.Create ("IncludeCodeSnippetsInCompletionList", true); - public readonly ConfigurationProperty<bool> AddParenthesesAfterCompletion = ConfigurationProperty.Create ("AddParenthesesAfterCompletion", true); - public readonly ConfigurationProperty<bool> AddOpeningOnly = ConfigurationProperty.Create ("AddOpeningOnly", false); public readonly ConfigurationProperty<bool> FilterCompletionListByEditorBrowsable = ConfigurationProperty.Create ("FilterCompletionListByEditorBrowsable", true); public readonly ConfigurationProperty<bool> IncludeEditorBrowsableAdvancedMembers = ConfigurationProperty.Create ("IncludeEditorBrowsableAdvancedMembers", true); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs index 19e3b067ca..a88c448dfc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs @@ -1182,7 +1182,7 @@ namespace MonoDevelop.Ide BuildResult res = null; try { tt.Trace ("Cleaning item"); - res = await entry.Clean (monitor, IdeApp.Workspace.ActiveConfiguration, operationContext); + res = await entry.Clean (monitor, IdeApp.Workspace.ActiveConfiguration, InitOperationContext (entry, operationContext)); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Clean failed."), ex); } finally { @@ -1435,13 +1435,13 @@ namespace MonoDevelop.Ide var sei = target as Project; if (sei != null) { - if (sei.FastCheckNeedsBuild (configuration)) + if (sei.FastCheckNeedsBuild (configuration, InitOperationContext (target, new TargetEvaluationContext ()))) return true; //TODO: respect solution level dependencies var deps = new HashSet<SolutionItem> (); CollectReferencedItems (sei, deps, configuration); foreach (var dep in deps.OfType<Project> ()) { - if (dep.FastCheckNeedsBuild (configuration)) + if (dep.FastCheckNeedsBuild (configuration, InitOperationContext (target, new TargetEvaluationContext ()))) return true; } return false; @@ -1450,7 +1450,7 @@ namespace MonoDevelop.Ide var sln = target as Solution; if (sln != null) { foreach (var item in sln.GetAllProjects ()) { - if (item.FastCheckNeedsBuild (configuration)) + if (item.FastCheckNeedsBuild (configuration, InitOperationContext (target, new TargetEvaluationContext ()))) return true; } return false; @@ -1517,7 +1517,7 @@ namespace MonoDevelop.Ide if (skipPrebuildCheck || result.ErrorCount == 0) { tt.Trace ("Building item"); - result = await entry.Build (monitor, IdeApp.Workspace.ActiveConfiguration, true, operationContext); + result = await entry.Build (monitor, IdeApp.Workspace.ActiveConfiguration, true, InitOperationContext (entry, operationContext)); } } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Build failed."), ex); @@ -1534,6 +1534,25 @@ namespace MonoDevelop.Ide return result; } + + /// <summary> + /// Initializes the context to be used for build operations. It currently just initializes + /// it with the currently selected execution target. + /// </summary> + T InitOperationContext<T> (IBuildTarget target, T context) where T:OperationContext + { + OperationContext ctx = context; + if (ctx == null) + ctx = new OperationContext (); + if (ctx.ExecutionTarget == null) { + var item = target as SolutionItem; + if (item != null) + ctx.ExecutionTarget = IdeApp.Workspace.GetActiveExecutionTarget (item); + else + ctx.ExecutionTarget = IdeApp.Workspace.ActiveExecutionTarget; + } + return (T)ctx; + } // Note: This must run in the main thread async Task PromptForSave (BuildResult result) diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.CombineBuildOptionsWidget.cs b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.CombineBuildOptionsWidget.cs index 642f591582..f0c3177361 100644 --- a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.CombineBuildOptionsWidget.cs +++ b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.CombineBuildOptionsWidget.cs @@ -5,62 +5,67 @@ namespace MonoDevelop.Ide.Projects.OptionPanels internal partial class CombineBuildOptionsWidget { private global::Gtk.VBox vbox68; + private global::Gtk.Label label73; + private global::Gtk.HBox hbox46; + private global::Gtk.Label label74; + private global::MonoDevelop.Components.FolderEntry folderEntry; - protected virtual void Build () + protected virtual void Build() { - global::Stetic.Gui.Initialize (this); + global::Stetic.Gui.Initialize(this); // Widget MonoDevelop.Ide.Projects.OptionPanels.CombineBuildOptionsWidget - global::Stetic.BinContainer.Attach (this); + global::Stetic.BinContainer.Attach(this); this.Name = "MonoDevelop.Ide.Projects.OptionPanels.CombineBuildOptionsWidget"; // Container child MonoDevelop.Ide.Projects.OptionPanels.CombineBuildOptionsWidget.Gtk.Container+ContainerChild - this.vbox68 = new global::Gtk.VBox (); + this.vbox68 = new global::Gtk.VBox(); this.vbox68.Name = "vbox68"; this.vbox68.BorderWidth = ((uint)(12)); // Container child vbox68.Gtk.Box+BoxChild - this.label73 = new global::Gtk.Label (); + this.label73 = new global::Gtk.Label(); this.label73.Name = "label73"; this.label73.Xalign = 0F; - this.label73.LabelProp = global::Mono.Unix.Catalog.GetString ("<b>Output Directory</b>"); + this.label73.LabelProp = global::Mono.Unix.Catalog.GetString("<b>Output Directory</b>"); this.label73.UseMarkup = true; - this.vbox68.Add (this.label73); - global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox68 [this.label73])); + this.vbox68.Add(this.label73); + global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox68[this.label73])); w1.Position = 0; w1.Expand = false; w1.Fill = false; // Container child vbox68.Gtk.Box+BoxChild - this.hbox46 = new global::Gtk.HBox (); + this.hbox46 = new global::Gtk.HBox(); this.hbox46.Name = "hbox46"; this.hbox46.Spacing = 6; // Container child hbox46.Gtk.Box+BoxChild - this.label74 = new global::Gtk.Label (); + this.label74 = new global::Gtk.Label(); this.label74.Name = "label74"; - this.label74.LabelProp = global::Mono.Unix.Catalog.GetString (" "); - this.hbox46.Add (this.label74); - global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox46 [this.label74])); + this.label74.LabelProp = global::Mono.Unix.Catalog.GetString(" "); + this.hbox46.Add(this.label74); + global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox46[this.label74])); w2.Position = 0; w2.Expand = false; w2.Fill = false; // Container child hbox46.Gtk.Box+BoxChild - this.folderEntry = new global::MonoDevelop.Components.FolderEntry (); + this.folderEntry = new global::MonoDevelop.Components.FolderEntry(); this.folderEntry.Name = "folderEntry"; - this.hbox46.Add (this.folderEntry); - global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox46 [this.folderEntry])); + this.hbox46.Add(this.folderEntry); + global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox46[this.folderEntry])); w3.Position = 1; - this.vbox68.Add (this.hbox46); - global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox68 [this.hbox46])); + this.vbox68.Add(this.hbox46); + global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox68[this.hbox46])); w4.Position = 1; w4.Expand = false; w4.Fill = false; w4.Padding = ((uint)(6)); - this.Add (this.vbox68); - if ((this.Child != null)) { - this.Child.ShowAll (); + this.Add(this.vbox68); + if ((this.Child != null)) + { + this.Child.ShowAll(); } - this.Show (); + this.Show(); } } } diff --git a/main/src/core/MonoDevelop.Ide/packages.config b/main/src/core/MonoDevelop.Ide/packages.config index d9b79ad7a5..b0adcab8d3 100644 --- a/main/src/core/MonoDevelop.Ide/packages.config +++ b/main/src/core/MonoDevelop.Ide/packages.config @@ -13,7 +13,7 @@ <package id="Microsoft.VisualStudio.Text.UI" version="15.0.26201" targetFramework="net461" /> <package id="Microsoft.VisualStudio.Validation" version="15.3.15" targetFramework="net461" /> <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" /> - <package id="SharpZipLib" version="0.86.0" targetFramework="net45" /> + <package id="JetBrains.SharpZipLib.Stripped" version="0.87.20170615.10" targetFramework="net461" /> <package id="System.Collections.Immutable" version="1.3.1" targetFramework="net45" /> <package id="System.Composition" version="1.0.31" targetFramework="net45" /> <package id="System.IO.Compression" version="4.3.0" targetFramework="net45" /> diff --git a/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj b/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj index 4301c1c776..dac10de985 100644 --- a/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj +++ b/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj @@ -127,5 +127,5 @@ </Content> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> - <Import Project="$(MSBuildThisFileDirectory)..\..\..\packages\LargeAddressAware.1.0.0\build\LargeAddressAware.targets" Condition="$(OS) != 'Unix' AND Exists('$(MSBuildThisFileDirectory)..\..\..\packages\LargeAddressAware.1.0.0\build\LargeAddressAware.targets')" /> + <Import Project="$(MSBuildThisFileDirectory)..\..\..\packages\LargeAddressAware.1.0.1\build\LargeAddressAware.targets" Condition="$(OS) != 'Unix' AND Exists('$(MSBuildThisFileDirectory)..\..\..\packages\LargeAddressAware.1.0.1\build\LargeAddressAware.targets')" /> </Project> diff --git a/main/src/core/MonoDevelop.Startup/app.config b/main/src/core/MonoDevelop.Startup/app.config index a6193c0c18..a4ff3b3413 100644 --- a/main/src/core/MonoDevelop.Startup/app.config +++ b/main/src/core/MonoDevelop.Startup/app.config @@ -6,8 +6,8 @@ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="ICSharpCode.SharpZipLib" publicKeyToken="1b03e6acf1164f73" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-0.86.0.518" newVersion="0.86.0.518" /> - <bindingRedirect oldVersion="2.84.0.0-4.84.0.0" newVersion="0.86.0.518" /> + <bindingRedirect oldVersion="0.0.0.0-0.86.0.518" newVersion="1.0.6375.31400" /> + <bindingRedirect oldVersion="2.84.0.0-4.84.0.0" newVersion="1.0.6375.31400" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> diff --git a/main/src/core/MonoDevelop.Startup/packages.config b/main/src/core/MonoDevelop.Startup/packages.config index b66b85fce8..5e81482871 100644 --- a/main/src/core/MonoDevelop.Startup/packages.config +++ b/main/src/core/MonoDevelop.Startup/packages.config @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="LargeAddressAware" version="1.0.0" /> + <package id="LargeAddressAware" version="1.0.1" /> </packages>
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/DeleteActionTests.cs b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/DeleteActionTests.cs index d8fcc9ff1e..d537f0e107 100644 --- a/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/DeleteActionTests.cs +++ b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/DeleteActionTests.cs @@ -215,5 +215,30 @@ namespace Mono.TextEditor.Tests.Actions DeleteActions.NextSubword (data); Check (data, @" $"); } + + [Test] + public void AdvancedBackspaceTests () + { + var data = Create (@"($)", mimeType: "text/x-csharp"); + MonoDevelop.SourceEditor.EditActions.AdvancedBackspace (data); + Check (data, @"$"); + data = Create (@"[$]", mimeType:"text/x-csharp"); + MonoDevelop.SourceEditor.EditActions.AdvancedBackspace (data); + Check (data, @"$"); + data = Create ("\"$\"", mimeType:"text/x-csharp"); + MonoDevelop.SourceEditor.EditActions.AdvancedBackspace (data); + Check (data, @"$"); + data = Create ("'$'", mimeType: "text/x-csharp"); + MonoDevelop.SourceEditor.EditActions.AdvancedBackspace (data); + Check (data, @"$"); + + data = Create (@"// ($)", mimeType: "text/x-csharp"); + MonoDevelop.SourceEditor.EditActions.AdvancedBackspace (data); + Check (data, @"// $)"); + + data = Create (@""" ($)", mimeType: "text/x-csharp"); + MonoDevelop.SourceEditor.EditActions.AdvancedBackspace (data); + Check (data, @""" $)"); + } } } diff --git a/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/TextEditorTestBase.cs b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/TextEditorTestBase.cs index 6fa47fa552..6446512e13 100644 --- a/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/TextEditorTestBase.cs +++ b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests.DefaultEditActions/TextEditorTestBase.cs @@ -92,11 +92,13 @@ namespace Mono.TextEditor.Tests - public static TextEditorData Create (string content, ITextEditorOptions options = null) + public static TextEditorData Create (string content, ITextEditorOptions options = null, string mimeType = null) { var data = new TextEditorData (); if (options != null) data.Options = options; + if (mimeType != null) + data.Document.MimeType = mimeType; var sb = new StringBuilder (); int caretIndex = -1, selectionStart = -1, selectionEnd = -1; var foldSegments = new List<FoldSegment> (); |