diff --git a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs index 3b19dba9b2..9f47b35148 100644 --- a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs +++ b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs @@ -58,6 +58,7 @@ namespace ICSharpCode.CodeCoverage public string FileID { get; private set; } public string FileName { get; private set; } + public string FileNameExt { get; private set; } public bool IsVisited { get; private set; } public int CyclomaticComplexity { get; private set; } public decimal SequenceCoverage { get; private set; } @@ -86,9 +87,14 @@ namespace ICSharpCode.CodeCoverage this.FileID = GetFileRef(); this.FileName = String.Empty; + this.FileNameExt = String.Empty; if (!String.IsNullOrEmpty(this.FileID)) { if (results != null) { this.FileName = results.GetFileName(this.FileID); + try { + this.FileNameExt = Path.GetExtension(this.FileName).ToLowerInvariant(); + } + catch {} if (cacheFileName != this.FileName) { cacheFileName = this.FileName; cacheDocument = GetSource (cacheFileName); @@ -220,14 +226,19 @@ namespace ICSharpCode.CodeCoverage // -> this method SP with lowest Line/Column void getBodyStartSP() { if (this.SequencePoints.Count != 0) { - foreach (CodeCoverageSequencePoint sp in this.SequencePoints) { - if (sp.FileID != this.FileID) continue; - if (this.BodyStartSP == null || (sp.Line < this.BodyStartSP.Line) || - (sp.Line == this.BodyStartSP.Line && sp.Column < this.BodyStartSP.Column) - ) { - this.BodyStartSP = sp; + if (this.FileNameExt == ".cs") { + foreach (CodeCoverageSequencePoint sp in this.SequencePoints) { + if (sp.FileID != this.FileID) continue; + if (this.BodyStartSP == null || (sp.Line < this.BodyStartSP.Line) || + (sp.Line == this.BodyStartSP.Line && sp.Column < this.BodyStartSP.Column) + ) { + this.BodyStartSP = sp; + } } } + else { + this.BodyStartSP = this.SequencePoints.First(); + } } } @@ -236,29 +247,34 @@ namespace ICSharpCode.CodeCoverage // and lowest Offset (when duplicated bw ccrewrite) void getBodyFinalSP() { if (this.SequencePoints.Count != 0) { - for (int i = this.SequencePoints.Count-1; i > 0; i--) { - var sp = this.SequencePoints[i]; - if (sp.FileID != this.FileID) continue; - if (sp.Content != "}") continue; - if (this.BodyFinalSP == null || (sp.Line > this.BodyFinalSP.Line) || - (sp.Line == this.BodyFinalSP.Line && sp.Column >= this.BodyFinalSP.Column) - ) { - // ccrewrite ContractClass/ContractClassFor - // adds duplicate method end-sequence-point "}" - // - // Take duplicate BodyFinalSP with lower Offset - // Because IL.Offset of second duplicate - // will extend branch coverage of this method - // by coverage of ContractClassFor inserted SequencePoint! - if (this.BodyFinalSP != null && - sp.Line == this.BodyFinalSP.Line && - sp.Column == this.BodyFinalSP.Column && - sp.Offset < this.BodyFinalSP.Offset) { - this.SequencePoints.Remove(this.BodyFinalSP); // remove duplicate + if (this.FileNameExt == ".cs") { + for (int i = this.SequencePoints.Count-1; i > 0; i--) { + var sp = this.SequencePoints[i]; + if (sp.FileID != this.FileID) continue; + if (sp.Content != "}") continue; + if (this.BodyFinalSP == null || (sp.Line > this.BodyFinalSP.Line) || + (sp.Line == this.BodyFinalSP.Line && sp.Column >= this.BodyFinalSP.Column) + ) { + // ccrewrite ContractClass/ContractClassFor + // adds duplicate method end-sequence-point "}" + // + // Take duplicate BodyFinalSP with lower Offset + // Because IL.Offset of second duplicate + // will extend branch coverage of this method + // by coverage of ContractClassFor inserted SequencePoint! + if (this.BodyFinalSP != null && + sp.Line == this.BodyFinalSP.Line && + sp.Column == this.BodyFinalSP.Column && + sp.Offset < this.BodyFinalSP.Offset) { + this.SequencePoints.Remove(this.BodyFinalSP); // remove duplicate + } + this.BodyFinalSP = sp; } - this.BodyFinalSP = sp; } } + else { + this.BodyFinalSP = this.SequencePoints.Last(); + } } } @@ -273,6 +289,9 @@ namespace ICSharpCode.CodeCoverage return 0; } + const string @assert = "Assert"; + const string @contract = "Contract"; + void GetBranchRatio () { this.BranchCoverageRatio = null; @@ -295,31 +314,33 @@ namespace ICSharpCode.CodeCoverage // SequencePoint is visited and belongs to this method? if (sp.VisitCount != 0 && sp.FileID == this.FileID) { - // Don't want branch coverage of ccrewrite(n) - // SequencePoint's with offset before and after method body - if (sp.Offset < BodyStartSP.Offset || - sp.Offset > BodyFinalSP.Offset) { - sp.BranchCoverage = true; - continue; // skip - } + if (this.FileNameExt == ".cs") { + // Only for C# - // 1) Generated "in" code for IEnumerables contains hidden "try/catch/finally" branches that - // one do not want or cannot cover by test-case because is handled earlier at same method. - // ie: NullReferenceException in foreach loop is pre-handled at method entry, ie. by Contract.Require(items!=null) - // 2) Branches within sequence points "{" and "}" are not source branches but compiler generated branches - // ie: static methods start sequence point "{" contains compiler generated branches - // 3) Exclude Contract class (EnsuresOnThrow/Assert/Assume is inside method body) - // 4) Exclude NUnit Assert(.Throws) class - const string assert = "Assert"; - const string contract = "Contract"; - if (sp.Content == "in" || sp.Content == "{" || sp.Content == "}" || - sp.Content.StartsWith(assert + ".", StringComparison.Ordinal) || - sp.Content.StartsWith(assert + " ", StringComparison.Ordinal) || - sp.Content.StartsWith(contract + ".", StringComparison.Ordinal) || - sp.Content.StartsWith(contract + " ", StringComparison.Ordinal) - ) { - sp.BranchCoverage = true; - continue; // skip + // Don't want branch coverage of ccrewrite(n) + // SequencePoint(s) with offset before and after method body + if (sp.Offset < BodyStartSP.Offset || + sp.Offset > BodyFinalSP.Offset) { + sp.BranchCoverage = true; + continue; // skip + } + + // 1) Generated "in" code for IEnumerables contains hidden "try/catch/finally" branches that + // one do not want or cannot cover by test-case because is handled earlier at same method. + // ie: NullReferenceException in foreach loop is pre-handled at method entry, ie. by Contract.Require(items!=null) + // 2) Branches within sequence points "{" and "}" are not source branches but compiler generated branches + // ie: static methods start sequence point "{" contains compiler generated branches + // 3) Exclude Contract class (EnsuresOnThrow/Assert/Assume is inside method body) + // 4) Exclude NUnit Assert(.Throws) class + if (sp.Content == "in" || sp.Content == "{" || sp.Content == "}" || + sp.Content.StartsWith(@assert + ".", StringComparison.Ordinal) || + sp.Content.StartsWith(@assert + " ", StringComparison.Ordinal) || + sp.Content.StartsWith(@contract + ".", StringComparison.Ordinal) || + sp.Content.StartsWith(@contract + " ", StringComparison.Ordinal) + ) { + sp.BranchCoverage = true; + continue; // skip + } } totalBranchCount += sp.BranchExitsCount; diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin index f2e4adf86b..c9bea23cba 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin @@ -510,7 +510,7 @@ - + diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj index 2762300961..dbbd1b7739 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj @@ -93,7 +93,7 @@ - + diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs index 411279933f..48103a5acf 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs @@ -19,7 +19,9 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Threading; +using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.TypeSystem; @@ -62,6 +64,8 @@ namespace CSharpBinding IList contextActionProviders; CodeManipulation codeManipulation; CaretReferenceHighlightRenderer renderer; + CodeEditorFormattingOptionsAdapter options; + TextEditorOptions originalEditorOptions; public void Attach(ITextEditor editor) { @@ -70,14 +74,46 @@ namespace CSharpBinding codeManipulation = new CodeManipulation(editor); renderer = new CaretReferenceHighlightRenderer(editor); + // Patch editor options (indentation) to project-specific settings if (!editor.ContextActionProviders.IsReadOnly) { contextActionProviders = AddInTree.BuildItems("/SharpDevelop/ViewContent/TextEditor/C#/ContextActions", null); editor.ContextActionProviders.AddRange(contextActionProviders); } + + // Create instance of options adapter and register it as service + var formattingPolicy = CSharpFormattingPolicies.Instance.GetProjectOptions( + SD.ProjectService.FindProjectContainingFile(editor.FileName)); + options = new CodeEditorFormattingOptionsAdapter(editor.Options, formattingPolicy.OptionsContainer); + var textEditor = editor.GetService(); + if (textEditor != null) { + var textViewServices = textEditor.TextArea.TextView.Services; + + // Unregister any previous ITextEditorOptions instance from editor, if existing, register our impl. + textViewServices.RemoveService(typeof(ITextEditorOptions)); + textViewServices.AddService(typeof(ITextEditorOptions), options); + + // Set TextEditor's options to same object + originalEditorOptions = textEditor.Options; + textEditor.Options = options; + } } public void Detach() { + var textEditor = editor.GetService(); + if (textEditor != null) { + var textView = textEditor.TextArea.TextView; + + // Unregister our ITextEditorOptions instance from editor + var optionsService = textView.GetService(); + if ((optionsService != null) && (optionsService == options)) + textView.Services.RemoveService(typeof(ITextEditorOptions)); + + // Reset TextEditor options, too? + if ((textEditor.Options != null) && (textEditor.Options == options)) + textEditor.Options = originalEditorOptions; + } + codeManipulation.Dispose(); if (inspectionManager != null) { inspectionManager.Dispose(); @@ -87,7 +123,230 @@ namespace CSharpBinding editor.ContextActionProviders.RemoveAll(contextActionProviders.Contains); } renderer.Dispose(); + options = null; this.editor = null; } } + + class CodeEditorFormattingOptionsAdapter : TextEditorOptions, ITextEditorOptions, ICodeEditorOptions + { + CSharpFormattingOptionsContainer container; + readonly ITextEditorOptions globalOptions; + readonly ICodeEditorOptions globalCodeEditorOptions; + + public CodeEditorFormattingOptionsAdapter(ITextEditorOptions globalOptions, CSharpFormattingOptionsContainer container) + { + if (globalOptions == null) + throw new ArgumentNullException("globalOptions"); + if (container == null) + throw new ArgumentNullException("container"); + + this.globalOptions = globalOptions; + this.globalCodeEditorOptions = globalOptions as ICodeEditorOptions; + this.container = container; + + CSharpFormattingPolicies.Instance.FormattingPolicyUpdated += OnFormattingPolicyUpdated; + globalOptions.PropertyChanged += OnGlobalOptionsPropertyChanged; + } + + void OnFormattingPolicyUpdated(object sender, CSharpBinding.FormattingStrategy.CSharpFormattingPolicyUpdateEventArgs e) + { + OnPropertyChanged("IndentationSize"); + OnPropertyChanged("ConvertTabsToSpaces"); + } + + void OnGlobalOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + OnPropertyChanged(e.PropertyName); + } + + #region ITextEditorOptions implementation + + public override int IndentationSize { + get { + return container.GetEffectiveIndentationSize() ?? globalOptions.IndentationSize; + } + } + + public override bool ConvertTabsToSpaces { + get { + return container.GetEffectiveConvertTabsToSpaces() ?? globalOptions.ConvertTabsToSpaces; + } + } + + public bool AutoInsertBlockEnd { + get { + return globalOptions.AutoInsertBlockEnd; + } + } + + public int VerticalRulerColumn { + get { + return globalOptions.VerticalRulerColumn; + } + } + + public bool UnderlineErrors { + get { + return globalOptions.UnderlineErrors; + } + } + + public string FontFamily { + get { + return globalOptions.FontFamily; + } + } + + public double FontSize { + get { + return globalOptions.FontSize; + } + } + + #endregion + + public override bool AllowScrollBelowDocument { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.AllowScrollBelowDocument : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.AllowScrollBelowDocument = value; + } + } + } + + public bool ShowLineNumbers { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.ShowLineNumbers : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.ShowLineNumbers = value; + } + } + } + + public bool EnableChangeMarkerMargin { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableChangeMarkerMargin : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.EnableChangeMarkerMargin = value; + } + } + } + + public bool WordWrap { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.WordWrap : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.WordWrap = value; + } + } + } + + public bool CtrlClickGoToDefinition { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.CtrlClickGoToDefinition : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.CtrlClickGoToDefinition = value; + } + } + } + + public bool MouseWheelZoom { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.MouseWheelZoom : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.MouseWheelZoom = value; + } + } + } + + public bool HighlightBrackets { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.HighlightBrackets : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.HighlightBrackets = value; + } + } + } + + public bool HighlightSymbol { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.HighlightSymbol : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.HighlightSymbol = value; + } + } + } + + public bool EnableAnimations { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableAnimations : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.EnableAnimations = value; + } + } + } + + public bool UseSmartIndentation { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.UseSmartIndentation : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.UseSmartIndentation = value; + } + } + } + + public bool EnableFolding { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableFolding : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.EnableFolding = value; + } + } + } + + public bool EnableQuickClassBrowser { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableQuickClassBrowser : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.EnableQuickClassBrowser = value; + } + } + } + + public bool ShowHiddenDefinitions { + get { + return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.ShowHiddenDefinitions : default(bool); + } + set { + if (globalCodeEditorOptions != null) { + globalCodeEditorOptions.ShowHiddenDefinitions = value; + } + } + } + } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs index 3f3323cfbe..c81f2b3349 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs @@ -99,7 +99,7 @@ namespace CSharpBinding.Completion completionContext.ProjectContent, completionContext.TypeResolveContextAtCaret ); - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(completionContext.Compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(completionContext.Compilation.GetProject()); cce.FormattingPolicy = formattingOptions.OptionsContainer.GetEffectiveOptions(); cce.EolMarker = DocumentUtilities.GetLineTerminator(completionContext.Document, currentLocation.Line); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs index 939333a453..7d1eb15a51 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs @@ -72,7 +72,7 @@ namespace CSharpBinding.Completion ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; var stringBuilder = new StringBuilder(); var formatter = new ParameterHighlightingOutputFormatter(stringBuilder, highlightedParameterIndex); - ambience.ConvertSymbol(Method, formatter, CSharpFormattingOptionsPersistence.GlobalOptions.OptionsContainer.GetEffectiveOptions()); + ambience.ConvertSymbol(Method, formatter, CSharpFormattingPolicies.Instance.GlobalOptions.OptionsContainer.GetEffectiveOptions()); var documentation = XmlDocumentationElement.Get(Method); ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpMethodInsight.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpMethodInsight.cs index 33b42b37bd..8fb08c9316 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpMethodInsight.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpMethodInsight.cs @@ -50,7 +50,9 @@ namespace CSharpBinding.Completion public void Show() { window = editor.ShowInsightWindow(items); - window.StartOffset = startOffset; + // Set startOffset so that window always appears below the caret line + var startLocation = editor.Document.GetLocation(startOffset); + window.StartOffset = editor.Document.GetOffset(editor.Caret.Line, startLocation.Column); // closing the window at the end of the parameter list is handled by the CaretPositionChanged event window.EndOffset = editor.Document.TextLength; if (initiallySelectedItem != null) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideCompletionData.cs index ede72ab53e..f3d5c57eb4 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideCompletionData.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideCompletionData.cs @@ -98,7 +98,7 @@ namespace CSharpBinding.Completion var document = context.Editor.Document; StringWriter w = new StringWriter(); - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(contextAtCaret.Compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(contextAtCaret.Compilation.GetProject()); var segmentDict = SegmentTrackingOutputFormatter.WriteNode( w, entityDeclaration, formattingOptions.OptionsContainer.GetEffectiveOptions(), context.Editor.Options); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs index 7b0ae25f0e..78f1ca6e89 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs @@ -84,7 +84,7 @@ namespace CSharpBinding.Completion var document = context.Editor.Document; StringWriter w = new StringWriter(); - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(contextAtCaret.Compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(contextAtCaret.Compilation.GetProject()); var segmentDict = SegmentTrackingOutputFormatter.WriteNode( w, entityDeclaration, formattingOptions.OptionsContainer.GetEffectiveOptions(), context.Editor.Options); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs index 0d75f8f133..f0bcd41674 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs @@ -81,7 +81,7 @@ namespace CSharpBinding.Completion var document = context.Editor.Document; StringWriter w = new StringWriter(); - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(contextAtCaret.Compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(contextAtCaret.Compilation.GetProject()); var segmentDict = SegmentTrackingOutputFormatter.WriteNode( w, entityDeclaration, formattingOptions.OptionsContainer.GetEffectiveOptions(), context.Editor.Options); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/PartialCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/PartialCompletionData.cs index 7cd6f37a43..d05ff650c0 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/PartialCompletionData.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/PartialCompletionData.cs @@ -64,7 +64,7 @@ namespace CSharpBinding.Completion var document = context.Editor.Document; StringWriter w = new StringWriter(); - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(contextAtCaret.Compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(contextAtCaret.Compilation.GetProject()); var segmentDict = SegmentTrackingOutputFormatter.WriteNode( w, entityDeclaration, formattingOptions.OptionsContainer.GetEffectiveOptions(), context.Editor.Options); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs index 028a43e6a8..65bec18aca 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs @@ -31,7 +31,9 @@ namespace CSharpBinding.FormattingStrategy /// public static void Format(ITextEditor editor, int offset, int length, CSharpFormattingOptionsContainer optionsContainer) { - var formatter = new CSharpFormatter(optionsContainer.GetEffectiveOptions(), editor.ToEditorOptions()); + TextEditorOptions editorOptions = editor.ToEditorOptions(); + optionsContainer.CustomizeEditorOptions(editorOptions); + var formatter = new CSharpFormatter(optionsContainer.GetEffectiveOptions(), editorOptions); formatter.AddFormattingRegion(new DomRegion(editor.Document.GetLocation(offset), editor.Document.GetLocation(offset + length))); var changes = formatter.AnalyzeFormatting(editor.Document, SyntaxTree.Parse(editor.Document)); changes.ApplyChanges(offset, length); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs index 0dd30bc82a..103ba60284 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs @@ -34,8 +34,13 @@ namespace CSharpBinding.FormattingStrategy /// internal class CSharpFormattingOptionsContainer : INotifyPropertyChanged { + private const string IndentationSizePropertyName = "IndentationSize"; + private const string ConvertTabsToSpacesPropertyName = "ConvertTabsToSpaces"; + CSharpFormattingOptionsContainer parent; CSharpFormattingOptions cachedOptions; + int? indentationSize; + bool? convertTabsToSpaces; readonly HashSet activeOptions; @@ -106,6 +111,8 @@ namespace CSharpBinding.FormattingStrategy foreach (var activeOption in options.activeOptions) activeOptions.Add(activeOption); cachedOptions = options.cachedOptions.Clone(); + indentationSize = options.indentationSize; + convertTabsToSpaces = options.convertTabsToSpaces; OnPropertyChanged(null); } @@ -127,6 +134,14 @@ namespace CSharpBinding.FormattingStrategy if ((e.PropertyName == "Parent") || (e.PropertyName == null)) { // All properties might have changed -> update everything cachedOptions = CreateCachedOptions(); + } else if (e.PropertyName == IndentationSizePropertyName) { + if (!indentationSize.HasValue) { + indentationSize = GetEffectiveIndentationSize(); + } + } else if (e.PropertyName == ConvertTabsToSpacesPropertyName) { + if (!convertTabsToSpaces.HasValue) { + convertTabsToSpaces = GetEffectiveConvertTabsToSpaces(); + } } else { // Some other property has changed, check if we have our own value for it if (!activeOptions.Contains(e.PropertyName)) { @@ -148,10 +163,18 @@ namespace CSharpBinding.FormattingStrategy public object GetOption(string option) { // Run up the hierarchy until we find a defined value for property - if (activeOptions.Contains(option)) { - PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); - if (propertyInfo != null) { - return propertyInfo.GetValue(cachedOptions); + if (option == IndentationSizePropertyName) { + if (indentationSize.HasValue) + return indentationSize.Value; + } else if (option == ConvertTabsToSpacesPropertyName) { + if (convertTabsToSpaces.HasValue) + return convertTabsToSpaces.Value; + } else { + if (activeOptions.Contains(option)) { + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); + if (propertyInfo != null) { + return propertyInfo.GetValue(cachedOptions); + } } } @@ -186,6 +209,68 @@ namespace CSharpBinding.FormattingStrategy return null; } + public int? IndentationSize + { + get { + return indentationSize; + } + set { + indentationSize = value; + OnPropertyChanged(IndentationSizePropertyName); + } + } + + /// + /// Retrieves the value of "IndentationSize" option by looking at current and (if nothing set here) parent + /// containers. + /// + public int? GetEffectiveIndentationSize() + { + // Run up the hierarchy until we find a defined value for property + CSharpFormattingOptionsContainer container = this; + do + { + int? val = container.indentationSize; + if (val.HasValue) { + return val.Value; + } + container = container.parent; + } while (container != null); + + return null; + } + + public bool? ConvertTabsToSpaces + { + get { + return convertTabsToSpaces; + } + set { + convertTabsToSpaces = value; + OnPropertyChanged(ConvertTabsToSpacesPropertyName); + } + } + + /// + /// Retrieves the value of v option by looking at current and (if nothing set here) parent + /// containers. + /// + public bool? GetEffectiveConvertTabsToSpaces() + { + // Run up the hierarchy until we find a defined value for property + CSharpFormattingOptionsContainer container = this; + do + { + bool? val = container.convertTabsToSpaces; + if (val.HasValue) { + return val.Value; + } + container = container.parent; + } while (container != null); + + return null; + } + /// /// Sets an option. /// @@ -195,18 +280,32 @@ namespace CSharpBinding.FormattingStrategy { if (value != null) { // Save value in option values and cached options - activeOptions.Add(option); - PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); - if ((propertyInfo != null) && (propertyInfo.PropertyType == value.GetType())) { - propertyInfo.SetValue(cachedOptions, value); + if (option == IndentationSizePropertyName) { + if (value is int) + indentationSize = (int) value; + } else if (option == ConvertTabsToSpacesPropertyName) { + if (value is bool) + convertTabsToSpaces = (bool) value; + } else { + activeOptions.Add(option); + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); + if ((propertyInfo != null) && (propertyInfo.PropertyType == value.GetType())) { + propertyInfo.SetValue(cachedOptions, value); + } } } else { // Reset this option - activeOptions.Remove(option); - // Update formatting options object from parents - PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); - if (propertyInfo != null) { - propertyInfo.SetValue(cachedOptions, GetEffectiveOption(option)); + if (option == IndentationSizePropertyName) { + indentationSize = null; + } else if (option == ConvertTabsToSpacesPropertyName) { + convertTabsToSpaces = null; + } else { + activeOptions.Remove(option); + // Update formatting options object from parents + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); + if (propertyInfo != null) { + propertyInfo.SetValue(cachedOptions, GetEffectiveOption(option)); + } } } OnPropertyChanged(option); @@ -219,6 +318,11 @@ namespace CSharpBinding.FormattingStrategy /// Option's type. public Type GetOptionType(string option) { + if (option == IndentationSizePropertyName) + return typeof(int); + if (option == ConvertTabsToSpacesPropertyName) + return typeof(bool); + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); if (propertyInfo != null) { return propertyInfo.PropertyType; @@ -258,6 +362,19 @@ namespace CSharpBinding.FormattingStrategy return outputOptions; } + public void CustomizeEditorOptions(TextEditorOptions editorOptions) + { + int? indentationSize = GetEffectiveIndentationSize(); + if (indentationSize.HasValue) { + editorOptions.IndentSize = indentationSize.Value; + editorOptions.TabSize = indentationSize.Value; + editorOptions.ContinuationIndent = indentationSize.Value; + } + bool? convertTabsToSpaces = GetEffectiveConvertTabsToSpaces(); + if (convertTabsToSpaces.HasValue) + editorOptions.TabsToSpaces = convertTabsToSpaces.Value; + } + public void Load(Properties parentProperties) { if (parentProperties == null) @@ -275,6 +392,9 @@ namespace CSharpBinding.FormattingStrategy } } } + + indentationSize = formatProperties.Get(IndentationSizePropertyName, new int?()); + convertTabsToSpaces = formatProperties.Get(ConvertTabsToSpacesPropertyName, new bool?()); } } @@ -291,6 +411,10 @@ namespace CSharpBinding.FormattingStrategy formatProperties.Set(activeOption, val); } } + if (indentationSize.HasValue) + formatProperties.Set(IndentationSizePropertyName, indentationSize.Value); + if (convertTabsToSpaces.HasValue) + formatProperties.Set(ConvertTabsToSpacesPropertyName, convertTabsToSpaces.Value); parentProperties.SetNestedProperties("CSharpFormatting", formatProperties); } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsPersistence.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingPolicies.cs similarity index 59% rename from src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsPersistence.cs rename to src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingPolicies.cs index df5b11e2aa..5999f1dd1f 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsPersistence.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingPolicies.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using ICSharpCode.Core; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.SharpDevelop; @@ -25,43 +26,50 @@ using ICSharpCode.SharpDevelop.Project; namespace CSharpBinding.FormattingStrategy { - public class CSharpFormattingOptionsPersistenceInitCommand : SimpleCommand + public class CSharpFormattingOptionsPoliciesInitCommand : SimpleCommand { public override void Execute(object parameter) { - // Initialize CSharpFormattingOptionsPersistence as early as possible (before solution is opened) - CSharpFormattingOptionsPersistence.Initialize(); + // Initialize CSharpFormattingPolicies as early as possible (before solution is opened) + CSharpFormattingPolicies.Instance.Initialize(); } } /// - /// Persistence helper for C# formatting options. + /// Management class for formatting policies. /// - internal class CSharpFormattingOptionsPersistence + internal class CSharpFormattingPolicies { - static bool initialized; - static Dictionary projectOptions; + static readonly Lazy LazyInstance = + new Lazy(() => new CSharpFormattingPolicies()); - static CSharpFormattingOptionsPersistence() + public static CSharpFormattingPolicies Instance { + get { return LazyInstance.Value; } + } + + public event EventHandler FormattingPolicyUpdated; + + bool initialized; + Dictionary projectOptions; + + public CSharpFormattingPolicies() { - Initialize(); + // Load global settings + GlobalOptions = new CSharpFormattingPolicy( + SD.PropertyService.MainPropertiesContainer, new CSharpFormattingOptionsContainer() { + DefaultText = StringParser.Parse("${res:CSharpBinding.Formatting.GlobalOptionReference}") + }); + GlobalOptions.FormattingPolicyUpdated += OnFormattingPolicyUpdated; + GlobalOptions.Load(); } - public static void Initialize() + public void Initialize() { if (initialized) return; initialized = true; - projectOptions = new Dictionary(); - - // Load global settings - GlobalOptions = new CSharpFormattingOptionsPersistence( - SD.PropertyService.MainPropertiesContainer, new CSharpFormattingOptionsContainer() - { - DefaultText = StringParser.Parse("${res:CSharpBinding.Formatting.GlobalOptionReference}") - }); - GlobalOptions.Load(); + projectOptions = new Dictionary(); // Handlers for solution loading/unloading var projectService = SD.GetService(); @@ -71,8 +79,7 @@ namespace CSharpBinding.FormattingStrategy } } - public static bool AutoFormatting - { + public static bool AutoFormatting { get { return SD.PropertyService.Get("CSharpBinding.Formatting.AutoFormatting", false); } @@ -81,31 +88,32 @@ namespace CSharpBinding.FormattingStrategy } } - public static CSharpFormattingOptionsPersistence GlobalOptions - { + public CSharpFormattingPolicy GlobalOptions { get; private set; } - public static CSharpFormattingOptionsPersistence SolutionOptions - { + public CSharpFormattingPolicy SolutionOptions { get; private set; } - public static CSharpFormattingOptionsPersistence GetProjectOptions(IProject project) + public CSharpFormattingPolicy GetProjectOptions(IProject project) { + if (!initialized) + return GlobalOptions; + var csproject = project as CSharpProject; if (csproject != null) { string key = project.FileName; if (!projectOptions.ContainsKey(key)) { // Lazily create options container for project - var projectFormattingPersistence = new CSharpFormattingOptionsPersistence( + var projectFormattingPersistence = new CSharpFormattingPolicy( csproject.GlobalPreferences, - new CSharpFormattingOptionsContainer((SolutionOptions ?? GlobalOptions).OptionsContainer) - { + new CSharpFormattingOptionsContainer((SolutionOptions ?? GlobalOptions).OptionsContainer) { DefaultText = StringParser.Parse("${res:CSharpBinding.Formatting.ProjectOptionReference}") }); + projectFormattingPersistence.FormattingPolicyUpdated += OnFormattingPolicyUpdated; projectFormattingPersistence.Load(); projectOptions[key] = projectFormattingPersistence; } @@ -116,34 +124,70 @@ namespace CSharpBinding.FormattingStrategy return SolutionOptions ?? GlobalOptions; } - static void SolutionOpened(object sender, SolutionEventArgs e) + void SolutionOpened(object sender, SolutionEventArgs e) { // Load solution settings - SolutionOptions = new CSharpFormattingOptionsPersistence( + SolutionOptions = new CSharpFormattingPolicy( e.Solution.SDSettings, - new CSharpFormattingOptionsContainer(GlobalOptions.OptionsContainer) - { + new CSharpFormattingOptionsContainer(GlobalOptions.OptionsContainer) { DefaultText = StringParser.Parse("${res:CSharpBinding.Formatting.SolutionOptionReference}") }); + SolutionOptions.FormattingPolicyUpdated += OnFormattingPolicyUpdated; SolutionOptions.Load(); } - static void SolutionClosed(object sender, SolutionEventArgs e) + void SolutionClosed(object sender, SolutionEventArgs e) { + SolutionOptions.FormattingPolicyUpdated -= OnFormattingPolicyUpdated; SolutionOptions = null; projectOptions.Clear(); } + void OnFormattingPolicyUpdated(object sender, CSharpFormattingPolicyUpdateEventArgs e) + { + if (FormattingPolicyUpdated != null) { + FormattingPolicyUpdated(sender, e); + } + } + } + + /// + /// Contains event data for formatting policy update events. + /// + internal class CSharpFormattingPolicyUpdateEventArgs : EventArgs + { + public CSharpFormattingPolicyUpdateEventArgs(CSharpFormattingOptionsContainer container) + { + OptionsContainer = container; + } + + /// + /// Returns updated options container. + /// + public CSharpFormattingOptionsContainer OptionsContainer + { + get; + private set; + } + } + + /// + /// Persistence helper for C# formatting options of a certain policy (e.g. global, solution, project). + /// + internal class CSharpFormattingPolicy + { + public event EventHandler FormattingPolicyUpdated; + readonly Properties propertiesContainer; - CSharpFormattingOptionsContainer optionsContainer; + readonly CSharpFormattingOptionsContainer optionsContainer; CSharpFormattingOptionsContainer optionsContainerWorkingCopy; /// - /// Creates a new instance of formatting options persistence helper, using given options to predefine the options container. + /// Creates a new instance of formatting options policy, using given options to predefine the options container. /// /// Properties container to load from and save to. /// Initial (empty) instance of formatting options container. - public CSharpFormattingOptionsPersistence(Properties propertiesContainer, CSharpFormattingOptionsContainer initialContainer) + public CSharpFormattingPolicy(Properties propertiesContainer, CSharpFormattingOptionsContainer initialContainer) { if (initialContainer == null) throw new ArgumentNullException("initialContainer"); @@ -153,7 +197,7 @@ namespace CSharpBinding.FormattingStrategy } /// - /// Returns the option container managed by this helper. + /// Returns the option container for this policy. /// public CSharpFormattingOptionsContainer OptionsContainer { @@ -196,7 +240,15 @@ namespace CSharpBinding.FormattingStrategy // Convert to SD properties optionsContainer.Save(propertiesContainer); + OnFormattingPolicyUpdated(this, optionsContainer); return true; } + + void OnFormattingPolicyUpdated(object sender, CSharpFormattingOptionsContainer container) + { + if (FormattingPolicyUpdated != null) { + FormattingPolicyUpdated(sender, new CSharpFormattingPolicyUpdateEventArgs(container)); + } + } } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs index 5c365b2f66..2ab802e950 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs @@ -48,7 +48,7 @@ namespace CSharpBinding.FormattingStrategy DocumentAccessor acc = new DocumentAccessor(editor.Document, lineNr, lineNr); CSharpIndentationStrategy indentStrategy = new CSharpIndentationStrategy(); - indentStrategy.IndentationString = editor.Options.IndentationString; + indentStrategy.IndentationString = GetIndentationString(editor); indentStrategy.Indent(acc, false); string t = acc.Text; @@ -62,33 +62,64 @@ namespace CSharpBinding.FormattingStrategy { DocumentAccessor acc = new DocumentAccessor(editor.Document, beginLine, endLine); CSharpIndentationStrategy indentStrategy = new CSharpIndentationStrategy(); - indentStrategy.IndentationString = editor.Options.IndentationString; + indentStrategy.IndentationString = GetIndentationString(editor); indentStrategy.Indent(acc, true); } + CSharpFormattingOptionsContainer GetOptionsContainerForEditor(ITextEditor editor) + { + var currentProject = SD.ProjectService.FindProjectContainingFile(editor.FileName); + if (currentProject != null) { + var persistence = CSharpFormattingPolicies.Instance.GetProjectOptions(currentProject); + if (persistence != null) { + return persistence.OptionsContainer; + } + } + + return null; + } + + string GetIndentationString(ITextEditor editor) + { + // Get current indentation option values + int indentationSize = editor.Options.IndentationSize; + bool convertTabsToSpaces = editor.Options.ConvertTabsToSpaces; + var container = GetOptionsContainerForEditor(editor); + if (container != null) { + int? effectiveIndentationSize = container.GetEffectiveIndentationSize(); + if (effectiveIndentationSize.HasValue) + indentationSize = effectiveIndentationSize.Value; + bool? effectiveConvertTabsToSpaces = container.GetEffectiveConvertTabsToSpaces(); + if (effectiveConvertTabsToSpaces.HasValue) + convertTabsToSpaces = effectiveConvertTabsToSpaces.Value; + } + + return ICSharpCode.AvalonEdit.TextEditorOptions.GetIndentationString(1, indentationSize, convertTabsToSpaces); + } + /* NR indent engine (temporarily?) disabled as per #447 static void IndentSingleLine(CacheIndentEngine engine, IDocument document, IDocumentLine line) { - engine.Update(line.EndOffset); - if (engine.NeedsReindent) { - var indentation = TextUtilities.GetWhitespaceAfter(document, line.Offset); - // replacing the indentation in two steps is necessary to make the caret move accordingly. - document.Replace(indentation.Offset, indentation.Length, ""); - document.Replace(indentation.Offset, 0, engine.ThisLineIndent); - engine.ResetEngineToPosition(line.Offset); - } + engine.Update(line.EndOffset); + if (engine.NeedsReindent) { + var indentation = TextUtilities.GetWhitespaceAfter(document, line.Offset); + // replacing the indentation in two steps is necessary to make the caret move accordingly. + document.Replace(indentation.Offset, indentation.Length, ""); + document.Replace(indentation.Offset, 0, engine.ThisLineIndent); + engine.ResetEngineToPosition(line.Offset); + } } static CacheIndentEngine CreateIndentEngine(IDocument document, TextEditorOptions options) { - IProject currentProject = null; - var projectService = SD.GetService(); - if (projectService != null) { - currentProject = projectService.FindProjectContainingFile(new FileName(document.FileName)); - } - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(currentProject); - var engine = new CSharpIndentEngine(document, options, formattingOptions.OptionsContainer.GetEffectiveOptions()); - return new CacheIndentEngine(engine); + IProject currentProject = null; + var projectService = SD.GetService(); + if (projectService != null) { + currentProject = projectService.FindProjectContainingFile(new FileName(document.FileName)); + } + var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(currentProject); + var engine = new CSharpIndentEngine(document, options, formattingOptions.OptionsContainer.GetEffectiveOptions()); + return new CacheIndentEngine(engine); } */ #endregion @@ -302,11 +333,11 @@ namespace CSharpBinding.FormattingStrategy { if ((offset > textArea.Document.TextLength) || ((offset + length) > textArea.Document.TextLength)) return false; - if (respectAutoFormattingSetting && !CSharpFormattingOptionsPersistence.AutoFormatting) + if (respectAutoFormattingSetting && !CSharpFormattingPolicies.AutoFormatting) return false; using (textArea.Document.OpenUndoGroup()) { - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(SD.ProjectService.CurrentProject); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(SD.ProjectService.CurrentProject); try { CSharpFormatterHelper.Format(textArea, offset, length, formattingOptions.OptionsContainer); } catch (Exception) { diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/FormattingOptionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/FormattingOptionBinding.cs index 9caa50b055..b36677c142 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/FormattingOptionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/FormattingOptionBinding.cs @@ -22,6 +22,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using ICSharpCode.NRefactory.CSharp; +using CSharpBinding.OptionPanels; namespace CSharpBinding.FormattingStrategy { @@ -32,11 +33,8 @@ namespace CSharpBinding.FormattingStrategy { public static readonly DependencyProperty ContainerProperty = DependencyProperty.RegisterAttached("Container", typeof(CSharpFormattingOptionsContainer), - typeof(FormattingOptionBinding), - new FrameworkPropertyMetadata()); - public static readonly DependencyProperty OptionProperty = - DependencyProperty.RegisterAttached("Option", typeof(string), typeof(FormattingOptionBinding), - new FrameworkPropertyMetadata(OnOptionPropertyChanged)); + typeof(FormattingOptionBinding), + new FrameworkPropertyMetadata((o, e) => UpdateOptionBinding(o))); public static CSharpFormattingOptionsContainer GetContainer(Selector element) { @@ -48,21 +46,26 @@ namespace CSharpBinding.FormattingStrategy element.SetValue(ContainerProperty, container); } - public static string GetOption(Selector element) + public static readonly DependencyProperty FormattingOptionProperty = + DependencyProperty.RegisterAttached("FormattingOption", typeof(FormattingOption), + typeof(FormattingOptionBinding), + new FrameworkPropertyMetadata((o, e) => UpdateOptionBinding(o))); + + public static FormattingOption GetFormattingOption(Selector element) { - return (string) element.GetValue(OptionProperty); + return (FormattingOption) element.GetValue(FormattingOptionProperty); } - public static void SetOption(Selector element, string option) + public static void SetFormattingOption(Selector element, FormattingOption container) { - element.SetValue(OptionProperty, option); + element.SetValue(FormattingOptionProperty, container); } - static void OnOptionPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + static void UpdateOptionBinding(DependencyObject o) { - string option = e.NewValue as string; ComboBox comboBox = o as ComboBox; CSharpFormattingOptionsContainer container = GetContainer(comboBox); + FormattingOption option = GetFormattingOption(comboBox); if ((option != null) && (comboBox != null) && (container != null)) { if (container != null) { if (container.Parent != null) { @@ -72,17 +75,24 @@ namespace CSharpBinding.FormattingStrategy Tag = null }); comboBox.SelectedIndex = 0; + } else if (option.AlwaysAllowDefault) { + // Also add "default" entry, but without changeable text by container + comboBox.Items.Add(new ComboBoxItem { + Content = "(default)", + Tag = null + }); + comboBox.SelectedIndex = 0; } - Type optionType = container.GetOptionType(option); + Type optionType = container.GetOptionType(option.Option); FillComboValues(comboBox, optionType); - UpdateComboBoxValue(container, option, comboBox); + UpdateComboBoxValue(container, option.Option, comboBox); comboBox.SelectionChanged += ComboBox_SelectionChanged; container.PropertyChanged += (sender, eventArgs) => { - if ((eventArgs.PropertyName == null) || (eventArgs.PropertyName == option)) - UpdateComboBoxValue(container, option, comboBox); + if ((eventArgs.PropertyName == null) || (eventArgs.PropertyName == option.Option)) + UpdateComboBoxValue(container, option.Option, comboBox); }; } } @@ -98,13 +108,13 @@ namespace CSharpBinding.FormattingStrategy { ComboBox comboBox = sender as ComboBox; if (comboBox != null) { - string option = GetOption(comboBox); + FormattingOption option = GetFormattingOption(comboBox); CSharpFormattingOptionsContainer container = GetContainer(comboBox); if ((container != null) && (option != null)) { ComboBoxItem selectedItem = comboBox.SelectedItem as ComboBoxItem; if (selectedItem != null) { // Set option to appropriate value - container.SetOption(option, selectedItem.Tag); + container.SetOption(option.Option, selectedItem.Tag); } } } @@ -140,11 +150,10 @@ namespace CSharpBinding.FormattingStrategy static void FillIntComboValues(ComboBox comboBox) { - comboBox.Items.Add(new ComboBoxItem { Content = "0", Tag = 0 }); - comboBox.Items.Add(new ComboBoxItem { Content = "1", Tag = 1 }); - comboBox.Items.Add(new ComboBoxItem { Content = "2", Tag = 2 }); - comboBox.Items.Add(new ComboBoxItem { Content = "3", Tag = 3 }); - comboBox.Items.Add(new ComboBoxItem { Content = "4", Tag = 4 }); + for (int i = 0; i < 11; i++) + { + comboBox.Items.Add(new ComboBoxItem { Content = i.ToString(), Tag = i }); + } } static void FillBraceStyleComboValues(ComboBox comboBox) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs index f10b094d8e..5045d6fc8f 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs @@ -155,7 +155,7 @@ namespace CSharpBinding.FormsDesigner IDocument document = context.GetDocument(fileNameObj); var ctx = SDRefactoringContext.Create(fileNameObj, document); - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(compilation.GetProject()); script = new DocumentScript(document, formattingOptions.OptionsContainer.GetEffectiveOptions(), new TextEditorOptions()); scripts.Add(fileNameObj, script); return script; diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml index 259702aa7d..4db4b5233e 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml @@ -274,13 +274,13 @@ - + + format:FormattingOptionBinding.FormattingOption="{Binding}" /> + + + + + + + + + + + + + DockPanel.Dock="Top" Margin="0,5,0,0"> diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml.cs index cd2c4cdf70..b1a6bba1ac 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml.cs @@ -29,21 +29,13 @@ using CSharpBinding.FormattingStrategy; namespace CSharpBinding.OptionPanels { - /// - /// Marker interface for group or option container. - /// It doesn't need to have any members. - /// - internal interface IFormattingItemContainer - { - } - /// /// Represents a container item for other container items in formatting editor list /// [ContentProperty("Children")] - internal class FormattingGroupContainer : DependencyObject, IFormattingItemContainer + internal class FormattingGroupContainer : DependencyObject { - readonly ObservableCollection children = new ObservableCollection(); + readonly ObservableCollection children = new ObservableCollection(); public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(FormattingGroupContainer), @@ -54,7 +46,7 @@ namespace CSharpBinding.OptionPanels set { SetValue(TextProperty, value); } } - public ObservableCollection Children + public ObservableCollection Children { get { return children; @@ -66,7 +58,7 @@ namespace CSharpBinding.OptionPanels /// Represents a container for formatting options. /// [ContentProperty("Children")] - internal class FormattingOptionContainer : DependencyObject, IFormattingItemContainer + internal class FormattingOptionContainer : DependencyObject { readonly ObservableCollection children = new ObservableCollection(); @@ -91,11 +83,26 @@ namespace CSharpBinding.OptionPanels set { SetValue(TextProperty, value); } } +// public static readonly DependencyProperty AlwaysAllowDefaultProperty = +// DependencyProperty.Register("AlwaysAllowDefault", typeof(bool), typeof(FormattingOption), +// new FrameworkPropertyMetadata()); +// +// public bool AlwaysAllowDefault { +// get { return (bool)GetValue(AlwaysAllowDefaultProperty); } +// set { SetValue(AlwaysAllowDefaultProperty, value); } +// } + public string Option { get; set; } + + public bool AlwaysAllowDefault + { + get; + set; + } } /// @@ -133,6 +140,15 @@ namespace CSharpBinding.OptionPanels set { SetValue(AllowPresetsProperty, value); } } + public static readonly DependencyProperty OverrideGlobalIndentationProperty = + DependencyProperty.Register("OverrideGlobalIndentation", typeof(bool), typeof(CSharpFormattingEditor), + new FrameworkPropertyMetadata()); + + public bool OverrideGlobalIndentation { + get { return (bool)GetValue(OverrideGlobalIndentationProperty); } + set { SetValue(OverrideGlobalIndentationProperty, value); } + } + static void OnOptionsContainerPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var editor = o as CSharpFormattingEditor; @@ -197,7 +213,7 @@ namespace CSharpBinding.OptionPanels } } - public ObservableCollection RootChildren + public ObservableCollection RootChildren { get { // rootEntries object is only the root container, its children should be shown directly diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml index 4620821994..05e73ee15e 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml @@ -19,7 +19,7 @@ diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs index e358b6c90c..91cd559fc6 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs @@ -40,7 +40,7 @@ namespace CSharpBinding.OptionPanels internal class CSharpGlobalFormattingOptionPanel : CSharpFormattingOptionPanel { public CSharpGlobalFormattingOptionPanel() - : base(CSharpFormattingOptionsPersistence.GlobalOptions, true) + : base(CSharpFormattingPolicies.Instance.GlobalOptions, true, false) { autoFormattingCheckBox.Visibility = Visibility.Visible; } @@ -52,7 +52,7 @@ namespace CSharpBinding.OptionPanels internal class CSharpSolutionFormattingOptionPanel : CSharpFormattingOptionPanel { public CSharpSolutionFormattingOptionPanel() - : base(CSharpFormattingOptionsPersistence.SolutionOptions, true) + : base(CSharpFormattingPolicies.Instance.SolutionOptions, true, true) { autoFormattingCheckBox.Visibility = Visibility.Collapsed; } @@ -63,25 +63,26 @@ namespace CSharpBinding.OptionPanels /// internal partial class CSharpFormattingOptionPanel : OptionPanel { - readonly CSharpFormattingOptionsPersistence persistenceHelper; + readonly CSharpFormattingPolicy formattingPolicy; bool isDirty; - public CSharpFormattingOptionPanel(CSharpFormattingOptionsPersistence persistenceHelper, bool allowPresets) + public CSharpFormattingOptionPanel(CSharpFormattingPolicy persistenceHelper, bool allowPresets, bool overrideGlobalIndentation) { if (persistenceHelper == null) throw new ArgumentNullException("persistenceHelper"); - this.persistenceHelper = persistenceHelper; + this.formattingPolicy = persistenceHelper; this.isDirty = false; InitializeComponent(); formattingEditor.AllowPresets = allowPresets; + formattingEditor.OverrideGlobalIndentation = overrideGlobalIndentation; } public override void LoadOptions() { base.LoadOptions(); - formattingEditor.OptionsContainer = persistenceHelper.StartEditing(); + formattingEditor.OptionsContainer = formattingPolicy.StartEditing(); formattingEditor.OptionsContainer.PropertyChanged += ContainerPropertyChanged; } @@ -94,7 +95,7 @@ namespace CSharpBinding.OptionPanels { // Only save container, if some option really has changed formattingEditor.OptionsContainer.PropertyChanged -= ContainerPropertyChanged; - return (!isDirty || persistenceHelper.Save()) && base.SaveOptions(); + return (!isDirty || formattingPolicy.Save()) && base.SaveOptions(); } } } \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml.cs index d3ca858d81..e12bdeaa8d 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml.cs @@ -35,7 +35,7 @@ namespace CSharpBinding.OptionPanels /// internal partial class CSharpProjectFormattingOptionPanel : ProjectOptionPanel { - CSharpFormattingOptionsPersistence persistenceHelper; + CSharpFormattingPolicy formattingPolicy; public CSharpProjectFormattingOptionPanel() { @@ -45,18 +45,19 @@ namespace CSharpBinding.OptionPanels protected override void Load(ICSharpCode.SharpDevelop.Project.MSBuildBasedProject project, string configuration, string platform) { base.Load(project, configuration, platform); - if (persistenceHelper != null) { - persistenceHelper.OptionsContainer.PropertyChanged -= ContainerPropertyChanged; + if (formattingPolicy != null) { + formattingPolicy.OptionsContainer.PropertyChanged -= ContainerPropertyChanged; } - persistenceHelper = CSharpFormattingOptionsPersistence.GetProjectOptions(project); - formattingEditor.OptionsContainer = persistenceHelper.OptionsContainer; + formattingPolicy = CSharpFormattingPolicies.Instance.GetProjectOptions(project); + formattingEditor.OptionsContainer = formattingPolicy.OptionsContainer; formattingEditor.AllowPresets = true; - persistenceHelper.OptionsContainer.PropertyChanged += ContainerPropertyChanged; + formattingEditor.OverrideGlobalIndentation = true; + formattingPolicy.OptionsContainer.PropertyChanged += ContainerPropertyChanged; } protected override bool Save(ICSharpCode.SharpDevelop.Project.MSBuildBasedProject project, string configuration, string platform) { - bool success = (persistenceHelper != null) && persistenceHelper.Save(); + bool success = (formattingPolicy != null) && formattingPolicy.Save(); return base.Save(project, configuration, platform) && success; } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs index a341e62b93..9902fef703 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs @@ -86,7 +86,10 @@ namespace CSharpBinding.Refactoring var node = context.RootNode.GetNodeAt(last.Region.Begin); var resolver = context.GetResolverStateAfter(node); var builder = new TypeSystemAstBuilder(resolver); - var delegateDecl = builder.ConvertEntity(eventDefinition.ReturnType.GetDefinition()) as DelegateDeclaration; + var invokeMethod = eventDefinition.ReturnType.GetDelegateInvokeMethod(); + if (invokeMethod == null) return; + var importedMethod = resolver.Compilation.Import(invokeMethod); + var delegateDecl = builder.ConvertEntity(importedMethod) as MethodDeclaration; if (delegateDecl == null) return; var throwStmt = new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException"))); var decl = new MethodDeclaration() { @@ -96,7 +99,7 @@ namespace CSharpBinding.Refactoring throwStmt } }; - var param = delegateDecl.Parameters.Select(p => p.Clone()).OfType().ToArray(); + var param = delegateDecl.Parameters.Select(p => p.Clone()).ToArray(); decl.Parameters.AddRange(param); using (Script script = context.StartScript()) { diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs index 2ff47fa0b7..973dbd97c7 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs @@ -171,7 +171,7 @@ namespace CSharpBinding.Refactoring using (StringWriter textWriter = new StringWriter(pList)) { // Output parameter list as string - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(refactoringContext.Compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(refactoringContext.Compilation.GetProject()); CSharpOutputVisitor outputVisitor = new CSharpOutputVisitor(textWriter, formattingOptions.OptionsContainer.GetEffectiveOptions()); for (int i = 0; i < parameters.Count; i++) { if (i > 0) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/MoveTypeToFileContextAction.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/MoveTypeToFileContextAction.cs index 6e42276226..014ea3a7cc 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/MoveTypeToFileContextAction.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/MoveTypeToFileContextAction.cs @@ -109,7 +109,7 @@ namespace CSharpBinding.Refactoring || ch is UsingAliasDeclaration || ch is ExternAliasDeclaration); StringBuilder newCode = new StringBuilder(header); - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(compilation.GetProject()); CSharpOutputVisitor visitor = new CSharpOutputVisitor(new StringWriter(newCode), formattingOptions.OptionsContainer.GetEffectiveOptions()); foreach (var topLevelUsing in topLevelUsings) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs index 134f7fc14a..1fa3af1f23 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs @@ -119,13 +119,16 @@ namespace CSharpBinding.Refactoring public Script StartScript() { - var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(resolver.Compilation.GetProject()); + var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(resolver.Compilation.GetProject()); if (editor != null) return new EditorScript(editor, this, formattingOptions.OptionsContainer.GetEffectiveOptions()); else if (document == null || document is ReadOnlyDocument) throw new InvalidOperationException("Cannot start a script in a read-only context"); - else - return new DocumentScript(document, formattingOptions.OptionsContainer.GetEffectiveOptions(), this.TextEditorOptions); + else { + var textEditorOptions = this.TextEditorOptions; + formattingOptions.OptionsContainer.CustomizeEditorOptions(textEditorOptions); + return new DocumentScript(document, formattingOptions.OptionsContainer.GetEffectiveOptions(), textEditorOptions); + } } public IDocument Document { diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs index 0873442d6d..e747ab6177 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs @@ -38,12 +38,14 @@ namespace ICSharpCode.AvalonEdit.AddIn sealed class CodeEditorAdapter : CodeCompletionEditorAdapter { readonly CodeEditor codeEditor; + ITextEditorOptions options; public CodeEditorAdapter(CodeEditor codeEditor, CodeEditorView textEditor) : base(textEditor) { if (codeEditor == null) throw new ArgumentNullException("codeEditor"); this.codeEditor = codeEditor; + options = CodeEditorOptions.Instance; } public override FileName FileName { @@ -78,9 +80,14 @@ namespace ICSharpCode.AvalonEdit.AddIn internal void DetachExtensions() { if (extensions != null) { - foreach (var extension in extensions) - extension.Detach(); + // Detach extensions in reverse order + for (int i = extensions.Count - 1; i >= 0; i--) { + extensions[i].Detach(); + } } + + // Switch to global options, if no specific options service is registered + options = this.GetService() ?? CodeEditorOptions.Instance; } @@ -90,6 +97,13 @@ namespace ICSharpCode.AvalonEdit.AddIn foreach (var extension in extensions) extension.Attach(this); } + + // If we have any registered ITextEditorOptions service now, use it, otherwise global options + options = this.GetService() ?? CodeEditorOptions.Instance; + } + + public override ITextEditorOptions Options { + get { return options; } } sealed class OptionControlledIndentationStrategy : IndentationStrategyAdapter diff --git a/src/AddIns/DisplayBindings/HexEditor/Project/Src/Editor.cs b/src/AddIns/DisplayBindings/HexEditor/Project/Src/Editor.cs index c88ff715ba..fab5025825 100644 --- a/src/AddIns/DisplayBindings/HexEditor/Project/Src/Editor.cs +++ b/src/AddIns/DisplayBindings/HexEditor/Project/Src/Editor.cs @@ -1413,6 +1413,14 @@ namespace HexEditor this.Delete(); } break; + // Ctrl-Y is pressed -> redo + case 89: + Redo(); + break; + // Ctrl-Z is pressed -> undo + case 90: + Undo(); + break; } break; } diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyParser.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyParser.cs index 12d74a23aa..de246b0a27 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyParser.cs +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyParser.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Text; using System.Threading; using ICSharpCode.Core; using ICSharpCode.NRefactory; @@ -82,7 +83,32 @@ namespace ICSharpCode.ILSpyAddIn public ResolveResult ResolveSnippet(ParseInformation parseInfo, TextLocation location, string codeSnippet, ICompilation compilation, CancellationToken cancellationToken) { - return null; + var decompiledParseInfo = parseInfo as ILSpyFullParseInformation; + if (decompiledParseInfo == null) + throw new ArgumentException("ParseInfo does not have SyntaxTree"); + CSharpAstResolver contextResolver = new CSharpAstResolver(compilation, decompiledParseInfo.SyntaxTree, null); + var node = decompiledParseInfo.SyntaxTree.GetNodeAt(location); + CSharpResolver context; + if (node != null) + context = contextResolver.GetResolverStateAfter(node, cancellationToken); + else + context = new CSharpResolver(compilation); + CSharpParser parser = new CSharpParser(); + var expr = parser.ParseExpression(codeSnippet); + if (parser.HasErrors) + return new ErrorResolveResult(SpecialType.UnknownType, PrintErrorsAsString(parser.Errors), TextLocation.Empty); + CSharpAstResolver snippetResolver = new CSharpAstResolver(context, expr); + return snippetResolver.Resolve(expr, cancellationToken); + } + + string PrintErrorsAsString(IEnumerable errors) + { + StringBuilder builder = new StringBuilder(); + + foreach (var error in errors) + builder.AppendLine(error.Message); + + return builder.ToString(); } public void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action callback, CancellationToken cancellationToken) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs index a113913de2..f48ca4ab07 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs @@ -189,7 +189,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions yield return designItem; if (designItem.ContentProperty.Value != null) { yield return designItem.ContentProperty.Value; - designItem = designItem.ContentProperty.Value; + designItem = ExtendedItem; //set designitem back to current control after yield } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs index a32806a5e9..84bcd70377 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs @@ -668,6 +668,11 @@ namespace ICSharpCode.WpfDesign.Tests.Designer } public void AddNativeTypeAsResource(object component, string expectedXamlValue) + { + AddTypeAsResource(component, expectedXamlValue, "Controls0:", new string[] { "xmlns:Controls0=\"clr-namespace:System;assembly=mscorlib\""} ); + } + + public void AddTypeAsResource(object component, string expectedXamlValue, string typePrefix, String[] additionalXmlns) { DesignItem textBlock = CreateCanvasContext(""); DesignItem canvas = textBlock.Parent; @@ -687,11 +692,11 @@ namespace ICSharpCode.WpfDesign.Tests.Designer string typeName = component.GetType().Name; string expectedXaml = "\n" + - " " + expectedXamlValue + "\n" + + " <" + typePrefix + typeName + " x:Key=\"res1\">" + expectedXamlValue + "\n" + "\n" + ""; - AssertCanvasDesignerOutput(expectedXaml, textBlock.Context, "xmlns:Controls0=\"clr-namespace:System;assembly=mscorlib\""); + AssertCanvasDesignerOutput(expectedXaml, textBlock.Context, additionalXmlns); AssertLog(""); } @@ -736,6 +741,18 @@ namespace ICSharpCode.WpfDesign.Tests.Designer const int i = 123; AddNativeTypeAsResource(i, "123"); } + + [Test] + public void AddWpfEnumAsResource() + { + AddTypeAsResource(VerticalAlignment.Center, "Center", "", new string[0]); + } + + [Test] + public void AddCustomEnumAsResource() + { + AddTypeAsResource(MyEnum.One, "One", "t:", new string[0]); + } } public class MyMultiConverter : IMultiValueConverter @@ -760,4 +777,9 @@ namespace ICSharpCode.WpfDesign.Tests.Designer set { stringProp = value; } } } + + public enum MyEnum + { + One, Two + } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs index 48ee85ec63..b517eea9f0 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs @@ -275,7 +275,7 @@ namespace ICSharpCode.WpfDesign.XamlDom bool IsNativeType(object instance) { - return instance.GetType().Assembly == typeof(String).Assembly; + return instance.GetType().Assembly == typeof(String).Assembly || instance.GetType().IsEnum; } } } diff --git a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/InstallPackageCmdlet.cs b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/InstallPackageCmdlet.cs index ac57cae245..93dab21b5e 100644 --- a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/InstallPackageCmdlet.cs +++ b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/InstallPackageCmdlet.cs @@ -66,7 +66,9 @@ namespace ICSharpCode.PackageManagement.Cmdlets { ThrowErrorIfProjectNotOpen(); using (IConsoleHostFileConflictResolver resolver = CreateFileConflictResolver()) { - InstallPackage(); + using (IDisposable logger = ConsoleHost.CreateLogger(this)) { + InstallPackage(); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/PackageManagementCmdlet.cs b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/PackageManagementCmdlet.cs index 8681445d15..32eba1779e 100644 --- a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/PackageManagementCmdlet.cs +++ b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/PackageManagementCmdlet.cs @@ -25,7 +25,7 @@ using NuGet; namespace ICSharpCode.PackageManagement.Cmdlets { - public abstract class PackageManagementCmdlet : PSCmdlet, ITerminatingCmdlet, IPackageScriptSession, IPackageScriptRunner + public abstract class PackageManagementCmdlet : PSCmdlet, ITerminatingCmdlet, IPackageScriptSession, IPackageScriptRunner, ICmdletLogger { IPackageManagementConsoleHost consoleHost; ICmdletTerminatingError terminatingError; @@ -114,5 +114,10 @@ namespace ICSharpCode.PackageManagement.Cmdlets script.Run(this); } } + + void ICmdletLogger.WriteLine(string message) + { + Host.UI.WriteLine(message); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UninstallPackageCmdlet.cs b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UninstallPackageCmdlet.cs index 513cfc8be7..1584992b0e 100644 --- a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UninstallPackageCmdlet.cs +++ b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UninstallPackageCmdlet.cs @@ -59,7 +59,9 @@ namespace ICSharpCode.PackageManagement.Cmdlets protected override void ProcessRecord() { ThrowErrorIfProjectNotOpen(); - UninstallPackage(); + using (IDisposable logger = ConsoleHost.CreateLogger(this)) { + UninstallPackage(); + } } void UninstallPackage() diff --git a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UpdatePackageCmdlet.cs b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UpdatePackageCmdlet.cs index 91aeb5abc6..4c920e79ef 100644 --- a/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UpdatePackageCmdlet.cs +++ b/src/AddIns/Misc/PackageManagement/Cmdlets/Project/Src/UpdatePackageCmdlet.cs @@ -73,7 +73,9 @@ namespace ICSharpCode.PackageManagement.Cmdlets { ThrowErrorIfProjectNotOpen(); using (IConsoleHostFileConflictResolver resolver = CreateFileConflictResolver()) { - RunUpdate(); + using (IDisposable logger = ConsoleHost.CreateLogger(this)) { + RunUpdate(); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/InstallPackageCmdletTests.cs b/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/InstallPackageCmdletTests.cs index dfacfdab29..8dbbe66d67 100644 --- a/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/InstallPackageCmdletTests.cs +++ b/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/InstallPackageCmdletTests.cs @@ -321,5 +321,19 @@ namespace PackageManagement.Cmdlets.Tests operationAwareRepository.AssertOperationWasStartedAndDisposed(RepositoryOperationNames.Install, "Test"); } + + [Test] + public void ProcessRecord_PackageIdSpecified_ConsoleHostLoggerIsDisposed() + { + CreateCmdletWithoutActiveProject(); + AddDefaultProjectToConsoleHost(); + AddPackageSourceToConsoleHost(); + SetIdParameter("Test"); + + RunCmdlet(); + + fakeConsoleHost.AssertLoggerIsDisposed(); + Assert.AreEqual(cmdlet, fakeConsoleHost.CmdletLoggerUsedToCreateLogger); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UninstallPackageCmdletTests.cs b/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UninstallPackageCmdletTests.cs index 840d132397..2ff8092318 100644 --- a/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UninstallPackageCmdletTests.cs +++ b/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UninstallPackageCmdletTests.cs @@ -237,8 +237,22 @@ namespace PackageManagement.Cmdlets.Tests RunCmdlet(); IPackageScriptRunner scriptRunner = uninstallPackageAction.PackageScriptRunner; - + Assert.AreEqual(cmdlet, scriptRunner); } + + [Test] + public void ProcessRecord_PackageIdSpecified_ConsoleHostLoggerIsDisposed() + { + CreateCmdletWithoutActiveProject(); + AddDefaultProjectToConsoleHost(); + AddPackageSourceToConsoleHost(); + SetIdParameter("Test"); + + RunCmdlet(); + + fakeConsoleHost.AssertLoggerIsDisposed(); + Assert.AreEqual(cmdlet, fakeConsoleHost.CmdletLoggerUsedToCreateLogger); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UpdatePackageCmdletTests.cs b/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UpdatePackageCmdletTests.cs index 59cdc7d7fc..e683100c35 100644 --- a/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UpdatePackageCmdletTests.cs +++ b/src/AddIns/Misc/PackageManagement/Cmdlets/Test/Src/UpdatePackageCmdletTests.cs @@ -832,5 +832,19 @@ namespace PackageManagement.Cmdlets.Tests operationAwareRepository.AssertOperationWasStartedAndDisposed(RepositoryOperationNames.Update, "Test2"); } + + [Test] + public void ProcessRecord_PackageIdSpecified_ConsoleHostLoggerIsDisposed() + { + CreateCmdletWithoutActiveProject(); + AddDefaultProjectToConsoleHost(); + AddPackageSourceToConsoleHost(); + SetIdParameter("Test"); + + RunCmdlet(); + + fakeConsoleHost.AssertLoggerIsDisposed(); + Assert.AreEqual(cmdlet, fakeConsoleHost.CmdletLoggerUsedToCreateLogger); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj index cdb4f112ec..7875954521 100644 --- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj +++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj @@ -58,6 +58,7 @@ 3.5 + 4.0 @@ -243,6 +244,7 @@ + @@ -250,6 +252,7 @@ + diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/RestorePackagesCommand.cs b/src/AddIns/Misc/PackageManagement/Project/Src/RestorePackagesCommand.cs index 76a175950d..5020d26206 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/RestorePackagesCommand.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/RestorePackagesCommand.cs @@ -18,6 +18,9 @@ using System; using System.IO; +using System.Linq; +using System.Threading.Tasks; + using ICSharpCode.Core; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Gui; @@ -71,7 +74,33 @@ namespace ICSharpCode.PackageManagement var runner = new ProcessRunner(); runner.WorkingDirectory = Path.GetDirectoryName(solution.FileName); - runner.RunInOutputPadAsync(outputMessagesView.OutputCategory, commandLine.Command, commandLine.Arguments).FireAndForget(); + runner.RunInOutputPadAsync(outputMessagesView.OutputCategory, commandLine.Command, commandLine.Arguments) + .ContinueWith(task => OnNuGetPackageRestoreComplete(task)); + } + + void OnNuGetPackageRestoreComplete(Task task) + { + if (task.Exception != null) { + LoggingService.Debug(task.Exception.ToString()); + outputMessagesView.AppendLine(task.Exception.Message); + } else { + ForceGenerationOfRepositoriesConfigFile(); + } + } + + /// + /// Create a Package Manager for each project to force a new repositories.config file + /// to be generated with references to all projects that have NuGet packages. + /// + void ForceGenerationOfRepositoriesConfigFile() + { + try { + var repository = PackageManagementServices.RegisteredPackageRepositories.CreateAggregateRepository(); + var projects = solution.GetProjects(repository).ToList(); + } catch (Exception ex) { + LoggingService.Debug(ex.ToString()); + outputMessagesView.AppendLine(ex.Message); + } } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/ICmdletLogger.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/ICmdletLogger.cs new file mode 100644 index 0000000000..f557d7c7be --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/ICmdletLogger.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Management.Automation; + +namespace ICSharpCode.PackageManagement.Scripting +{ + public interface ICmdletLogger + { + void WriteError(ErrorRecord error); + void WriteLine(string message); + void WriteVerbose(string message); + void WriteWarning(string message); + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageManagementConsoleHost.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageManagementConsoleHost.cs index 0695932eeb..d4d4c3f7ca 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageManagementConsoleHost.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/IPackageManagementConsoleHost.cs @@ -42,6 +42,7 @@ namespace ICSharpCode.PackageManagement.Scripting void SetDefaultRunspace(); IConsoleHostFileConflictResolver CreateFileConflictResolver(FileConflictAction fileConflictAction); + IDisposable CreateLogger(ICmdletLogger logger); IPackageManagementProject GetProject(string packageSource, string projectName); IPackageManagementProject GetProject(IPackageRepository sourceRepository, string projectName); diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageManagementConsoleHost.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageManagementConsoleHost.cs index 6fec26b929..5742c26bf7 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageManagementConsoleHost.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageManagementConsoleHost.cs @@ -295,5 +295,10 @@ namespace ICSharpCode.PackageManagement.Scripting { return new ConsoleHostFileConflictResolver(packageEvents, fileConflictAction); } + + public IDisposable CreateLogger(ICmdletLogger logger) + { + return new PackageManagementConsoleHostLogger(logger, packageEvents); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageManagementConsoleHostLogger.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageManagementConsoleHostLogger.cs new file mode 100644 index 0000000000..dc07b3357b --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PackageManagementConsoleHostLogger.cs @@ -0,0 +1,75 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Management.Automation; +using NuGet; + +namespace ICSharpCode.PackageManagement.Scripting +{ + public class PackageManagementConsoleHostLogger : IDisposable + { + ICmdletLogger logger; + IPackageManagementEvents packageEvents; + + public PackageManagementConsoleHostLogger(ICmdletLogger logger, IPackageManagementEvents packageEvents) + { + this.logger = logger; + this.packageEvents = packageEvents; + + packageEvents.PackageOperationMessageLogged += PackageOperationMessageLogged; + } + + void PackageOperationMessageLogged(object sender, PackageOperationMessageLoggedEventArgs e) + { + Log(e.Message.Level, e.Message.ToString()); + } + + void Log(MessageLevel level, string message) + { + switch (level) { + case MessageLevel.Debug: + logger.WriteVerbose(message); + break; + case MessageLevel.Warning: + logger.WriteWarning(message); + break; + case MessageLevel.Error: + logger.WriteError(CreateErrorRecord(message)); + break; + default: + logger.WriteLine(message); + break; + } + } + + ErrorRecord CreateErrorRecord(string message) + { + return new ErrorRecord( + new ApplicationException(message), + "PackageManagementError", + ErrorCategory.NotSpecified, + null); + } + + public void Dispose() + { + packageEvents.PackageOperationMessageLogged -= PackageOperationMessageLogged; + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PowerShellMissingConsoleHost.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PowerShellMissingConsoleHost.cs index 45beafca8d..050dca3086 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PowerShellMissingConsoleHost.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Scripting/PowerShellMissingConsoleHost.cs @@ -100,5 +100,10 @@ namespace ICSharpCode.PackageManagement.Scripting { return null; } + + public IDisposable CreateLogger(ICmdletLogger logger) + { + return null; + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj index fb3cc11e72..0a2c80e407 100644 --- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj +++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj @@ -108,6 +108,7 @@ + @@ -194,6 +195,7 @@ + diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeCmdletLogger.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeCmdletLogger.cs new file mode 100644 index 0000000000..bf87c211c9 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeCmdletLogger.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Management.Automation; +using ICSharpCode.PackageManagement.Scripting; + +namespace PackageManagement.Tests.Helpers +{ + public class FakeCmdletLogger : ICmdletLogger + { + public ErrorRecord ErrorRecordLogged; + + public void WriteError(ErrorRecord error) + { + ErrorRecordLogged = error; + } + + public string LineLogged; + + public void WriteLine(string message) + { + LineLogged = message; + } + + public string VerboseMessageLogged; + + public void WriteVerbose(string message) + { + VerboseMessageLogged = message; + } + + public string WarningMessageLogged; + + public void WriteWarning(string message) + { + WarningMessageLogged = message; + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageManagementConsoleHost.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageManagementConsoleHost.cs index caad95b80b..db0f583351 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageManagementConsoleHost.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageManagementConsoleHost.cs @@ -169,5 +169,21 @@ namespace PackageManagement.Tests.Helpers { FakeFileConflictResolver.AssertWasCalled(resolver => resolver.Dispose()); } + + public IDisposable FakeConsoleHostLogger = + MockRepository.GenerateStub(); + + public void AssertLoggerIsDisposed() + { + FakeConsoleHostLogger.AssertWasCalled(logger => logger.Dispose()); + } + + public ICmdletLogger CmdletLoggerUsedToCreateLogger; + + public IDisposable CreateLogger(ICmdletLogger logger) + { + CmdletLoggerUsedToCreateLogger = logger; + return FakeConsoleHostLogger; + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageManagementConsoleHostLoggerTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageManagementConsoleHostLoggerTests.cs new file mode 100644 index 0000000000..d1e6ad884f --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Scripting/PackageManagementConsoleHostLoggerTests.cs @@ -0,0 +1,85 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Management.Automation; +using ICSharpCode.PackageManagement; +using ICSharpCode.PackageManagement.Scripting; +using NuGet; +using NUnit.Framework; +using PackageManagement.Tests.Helpers; + +namespace PackageManagement.Tests.Scripting +{ + [TestFixture] + public class PackageManagementConsoleHostLoggerTests + { + FakeCmdletLogger cmdletLogger; + PackageManagementConsoleHostLogger consoleHostLogger; + PackageManagementEvents packageEvents; + + void CreateConsoleHostLogger() + { + cmdletLogger = new FakeCmdletLogger(); + packageEvents = new PackageManagementEvents(); + consoleHostLogger = new PackageManagementConsoleHostLogger(cmdletLogger, packageEvents); + } + + [Test] + public void OnPackageOperationMessageLogged_DebugMessage_WrittenAsVerboseMessageToCmdlet() + { + CreateConsoleHostLogger(); + + packageEvents.OnPackageOperationMessageLogged(MessageLevel.Debug, "test"); + + Assert.AreEqual("test", cmdletLogger.VerboseMessageLogged); + } + + [Test] + public void OnPackageOperationMessageLogged_WarningMessage_WrittenAsWarningMessageToCmdlet() + { + CreateConsoleHostLogger(); + + packageEvents.OnPackageOperationMessageLogged(MessageLevel.Warning, "test"); + + Assert.AreEqual("test", cmdletLogger.WarningMessageLogged); + } + + [Test] + public void OnPackageOperationMessageLogged_InfoMessage_WrittenAsLineToCmdlet() + { + CreateConsoleHostLogger(); + + packageEvents.OnPackageOperationMessageLogged(MessageLevel.Info, "test"); + + Assert.AreEqual("test", cmdletLogger.LineLogged); + } + + [Test] + public void OnPackageOperationMessageLogged_ErrorMessage_WrittenAsErrorRecordCmdlet() + { + CreateConsoleHostLogger(); + + packageEvents.OnPackageOperationMessageLogged(MessageLevel.Error, "test"); + + Assert.IsNotNull(cmdletLogger.ErrorRecordLogged); + Assert.AreEqual("test", cmdletLogger.ErrorRecordLogged.Exception.Message); + Assert.AreEqual(ErrorCategory.NotSpecified, cmdletLogger.ErrorRecordLogged.CategoryInfo.Category); + } + } +} diff --git a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/ReportingFactory.cs b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/ReportingFactory.cs index 7a41d44e24..9d72438667 100644 --- a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/ReportingFactory.cs +++ b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/ReportingFactory.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.Reporting } - internal ReportModel LoadReportModel (Stream stream) + internal IReportModel LoadReportModel (Stream stream) { var doc = new XmlDocument(); doc.Load(stream); @@ -69,7 +69,7 @@ namespace ICSharpCode.Reporting } - static ReportModel LoadModel(XmlDocument doc) + static IReportModel LoadModel(XmlDocument doc) { var loader = new ModelLoader(); object root = loader.Load(doc.DocumentElement); @@ -78,6 +78,6 @@ namespace ICSharpCode.Reporting } - public ReportModel ReportModel {get;private set;} + public IReportModel ReportModel {get;private set;} } } diff --git a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/FixedDocumentCreator.cs b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/FixedDocumentCreator.cs index ce9af88a6f..e0abb1b986 100644 --- a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/FixedDocumentCreator.cs +++ b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/FixedDocumentCreator.cs @@ -151,51 +151,58 @@ namespace ICSharpCode.Reporting.WpfReportViewer.Visitor FixedPage.SetTop(element,exportColumn.Location.Y); } - - static void SetContentAlignment(TextBlock textBlock,ExportText exportText) - { - //Vertical alignment not working - + public static Point CalculateAlignmentOffset (FormattedText formattedText, ExportText exportText) { + var offset = new Point(0,0); + double y = 0; + double x = 0; + var textLenDif = exportText.Size.Width - formattedText.Width; + var textHeightDif = exportText.Size.Height - formattedText.Height; + switch (exportText.ContentAlignment) { + // Top case System.Drawing.ContentAlignment.TopLeft: - textBlock.VerticalAlignment = VerticalAlignment.Top; - textBlock.TextAlignment = TextAlignment.Left; break; + case System.Drawing.ContentAlignment.TopCenter: - textBlock.VerticalAlignment = VerticalAlignment.Top; - textBlock.TextAlignment = TextAlignment.Center; + x = textLenDif / 2; break; + case System.Drawing.ContentAlignment.TopRight: - textBlock.VerticalAlignment = VerticalAlignment.Top; - textBlock.TextAlignment = TextAlignment.Right; + x = textLenDif; break; + // Middle case System.Drawing.ContentAlignment.MiddleLeft: - textBlock.VerticalAlignment = VerticalAlignment.Center; - textBlock.TextAlignment = TextAlignment.Left; + y = textHeightDif / 2; break; + case System.Drawing.ContentAlignment.MiddleCenter: - textBlock.VerticalAlignment = VerticalAlignment.Center; - textBlock.TextAlignment = TextAlignment.Center; + y = textHeightDif / 2; + x = textLenDif / 2; break; + case System.Drawing.ContentAlignment.MiddleRight: - textBlock.VerticalAlignment = VerticalAlignment.Center; - textBlock.TextAlignment = TextAlignment.Right; + x = textLenDif;; + y = textHeightDif / 2; break; + //Bottom case System.Drawing.ContentAlignment.BottomLeft: - textBlock.VerticalAlignment = VerticalAlignment.Bottom; - textBlock.TextAlignment = TextAlignment.Left; + x = 0; + y = textHeightDif; break; + case System.Drawing.ContentAlignment.BottomCenter: - textBlock.VerticalAlignment = VerticalAlignment.Bottom; - textBlock.TextAlignment = TextAlignment.Center; + x = textLenDif / 2; + y = textHeightDif; break; + case System.Drawing.ContentAlignment.BottomRight: - textBlock.VerticalAlignment = VerticalAlignment.Bottom; - textBlock.TextAlignment = TextAlignment.Right; + x = textLenDif; + y = textHeightDif; break; } + return new Point(x,y); } @@ -217,13 +224,13 @@ namespace ICSharpCode.Reporting.WpfReportViewer.Visitor } - public static Brush ConvertBrush(System.Drawing.Color color){ + public static Brush ConvertBrush(System.Drawing.Color color) + { var b = new BrushConverter(); - if (b.IsValid(color.Name)){ + if (b.IsValid(color.Name)) { return b.ConvertFromString(color.Name) as SolidColorBrush; - } else{ - return b.ConvertFromString("Black") as SolidColorBrush; } + return b.ConvertFromString("Black") as SolidColorBrush; } @@ -270,6 +277,7 @@ namespace ICSharpCode.Reporting.WpfReportViewer.Visitor return penLineCap; } + public static DashStyle DashStyle (IExportGraphics exportGraphics) { var dashStyle = DashStyles.Solid; diff --git a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/WpfVisitor.cs b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/WpfVisitor.cs index 5624ba60fd..70ed71dbdf 100644 --- a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/WpfVisitor.cs +++ b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Src/Wpf/Visitor/WpfVisitor.cs @@ -119,16 +119,27 @@ namespace ICSharpCode.Reporting.WpfReportViewer.Visitor public override void Visit(ExportText exportColumn){ - var ft = FixedDocumentCreator.CreateFormattedText((ExportText)exportColumn); + var formattedText = FixedDocumentCreator.CreateFormattedText((ExportText)exportColumn); var visual = new DrawingVisual(); + var location = new Point(exportColumn.Location.X,exportColumn.Location.Y); + using (var dc = visual.RenderOpen()){ if (ShouldSetBackcolor(exportColumn)) { dc.DrawRectangle(FixedDocumentCreator.ConvertBrush(exportColumn.BackColor), null, new Rect(location,new Size(exportColumn.Size.Width,exportColumn.Size.Height))); } - dc.DrawText(ft,location); + +// http://stackoverflow.com/questions/9264398/how-to-calculate-wpf-textblock-width-for-its-known-font-size-and-characters + +// if (exportColumn.ContentAlignment == System.Drawing.ContentAlignment.MiddleCenter) { +// location = new Point(location.X + (exportColumn.Size.Width - formattedText.Width) /2,location.Y + (exportColumn.Size.Height - formattedText.Height) / 2); +// } + var offset = FixedDocumentCreator.CalculateAlignmentOffset(formattedText,exportColumn); + var newLoc = new Point(location.X + offset.X,location.Y + offset.Y); +// dc.DrawText(formattedText,location); + dc.DrawText(formattedText,newLoc); } var dragingElement = new DrawingElement(visual); UIElement = dragingElement; diff --git a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_FromListFixture.cs b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_FromListFixture.cs index aa8101e507..45ba8599a2 100644 --- a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_FromListFixture.cs +++ b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_FromListFixture.cs @@ -20,6 +20,7 @@ using System; using System.Drawing; using System.Reflection; +using ICSharpCode.Reporting.Interfaces; using ICSharpCode.Reporting.Items; using NUnit.Framework; @@ -28,7 +29,7 @@ namespace ICSharpCode.Reporting.Test.Model [TestFixture] public class Report_FromListFixture { - private ReportModel model; + IReportModel model; [Test] public void ReportHeaderContainsOneItem () { diff --git a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_TwoItemsFixture.cs b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_TwoItemsFixture.cs index 75d01c457a..5b03ecd7a3 100644 --- a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_TwoItemsFixture.cs +++ b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/Model/Report_TwoItemsFixture.cs @@ -20,6 +20,7 @@ using System; using System.Drawing; using System.Reflection; +using ICSharpCode.Reporting.Interfaces; using ICSharpCode.Reporting.Items; using NUnit.Framework; @@ -29,7 +30,7 @@ namespace ICSharpCode.Reporting.Test.Model public class ReportTwoItemsFixture { - private ReportModel model; + IReportModel model; [Test] public void LoadModelWithItems() diff --git a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/PageBuilder/SectionConverterFixture.cs b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/PageBuilder/SectionConverterFixture.cs index 42dba39876..af4afbcd0a 100644 --- a/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/PageBuilder/SectionConverterFixture.cs +++ b/src/AddIns/Misc/Reporting/ICSharpCode.Reporting/Test/ICSharpCode.Reporting.Test/src/PageBuilder/SectionConverterFixture.cs @@ -95,7 +95,7 @@ namespace ICSharpCode.Reporting.Test.PageBuilder container.Items.Add(item1); container.Items.Add(item2); - Bitmap bitmap = new Bitmap(700,1000); + var bitmap = new Bitmap(700,1000); graphics = Graphics.FromImage(bitmap); } } diff --git a/src/AddIns/VersionControl/SubversionAddIn/Src/Commands/AutostartCommands.cs b/src/AddIns/VersionControl/SubversionAddIn/Src/Commands/AutostartCommands.cs index 639719169e..20e32b2a72 100644 --- a/src/AddIns/VersionControl/SubversionAddIn/Src/Commands/AutostartCommands.cs +++ b/src/AddIns/VersionControl/SubversionAddIn/Src/Commands/AutostartCommands.cs @@ -389,6 +389,10 @@ namespace ICSharpCode.Svn.Commands if (!AddInOptions.AutomaticallyRenameFiles) return; string fullSource = Path.GetFullPath(e.SourceFile); if (!CanBeVersionControlledFile(fullSource)) return; + if (!FileHelpers.CheckRenameOrReplacePossible(e)) { + e.Cancel = true; + return; + } try { using (SvnClientWrapper client = new SvnClientWrapper()) { SvnMessageView.HandleNotifications(client); diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs index 5b0fa5538e..e771f10e3c 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs @@ -264,11 +264,19 @@ namespace ICSharpCode.AvalonEdit /// Gets text required to indent from the specified to the next indentation level. /// public virtual string GetIndentationString(int column) + { + return GetIndentationString(column, IndentationSize, ConvertTabsToSpaces); + } + + /// + /// Gets text required to indent from the specified to the next indentation level, + /// considering given and settings. + /// + public static string GetIndentationString(int column, int indentationSize, bool convertTabsToSpaces) { if (column < 1) throw new ArgumentOutOfRangeException("column", column, "Value must be at least 1."); - int indentationSize = this.IndentationSize; - if (ConvertTabsToSpaces) { + if (convertTabsToSpaces) { return new string(' ', indentationSize - ((column - 1) % indentationSize)); } else { return "\t"; diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs index 4f390d92dc..3f92001457 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs @@ -61,6 +61,7 @@ namespace ICSharpCode.NRefactory.CSharp public override void WriteToken(Role role, string token) { CSharpTokenNode t = new CSharpTokenNode(locationProvider.Location, (TokenRole)role); + t.Role = role; EmptyStatement node = nodes.Peek().LastOrDefault() as EmptyStatement; if (node == null) currentList.Add(t); diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index b5d00fc3bb..07b470e716 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -366,6 +366,7 @@ + diff --git a/src/Main/Base/Project/Workbench/File/FileHelpers.cs b/src/Main/Base/Project/Workbench/File/FileHelpers.cs new file mode 100644 index 0000000000..d2f27371d5 --- /dev/null +++ b/src/Main/Base/Project/Workbench/File/FileHelpers.cs @@ -0,0 +1,49 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.IO; +using ICSharpCode.Core; + +namespace ICSharpCode.SharpDevelop.Workbench +{ + /// + /// Utility/helper methods for IFileService to avoid changing the IFileService interface. + /// + public static class FileHelpers + { + /// + /// Checks that the rename/overwrite operation is possible. + /// + public static bool CheckRenameOrReplacePossible(FileRenameEventArgs e, bool replaceAllowed = false) + { + if (e.IsDirectory && Directory.Exists(e.SourceFile)) { + if (!replaceAllowed && Directory.Exists(e.TargetFile)) { + SD.MessageService.ShowMessage(StringParser.Parse("${res:Gui.ProjectBrowser.FileInUseError}")); + return false; + } + } else if (File.Exists(e.SourceFile)) { + if (!replaceAllowed && File.Exists(e.TargetFile)) { + SD.MessageService.ShowMessage(StringParser.Parse("${res:Gui.ProjectBrowser.FileInUseError}")); + return false; + } + } + return true; + } + } +} diff --git a/src/Main/SharpDevelop/Workbench/FileService.cs b/src/Main/SharpDevelop/Workbench/FileService.cs index 41a18fb0ff..36816e36a4 100644 --- a/src/Main/SharpDevelop/Workbench/FileService.cs +++ b/src/Main/SharpDevelop/Workbench/FileService.cs @@ -580,20 +580,12 @@ namespace ICSharpCode.SharpDevelop.Workbench return false; if (!eargs.OperationAlreadyDone) { try { - if (isDirectory && Directory.Exists(oldName)) { - - if (Directory.Exists(newName)) { - MessageService.ShowMessage(StringParser.Parse("${res:Gui.ProjectBrowser.FileInUseError}")); - return false; + if (FileHelpers.CheckRenameOrReplacePossible(eargs)) { + if (isDirectory) { + Directory.Move(oldName, newName); + } else { + File.Move(oldName, newName); } - Directory.Move(oldName, newName); - - } else if (File.Exists(oldName)) { - if (File.Exists(newName)) { - MessageService.ShowMessage(StringParser.Parse("${res:Gui.ProjectBrowser.FileInUseError}")); - return false; - } - File.Move(oldName, newName); } } catch (Exception e) { if (isDirectory) { @@ -624,20 +616,12 @@ namespace ICSharpCode.SharpDevelop.Workbench return false; if (!eargs.OperationAlreadyDone) { try { - if (isDirectory && Directory.Exists(oldName)) { - - if (!overwrite && Directory.Exists(newName)) { - MessageService.ShowMessage(StringParser.Parse("${res:Gui.ProjectBrowser.FileInUseError}")); - return false; - } - FileUtility.DeepCopy(oldName, newName, overwrite); - - } else if (File.Exists(oldName)) { - if (!overwrite && File.Exists(newName)) { - MessageService.ShowMessage(StringParser.Parse("${res:Gui.ProjectBrowser.FileInUseError}")); - return false; + if (FileHelpers.CheckRenameOrReplacePossible(eargs, overwrite)) { + if (isDirectory) { + FileUtility.DeepCopy(oldName, newName, overwrite); + } else { + File.Copy(oldName, newName, overwrite); } - File.Copy(oldName, newName, overwrite); } } catch (Exception e) { if (isDirectory) {