From a8a3391f2575f7d1da63b009408555fb3645342a Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 29 Jul 2014 21:53:49 +0200 Subject: [PATCH 01/19] fix problem with captured/local variables in a generic context while debugging --- src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs | 4 +++- src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs b/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs index fec6bd7158..75b0441eef 100644 --- a/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs +++ b/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs @@ -232,7 +232,9 @@ namespace Debugger { var info = GetInfo(method.ParentAssembly); var variableTypes = info.GetLocalVariableTypes(method.UnresolvedMember); - return variableTypes[index].Resolve(new SimpleTypeResolveContext(method)); + return variableTypes[index] + .Resolve(new SimpleTypeResolveContext(method)) + .AcceptVisitor(method.Substitution); } #endregion diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs index 218178354b..24a89a5cb8 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs @@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpyAddIn return symbols.LocalVariables.Where(v => v.OriginalVariable != null).Select( v => new Debugger.ILLocalVariable() { Index = v.OriginalVariable.Index, - Type = loader.ReadTypeReference(v.Type).Resolve(context), + Type = loader.ReadTypeReference(v.Type).Resolve(context).AcceptVisitor(method.Substitution), Name = v.Name, IsCompilerGenerated = false, ILRanges = new [] { new ILRange(0, int.MaxValue) } From 8063942775eedd7242edc7f771052ff6f03558df Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 30 Jul 2014 20:09:01 +0200 Subject: [PATCH 02/19] close #296: ArgumentNullException when debugging and pdb points to missing file + show StackFrames without file name as unreachable in CallStackPad --- src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs index 4e0006a4d2..18b1f83dd2 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs @@ -150,7 +150,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads { bool showExternalMethods = DebuggingOptions.Instance.ShowExternalMethods; var symSource = WindowsDebugger.PdbSymbolSource; - bool hasSymbols = symSource.Handles(frame.MethodInfo) && !symSource.IsCompilerGenerated(frame.MethodInfo); + bool hasSymbols = symSource.Handles(frame.MethodInfo) + && !symSource.IsCompilerGenerated(frame.MethodInfo) + && frame.NextStatement != null && !string.IsNullOrWhiteSpace(frame.NextStatement.Filename); if (showExternalMethods || hasSymbols) { // Show the method in the list previousItemIsExternalMethod = false; From 466aa3a986bdd83167c8b60d9d3329619840ae35 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 31 Jul 2014 20:41:49 +0200 Subject: [PATCH 03/19] fix #371: No code completion in Razor .cshtml files --- .../AspNet.Mvc/Project/AspNet.Mvc.addin | 2 +- .../AspNet.Mvc/Project/AspNet.Mvc.csproj | 5 + .../RazorCSharpCompletionBinding.cs | 143 +++++++++++++++--- .../Project/Src/CSharpLanguageBinding.cs | 29 ++-- .../Src/Completion/CSharpCompletionBinding.cs | 9 +- .../Src/Completion/CSharpCompletionContext.cs | 24 +-- .../Pads/AutoCompleteTextBox.cs | 2 +- .../Debugger.AddIn/Pads/ConsolePad.cs | 2 +- .../Pads/DebuggerDotCompletion.cs | 8 +- .../LanguageBinding/DefaultLanguageBinding.cs | 2 +- .../LanguageBinding/ILanguageBinding.cs | 2 +- 11 files changed, 152 insertions(+), 76 deletions(-) diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.addin b/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.addin index 8f012b7a71..2b878a57fb 100644 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.addin +++ b/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.addin @@ -130,7 +130,7 @@ - + diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj b/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj index a6d3b5fd9d..0ac77f3dba 100644 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj +++ b/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj @@ -285,6 +285,11 @@ ICSharpCode.AvalonEdit False + + {53DCA265-3C3C-42F9-B647-F72BA678122B} + ICSharpCode.NRefactory.CSharp + False + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} ICSharpCode.NRefactory diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs index 4401cdb541..38b0020cb6 100644 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs @@ -16,27 +16,122 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -//using System; -//using ICSharpCode.SharpDevelop.Editor; -//using ICSharpCode.SharpDevelop.Editor.CodeCompletion; -// -//namespace ICSharpCode.AspNet.Mvc.Completion -//{ -// public class RazorCSharpCompletionBinding : DefaultCodeCompletionBinding -// { -// public RazorCSharpCompletionBinding() -// { -// } -// -// public override CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) -// { -// if (ch == '.') { -// new RazorCSharpDotCompletionDataProvider().ShowCompletion(editor); -// return CodeCompletionKeyPressResult.Completed; -// } else if (ch == '(') { -// return base.HandleKeyPress(editor, ch); -// } -// return CodeCompletionKeyPressResult.None; -// } -// } -//} +using System; +using System.IO; +using ICSharpCode.NRefactory; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.CSharp.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.CodeCompletion; + +namespace ICSharpCode.AspNet.Mvc.Completion +{ + public class RazorCSharpCompletionBinding : ICodeCompletionBinding + { + public bool HandleKeyPressed(ITextEditor editor, char ch) + { + if (ch == '.') { + var binding = CreateBinding(editor); + return binding.HandleKeyPressed(editor, ch); + } + return false; + } + + public bool CtrlSpace(ITextEditor editor) + { + return false; + } + + public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) + { + // We use HandleKeyPressed instead. + return CodeCompletionKeyPressResult.None; + } + + ICodeCompletionBinding CreateBinding(ITextEditor editor) + { + return SD.LanguageService.GetLanguageByExtension(".cs") + .CreateCompletionBinding(FindExpressionToComplete(editor), CreateContext(editor)); + } + + string FindExpressionToComplete(ITextEditor editor) + { + int endOffset = editor.Caret.Offset; + int startOffset = endOffset; + while (startOffset > 0 && IsValidCharacter(editor.Document.GetCharAt(startOffset - 1))) + startOffset--; + return editor.Document.GetText(startOffset, endOffset - startOffset); + } + + bool IsValidCharacter(char ch) + { + return Char.IsLetterOrDigit(ch) || + (ch == '.') || + (ch == '_'); + } + + ICodeContext CreateContext(ITextEditor editor) + { + var compilation = SD.ParserService.GetCompilationForFile(editor.FileName); + var project = SD.ProjectService.FindProjectContainingFile(editor.FileName); + + var resolveContext = new SimpleTypeResolveContext(compilation.MainAssembly); + + var currentTypeDefinition = new DefaultUnresolvedTypeDefinition(project.RootNamespace, Path.GetFileNameWithoutExtension(editor.FileName)); + ITypeReference baseTypeReference = new GetClassTypeReference("System.Web.Mvc", "WebViewPage", 1); + baseTypeReference = new ParameterizedTypeReference(baseTypeReference, new[] { KnownTypeReference.Object }); + currentTypeDefinition.BaseTypes.Add(baseTypeReference); + + var currentMethod = new DefaultUnresolvedMethod(currentTypeDefinition, "__ContextStub__"); + currentMethod.ReturnType = KnownTypeReference.Void; + currentTypeDefinition.Members.Add(currentMethod); + + var currentResolvedTypeDef = new DefaultResolvedTypeDefinition(resolveContext, currentTypeDefinition); + + var projectContent = compilation.MainAssembly.UnresolvedAssembly as IProjectContent; + + var currentFile = new CSharpUnresolvedFile(); + + currentFile.RootUsingScope.AddSimpleUsing("System.Web.Mvc"); + currentFile.RootUsingScope.AddSimpleUsing("System.Web.Mvc.Ajax"); + currentFile.RootUsingScope.AddSimpleUsing("System.Web.Mvc.Html"); + currentFile.RootUsingScope.AddSimpleUsing("System.Web.Routing"); + + currentFile.TopLevelTypeDefinitions.Add(currentTypeDefinition); + + if (projectContent != null) { + compilation = projectContent.AddOrUpdateFiles(currentFile).CreateCompilation(SD.ParserService.GetCurrentSolutionSnapshot()); + } + + var context = new CSharpTypeResolveContext(compilation.MainAssembly, + currentFile.RootUsingScope.Resolve(compilation), + currentResolvedTypeDef, + currentMethod.CreateResolved(resolveContext.WithCurrentTypeDefinition(currentResolvedTypeDef))); + return new CSharpResolver(context); + } + } + + static class NRUtils + { + /// Does not support type arguments! + public static void AddSimpleUsing(this UsingScope scope, string fullName) + { + if (scope == null) + throw new ArgumentNullException("scope"); + string[] parts = fullName.Trim().Split('.'); + TypeOrNamespaceReference reference = null; + foreach (var part in parts) { + if (reference != null) { + reference = new MemberTypeOrNamespaceReference(reference, part, EmptyList.Instance); + } else { + reference = new SimpleTypeOrNamespaceReference(part, EmptyList.Instance); + } + } + + scope.Usings.AddIfNotNull(reference); + } + } +} diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs index 548fddd585..8921e09daf 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs @@ -55,35 +55,26 @@ namespace CSharpBinding this.container.AddService(typeof(System.CodeDom.Compiler.CodeDomProvider), new Microsoft.CSharp.CSharpCodeProvider()); } - public override ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context) + public override ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, ICodeContext context) { - if (fileName == null) - throw new ArgumentNullException("fileName"); if (context == null) throw new ArgumentNullException("context"); - string content = GeneratePartialClassContextStub(fileName, location, context); + string content = GeneratePartialClassContextStub(context); const string caretPoint = "$__Caret_Point__$;"; int caretOffset = content.IndexOf(caretPoint, StringComparison.Ordinal) + expressionToComplete.Length; SD.Log.DebugFormatted("context used for dot completion: {0}", content.Replace(caretPoint, "$" + expressionToComplete + "|$")); var doc = new ReadOnlyDocument(content.Replace(caretPoint, expressionToComplete)); - return new CSharpCompletionBinding(fileName, doc.GetLocation(caretOffset), doc.CreateSnapshot()); + return new CSharpCompletionBinding(context, doc.GetLocation(caretOffset), doc.CreateSnapshot()); } - static string GeneratePartialClassContextStub(FileName fileName, TextLocation location, ICodeContext context) + static string GeneratePartialClassContextStub(ICodeContext context) { - var compilation = SD.ParserService.GetCompilationForFile(fileName); - var file = SD.ParserService.GetExistingUnresolvedFile(fileName); - if (compilation == null || file == null) - return ""; - var unresolvedMember = file.GetMember(location); - if (unresolvedMember == null) - return ""; - var member = unresolvedMember.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)); + var member = context.CurrentMember; if (member == null) return ""; var builder = new TypeSystemAstBuilder(); MethodDeclaration decl; - if (unresolvedMember is IMethod) { + if (member is IMethod) { // If it's a method, convert it directly (including parameters + type parameters) decl = (MethodDeclaration)builder.ConvertEntity(member); } else { @@ -97,11 +88,11 @@ namespace CSharpBinding } decl.Name = "__DebuggerStub__"; decl.ReturnType = builder.ConvertType(member.ReturnType); - decl.Modifiers = unresolvedMember.IsStatic ? Modifiers.Static : Modifiers.None; + decl.Modifiers = member.IsStatic ? Modifiers.Static : Modifiers.None; // Make the method look like an explicit interface implementation so that it doesn't appear in CC decl.PrivateImplementationType = new SimpleType("__DummyType__"); decl.Body = GenerateBodyFromContext(builder, context.LocalVariables.ToArray()); - return WrapInType(unresolvedMember.DeclaringTypeDefinition, decl).ToString(); + return WrapInType(context.CurrentTypeDefinition, decl).ToString(); } static BlockStatement GenerateBodyFromContext(TypeSystemAstBuilder builder, IVariable[] variables) @@ -113,7 +104,7 @@ namespace CSharpBinding return body; } - static AstNode WrapInType(IUnresolvedTypeDefinition entity, EntityDeclaration decl) + static AstNode WrapInType(ITypeDefinition entity, EntityDeclaration decl) { if (entity == null) return decl; @@ -137,7 +128,7 @@ namespace CSharpBinding }; } - static ClassType GetClassType(IUnresolvedTypeDefinition entity) + static ClassType GetClassType(ITypeDefinition entity) { switch (entity.Kind) { case TypeKind.Interface: diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs index 1e9943d962..11bbd494da 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs @@ -26,6 +26,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.CSharp.Completion; using ICSharpCode.NRefactory.Editor; +using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor.CodeCompletion; @@ -35,7 +36,7 @@ namespace CSharpBinding.Completion { public class CSharpCompletionBinding : ICodeCompletionBinding { - FileName contextFileName; + ICodeContext context; TextLocation currentLocation; ITextSource fileContent; @@ -44,9 +45,9 @@ namespace CSharpBinding.Completion { } - public CSharpCompletionBinding(FileName contextFileName, TextLocation currentLocation, ITextSource fileContent) + public CSharpCompletionBinding(ICodeContext context, TextLocation currentLocation, ITextSource fileContent) { - this.contextFileName = contextFileName; + this.context = context; this.currentLocation = currentLocation; this.fileContent = fileContent; } @@ -75,7 +76,7 @@ namespace CSharpBinding.Completion if (fileContent == null) { completionContext = CSharpCompletionContext.Get(editor); } else { - completionContext = CSharpCompletionContext.Get(editor, fileContent, currentLocation, contextFileName); + completionContext = CSharpCompletionContext.Get(editor, context, currentLocation, fileContent); } if (completionContext == null) return false; diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs index ae654a0d81..2f4623dcf7 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs @@ -61,38 +61,24 @@ namespace CSharpBinding.Completion return new CSharpCompletionContext(editor, parseInfo.SyntaxTree.ConditionalSymbols, compilation, projectContent, editor.Document, parseInfo.UnresolvedFile, editor.Caret.Location); } - public static CSharpCompletionContext Get(ITextEditor editor, ITextSource fileContent, TextLocation currentLocation, FileName fileName) + public static CSharpCompletionContext Get(ITextEditor editor, ICodeContext context, TextLocation currentLocation, ITextSource fileContent) { IDocument document = new ReadOnlyDocument(fileContent); - // Don't require the very latest parse information, an older cached version is OK. - var parseInfo = SD.ParserService.GetCachedParseInformation(fileName) as CSharpFullParseInformation; - if (parseInfo == null) { - parseInfo = SD.ParserService.Parse(fileName) as CSharpFullParseInformation; - } - if (parseInfo == null) - return null; - - - var project = SD.ProjectService.FindProjectContainingFile(fileName)as CSharpProject; - if (project == null) - return null; - - var solutionSnapshot = SD.ParserService.GetCurrentSolutionSnapshot(); - var projectContent = solutionSnapshot.GetProjectContent(project); + var projectContent = context.Compilation.MainAssembly.UnresolvedAssembly as IProjectContent; if (projectContent == null) return null; - CSharpParser parser = new CSharpParser(project.CompilerSettings); + CSharpParser parser = new CSharpParser(); parser.GenerateTypeSystemMode = false; SyntaxTree cu = parser.Parse(fileContent, Path.GetRandomFileName() + ".cs"); cu.Freeze(); CSharpUnresolvedFile unresolvedFile = cu.ToTypeSystem(); - ICompilation compilation = projectContent.AddOrUpdateFiles(unresolvedFile).CreateCompilation(solutionSnapshot); + ICompilation compilation = projectContent.AddOrUpdateFiles(unresolvedFile).CreateCompilation(SD.ParserService.GetCurrentSolutionSnapshot()); - return new CSharpCompletionContext(editor, parseInfo.SyntaxTree.ConditionalSymbols, compilation, projectContent, document, unresolvedFile, currentLocation); + return new CSharpCompletionContext(editor, EmptyList.Instance, compilation, projectContent, document, unresolvedFile, currentLocation); } private CSharpCompletionContext(ITextEditor editor, IList conditionalSymbols, ICompilation compilation, IProjectContent projectContent, IDocument document, CSharpUnresolvedFile unresolvedFile, TextLocation caretLocation) diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs index aca8f0c0b6..b931e96c10 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs @@ -134,7 +134,7 @@ namespace Debugger.AddIn.Pads.Controls ContextTextLocation = new TextLocation(frame.NextStatement.StartLine, frame.NextStatement.StartColumn); } if (ContextFileName == null) return; - var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), ContextFileName, ContextTextLocation, SD.ParserService.ResolveContext(ContextFileName, ContextTextLocation)); + var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), SD.ParserService.ResolveContext(ContextFileName, ContextTextLocation)); if (binding == null) return; binding.HandleKeyPressed(editorAdapter, '.'); } else { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs index c88df18834..76c3341a9d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs @@ -88,7 +88,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads { var fileName = new ICSharpCode.Core.FileName(frame.NextStatement.Filename); var textLocation = new TextLocation(frame.NextStatement.StartLine, frame.NextStatement.StartColumn); - var binding = DebuggerDotCompletion.PrepareDotCompletion(currentText, fileName, textLocation, SD.ParserService.ResolveContext(fileName, textLocation)); + var binding = DebuggerDotCompletion.PrepareDotCompletion(currentText, SD.ParserService.ResolveContext(fileName, textLocation)); if (binding == null) return; binding.HandleKeyPressed(console.TextEditor, '.'); } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs index 854abc5cca..9370726b9d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs @@ -41,12 +41,10 @@ namespace Debugger.AddIn.Pads.Controls return !errors.Any(); } - public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context) + public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, ICodeContext context) { - var lang = SD.LanguageService.GetLanguageByFileName(fileName); - if (lang == null) - return null; - return lang.CreateCompletionBinding(expressionToComplete, fileName, location, context); + return SD.LanguageService.GetLanguageByExtension(".cs") + .CreateCompletionBinding(expressionToComplete, context); } } } diff --git a/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs b/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs index c1b1bf7216..f48211e1d1 100644 --- a/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs +++ b/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs @@ -75,7 +75,7 @@ namespace ICSharpCode.SharpDevelop } } - public virtual ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context) + public virtual ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, ICodeContext context) { throw new NotSupportedException(); } diff --git a/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs b/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs index 49ad72abea..56528c08cc 100644 --- a/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs +++ b/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs @@ -65,6 +65,6 @@ namespace ICSharpCode.SharpDevelop /// /// Creates a completion binding for a given expression and context. /// - ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context); + ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, ICodeContext context); } } From 0c84517c9c966719eca9df5d60a6fbaa684ff939 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 31 Jul 2014 21:27:02 +0200 Subject: [PATCH 04/19] remove old RazorCSharp completion code --- .../AspNet.Mvc/Project/AspNet.Mvc.csproj | 5 - .../RazorCSharpDotCompletionDataProvider.cs | 26 ---- .../Completion/RazorCSharpExpressionFinder.cs | 58 --------- .../Src/Completion/RazorCSharpParser.cs | 68 ---------- .../Src/Completion/RazorCSharpResolver.cs | 119 ------------------ .../Src/Completion/RazorCompilationUnit.cs | 50 -------- 6 files changed, 326 deletions(-) delete mode 100644 src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpDotCompletionDataProvider.cs delete mode 100644 src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpExpressionFinder.cs delete mode 100644 src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpParser.cs delete mode 100644 src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpResolver.cs delete mode 100644 src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCompilationUnit.cs diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj b/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj index 0ac77f3dba..95273c0e26 100644 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj +++ b/src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj @@ -134,14 +134,9 @@ - - - - - diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpDotCompletionDataProvider.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpDotCompletionDataProvider.cs deleted file mode 100644 index e5a321335d..0000000000 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpDotCompletionDataProvider.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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; -// -//namespace ICSharpCode.AspNet.Mvc.Completion -//{ -// public class RazorCSharpDotCompletionDataProvider : DotCodeCompletionItemProvider -// { -// } -//} diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpExpressionFinder.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpExpressionFinder.cs deleted file mode 100644 index 11aae7c710..0000000000 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpExpressionFinder.cs +++ /dev/null @@ -1,58 +0,0 @@ -// 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 ICSharpCode.SharpDevelop.Dom; -// -//namespace ICSharpCode.AspNet.Mvc.Completion -//{ -// public class RazorCSharpExpressionFinder : IExpressionFinder -// { -// public RazorCSharpExpressionFinder() -// { -// } -// -// public ExpressionResult FindExpression(string text, int offset) -// { -// int position = offset - 1; -// while (position > 0 && IsValidCharacter(text[position])) { -// position--; -// } -// position++; -// string expression = text.Substring(position, offset - position); -// return new ExpressionResult(expression); -// } -// -// bool IsValidCharacter(char ch) -// { -// return Char.IsLetterOrDigit(ch) || -// (ch == '.') || -// (ch == '_'); -// } -// -// public ExpressionResult FindFullExpression(string text, int offset) -// { -// return ExpressionResult.Empty; -// } -// -// public string RemoveLastPart(string expression) -// { -// return expression; -// } -// } -//} diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpParser.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpParser.cs deleted file mode 100644 index cce64fb643..0000000000 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpParser.cs +++ /dev/null @@ -1,68 +0,0 @@ -// 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.SharpDevelop; -//using ICSharpCode.SharpDevelop.Dom; -//using ICSharpCode.SharpDevelop.Dom.CSharp; -//using ICSharpCode.SharpDevelop.Project; -// -//namespace ICSharpCode.AspNet.Mvc.Completion -//{ -// public class RazorCSharpParser : IParser -// { -// public RazorCSharpParser() -// { -// } -// -// public string[] LexerTags { get; set; } -// -// public LanguageProperties Language { -// get { return LanguageProperties.CSharp; } -// } -// -// public IExpressionFinder CreateExpressionFinder(string fileName) -// { -// return new RazorCSharpExpressionFinder(); -// } -// -// public bool CanParse(string fileName) -// { -// return Path.GetExtension(fileName).Equals(".cshtml", StringComparison.OrdinalIgnoreCase); -// } -// -// public bool CanParse(IProject project) -// { -// return project.Language == "C#"; -// } -// -// public ICompilationUnit Parse(IProjectContent projectContent, string fileName, ITextBuffer fileContent) -// { -// var modelTypeLocater = new RazorCSharpModelTypeLocater(fileContent); -// return new RazorCompilationUnit(projectContent) { -// ModelTypeName = modelTypeLocater.ModelTypeName -// }; -// } -// -// public IResolver CreateResolver() -// { -// return new RazorCSharpResolver(); -// } -// } -//} diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpResolver.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpResolver.cs deleted file mode 100644 index 1ce97c8dc5..0000000000 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpResolver.cs +++ /dev/null @@ -1,119 +0,0 @@ -// 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.Collections.Generic; -//using ICSharpCode.NRefactory.TypeSystem; -// -//namespace ICSharpCode.AspNet.Mvc.Completion -//{ -// public class RazorCSharpResolver : IResolver -// { -// NRefactoryResolver resolver = new NRefactoryResolver(LanguageProperties.CSharp); -// -// public ResolveResult Resolve(ExpressionResult expressionResult, ParseInformation parseInfo, string fileContent) -// { -// ParseInformation parseInfoWithWebViewPageClass = CreateParseInformationWithWebViewPageClass(parseInfo); -// expressionResult.Region = GetRegionInMiddleOfWebViewPageClass(); -// return resolver.Resolve(expressionResult, parseInfoWithWebViewPageClass, fileContent); -// } -// -// ParseInformation CreateParseInformationWithWebViewPageClass(ParseInformation parseInfo) -// { -// RazorCompilationUnit compilationUnit = RazorCompilationUnit.CreateFromParseInfo(parseInfo); -// AddDefaultUsings(compilationUnit); -// AddWebViewPageClass(compilationUnit); -// return new ParseInformation(compilationUnit); -// } -// -// void AddDefaultUsings(ICompilationUnit compilationUnit) -// { -// AddUsing("System.Web.Mvc", compilationUnit); -// AddUsing("System.Web.Mvc.Ajax", compilationUnit); -// AddUsing("System.Web.Mvc.Html", compilationUnit); -// AddUsing("System.Web.Routing", compilationUnit); -// } -// -// void AddUsing(string name, ICompilationUnit compilationUnit) -// { -// DefaultUsing defaultUsing = CreateUsing(name, compilationUnit.ProjectContent); -// compilationUnit.UsingScope.Usings.Add(defaultUsing); -// } -// -// DefaultUsing CreateUsing(string namespaceName, IProjectContent projectContent) -// { -// var defaultUsing = new DefaultUsing(projectContent); -// defaultUsing.Usings.Add(namespaceName); -// return defaultUsing; -// } -// -// void AddWebViewPageClass(RazorCompilationUnit compilationUnit) -// { -// DefaultClass webViewPageClass = CreateWebViewPageClass(compilationUnit); -// compilationUnit.Classes.Add(webViewPageClass); -// } -// -// DefaultClass CreateWebViewPageClass(RazorCompilationUnit compilationUnit) -// { -// var webViewPageClass = new DefaultClass(compilationUnit, "RazorWebViewPage") { -// Region = new DomRegion(1, 0, 3, 0) -// }; -// IReturnType modelType = GetModelReturnType(compilationUnit); -// AddWebViewPageBaseClass(webViewPageClass, modelType); -// return webViewPageClass; -// } -// -// IReturnType GetModelReturnType(RazorCompilationUnit compilationUnit) -// { -// IClass modelType = GetClassIfTypeNameIsNotEmpty(compilationUnit.ProjectContent, compilationUnit.ModelTypeName); -// if (modelType != null) { -// return modelType.DefaultReturnType; -// } -// return new DynamicReturnType(compilationUnit.ProjectContent); -// } -// -// IClass GetClassIfTypeNameIsNotEmpty(IProjectContent projectContent, string modelTypeName) -// { -// if (!String.IsNullOrEmpty(modelTypeName)) { -// return projectContent.GetClass(modelTypeName, 0); -// } -// return null; -// } -// -// void AddWebViewPageBaseClass(DefaultClass webViewPageClass, IReturnType modelType) -// { -// IClass webViewPageBaseClass = webViewPageClass.ProjectContent.GetClass("System.Web.Mvc.WebViewPage", 1); -// if (webViewPageBaseClass != null) { -// IReturnType returnType = GetWebViewPageBaseClassReturnType(webViewPageBaseClass, modelType); -// webViewPageClass.BaseTypes.Add(returnType); -// } -// } -// -// IReturnType GetWebViewPageBaseClassReturnType(IClass webViewPageBaseClass, IReturnType modelType) -// { -// var typeArguments = new List(); -// typeArguments.Add(modelType); -// return new ConstructedReturnType(webViewPageBaseClass.DefaultReturnType, typeArguments); -// } -// -// DomRegion GetRegionInMiddleOfWebViewPageClass() -// { -// return new DomRegion(2, 0, 2, 0); -// } -// } -//} diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCompilationUnit.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCompilationUnit.cs deleted file mode 100644 index 9672f4df56..0000000000 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCompilationUnit.cs +++ /dev/null @@ -1,50 +0,0 @@ -// 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 ICSharpCode.NRefactory.TypeSystem; -//using ICSharpCode.SharpDevelop.Parser; -// -//namespace ICSharpCode.AspNet.Mvc.Completion -//{ -// public class RazorCompilationUnit : DefaultCompilationUnit -// { -// public RazorCompilationUnit(IProjectContent projectContent) -// : base(projectContent) -// { -// } -// -// public static RazorCompilationUnit CreateFromParseInfo(ParseInformation parseInformation) -// { -// return new RazorCompilationUnit(parseInformation.CompilationUnit.ProjectContent) { -// ModelTypeName = GetModelTypeName(parseInformation.CompilationUnit) -// }; -// } -// -// static string GetModelTypeName(ICompilationUnit compilationUnit) -// { -// var originalRazorCompilationUnit = compilationUnit as RazorCompilationUnit; -// if (originalRazorCompilationUnit != null) { -// return originalRazorCompilationUnit.ModelTypeName; -// } -// return String.Empty; -// } -// -// public string ModelTypeName { get; set; } -// } -//} From d68d30151934109d28991ca4fe3437d07945c898 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 31 Jul 2014 21:27:53 +0200 Subject: [PATCH 05/19] reimplement support for @model ModelTypeName --- .../RazorCSharpCompletionBinding.cs | 35 +++++++++-- .../Completion/RazorCSharpModelTypeLocater.cs | 62 +++++++++---------- 2 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs index 38b0020cb6..1ab287f0cb 100644 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpCompletionBinding.cs @@ -18,9 +18,12 @@ using System; using System.IO; +using System.Web.Razor; using ICSharpCode.NRefactory; +using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.TypeSystem; +using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.SharpDevelop; @@ -82,7 +85,7 @@ namespace ICSharpCode.AspNet.Mvc.Completion var currentTypeDefinition = new DefaultUnresolvedTypeDefinition(project.RootNamespace, Path.GetFileNameWithoutExtension(editor.FileName)); ITypeReference baseTypeReference = new GetClassTypeReference("System.Web.Mvc", "WebViewPage", 1); - baseTypeReference = new ParameterizedTypeReference(baseTypeReference, new[] { KnownTypeReference.Object }); + baseTypeReference = new ParameterizedTypeReference(baseTypeReference, new[] { FindModelType(editor) }); currentTypeDefinition.BaseTypes.Add(baseTypeReference); var currentMethod = new DefaultUnresolvedMethod(currentTypeDefinition, "__ContextStub__"); @@ -107,11 +110,35 @@ namespace ICSharpCode.AspNet.Mvc.Completion } var context = new CSharpTypeResolveContext(compilation.MainAssembly, - currentFile.RootUsingScope.Resolve(compilation), - currentResolvedTypeDef, - currentMethod.CreateResolved(resolveContext.WithCurrentTypeDefinition(currentResolvedTypeDef))); + currentFile.RootUsingScope.Resolve(compilation), + currentResolvedTypeDef, + currentMethod.CreateResolved(resolveContext.WithCurrentTypeDefinition(currentResolvedTypeDef))); return new CSharpResolver(context); } + + ITypeReference FindModelType(ITextEditor editor) + { + ParserResults results = ParseTemplate(editor.Document); + string typeName = GetModelTypeName(results); + if (string.IsNullOrWhiteSpace(typeName)) + return KnownTypeReference.Object; + return new CSharpParser().ParseTypeReference(typeName) + .ToTypeReference(NameLookupMode.BaseTypeReference); + } + + ParserResults ParseTemplate(ITextSource textBuffer) + { + var host = new RazorEngineHost(new CSharpRazorCodeLanguage()); + var engine = new RazorTemplateEngine(host); + return engine.ParseTemplate(textBuffer.CreateReader()); + } + + string GetModelTypeName(ParserResults results) + { + var visitor = new RazorCSharpParserModelTypeVisitor(); + results.Document.Accept(visitor); + return visitor.ModelTypeName; + } } static class NRUtils diff --git a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpModelTypeLocater.cs b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpModelTypeLocater.cs index e45bc69574..a5cc0ea8be 100644 --- a/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpModelTypeLocater.cs +++ b/src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Completion/RazorCSharpModelTypeLocater.cs @@ -16,34 +16,34 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -//using System; -//using System.Web.Razor; -//using ICSharpCode.SharpDevelop; -// -//namespace ICSharpCode.AspNet.Mvc.Completion -//{ -// public class RazorCSharpModelTypeLocater -// { -// public RazorCSharpModelTypeLocater(ITextBuffer textBuffer) -// { -// ParserResults results = ParseTemplate(textBuffer); -// ModelTypeName = GetModelTypeName(results); -// } -// -// ParserResults ParseTemplate(ITextBuffer textBuffer) -// { -// var host = new RazorEngineHost(new CSharpRazorCodeLanguage()); -// var engine = new RazorTemplateEngine(host); -// return engine.ParseTemplate(textBuffer.CreateReader()); -// } -// -// string GetModelTypeName(ParserResults results) -// { -// var visitor = new RazorCSharpParserModelTypeVisitor(); -// results.Document.Accept(visitor); -// return visitor.ModelTypeName; -// } -// -// public string ModelTypeName { get; private set; } -// } -//} +using System; +using System.Web.Razor; +using ICSharpCode.NRefactory.Editor; + +namespace ICSharpCode.AspNet.Mvc.Completion +{ + public class RazorCSharpModelTypeLocater + { + public RazorCSharpModelTypeLocater(ITextSource textBuffer) + { + ParserResults results = ParseTemplate(textBuffer); + ModelTypeName = GetModelTypeName(results); + } + + ParserResults ParseTemplate(ITextSource textBuffer) + { + var host = new RazorEngineHost(new CSharpRazorCodeLanguage()); + var engine = new RazorTemplateEngine(host); + return engine.ParseTemplate(textBuffer.CreateReader()); + } + + string GetModelTypeName(ParserResults results) + { + var visitor = new RazorCSharpParserModelTypeVisitor(); + results.Document.Accept(visitor); + return visitor.ModelTypeName; + } + + public string ModelTypeName { get; private set; } + } +} From e152b747ddd56a604480379d5762df7ffc22f398 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 1 Aug 2014 16:57:29 +0200 Subject: [PATCH 06/19] fix calculation of sequence points for breakpoints in pdb files --- .../Debugger/Debugger.Core/Breakpoint.cs | 2 +- .../Debugger/Debugger.Core/PdbSymbolSource.cs | 58 +++++++++++++++---- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs index 2e170818cc..f6b1e8a034 100644 --- a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs +++ b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs @@ -84,7 +84,7 @@ namespace Debugger public void SetBreakpoint(Module module) { - foreach(var symbolSource in module.Process.Debugger.SymbolSources) { + foreach (var symbolSource in module.Process.Debugger.SymbolSources) { foreach (var seq in symbolSource.GetSequencePoints(module, this.FileName, this.Line, this.Column)) { ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken); ICorDebugFunctionBreakpoint corBreakpoint = corFunction.GetILCode().CreateBreakpoint((uint)seq.ILOffset); diff --git a/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs b/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs index 5715fa7443..aad518a400 100644 --- a/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs +++ b/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs @@ -48,6 +48,14 @@ namespace Debugger this.StartLine, this.StartColumn, this.EndLine, this.EndColumn); } + + public bool ContainsLocation(int line, int column = 0) + { + if (column == 0) + return line >= StartLine && line <= EndLine; + return (StartLine < line || (StartLine == line && StartColumn <= column)) + && (line < EndLine || (line == EndLine && column <= EndColumn)); + } } public struct ILRange @@ -185,14 +193,14 @@ namespace Debugger var realSeqPoints = sequencePoints.Where(p => p.StartLine != 0xFEEFEE); // Find point for which (ilstart <= iloffset < ilend) or fallback to the next valid sequence point - var sequencePoint = realSeqPoints.FirstOrDefault(p => p.ILRanges.Any(r => r.From <= iloffset && iloffset < r.To)) ?? - realSeqPoints.FirstOrDefault(p => iloffset <= p.ILOffset); + var sequencePoint = realSeqPoints.FirstOrDefault(p => p.ILRanges.Any(r => r.From <= iloffset && iloffset < r.To)) + ?? realSeqPoints.FirstOrDefault(p => iloffset <= p.ILOffset); if (sequencePoint != null) { // VB.NET sometimes produces temporary files which it then deletes // (eg 17d14f5c-a337-4978-8281-53493378c1071.vb) string name = Path.GetFileName(sequencePoint.Filename); - if (name.Length == 40 && name.EndsWith(".vb")) { + if (name.Length == 40 && name.EndsWith(".vb", StringComparison.OrdinalIgnoreCase)) { if (name.Substring(0, name.Length - 3).All(c => ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || (c == '-'))) { return null; } @@ -232,19 +240,47 @@ namespace Debugger foreach (ISymUnmanagedMethod symMethod in symMethods) { var corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); - int codesize = (int)corFunction.GetILCode().GetSize(); - var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE); - SequencePoint seqPoint = null; - if (column != 0) { - seqPoint = seqPoints.FirstOrDefault(s => (s.StartLine < line || (s.StartLine == line && s.StartColumn <= column)) && - (line < s.EndLine || (line == s.EndLine && column <= s.EndColumn))); - } - seqPoint = seqPoint ?? seqPoints.FirstOrDefault(s => line <= s.StartLine); + int codeSize = (int)corFunction.GetILCode().GetSize(); + var seqPoints = symMethod.GetSequencePoints(codeSize).Where(s => s.StartLine != 0xFEEFEE).OrderBy(s => s.StartLine).ToArray(); + SequencePoint seqPoint = FindNearestMatchingSequencePoint(seqPoints, line, column); if (seqPoint != null) yield return seqPoint; } } + SequencePoint FindNearestMatchingSequencePoint(SequencePoint[] seqPoints, int line, int column) + { + // value is nearest offset in lines; + // negative numbers: (Start|End)Line is same as line, value is offset in columns + int nearestOffset = 0; + SequencePoint bestMatch = null; + for (int i = 0; i < seqPoints.Length; i++) { + var s = seqPoints[i]; + if (s.ContainsLocation(line, column)) + return seqPoints[i]; + + if (bestMatch == null) { + bestMatch = s; + nearestOffset = GetOffsetValue(s, line, column); + } else { + int newOffset = GetOffsetValue(s, line, column); + if ((newOffset < 0 && nearestOffset < 0 && newOffset > nearestOffset) || (newOffset < nearestOffset)) { + bestMatch = s; + nearestOffset = newOffset; + } + } + } + + return bestMatch; + } + + static int GetOffsetValue(SequencePoint s, int line, int column) + { + if (line == s.StartLine || s.EndLine == line) + return -Math.Min(Math.Abs(s.StartColumn - column), Math.Abs(s.EndColumn - column)); + return Math.Min(Math.Abs(s.StartLine - line), Math.Abs(s.EndLine - line)); + } + public IEnumerable GetIgnoredILRanges(IMethod method) { var symMethod = method.GetSymMethod(); From 7a6df89318ffbbcc7c9f9f447eaa5e4127204a78 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 1 Aug 2014 17:24:36 +0200 Subject: [PATCH 07/19] fix build --- .../Debugger/Debugger.Core/PdbSymbolSource.cs | 31 ++++--------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs b/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs index aad518a400..945242fbe3 100644 --- a/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs +++ b/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs @@ -234,6 +234,8 @@ namespace Debugger try { uint validLine = symDoc.FindClosestLine((uint)line); symMethods = symReader.GetMethodsFromDocumentPosition(symDoc, validLine, (uint)column); + if (validLine > 0) + line = (int)validLine; } catch { yield break; //Not found } @@ -250,35 +252,14 @@ namespace Debugger SequencePoint FindNearestMatchingSequencePoint(SequencePoint[] seqPoints, int line, int column) { - // value is nearest offset in lines; - // negative numbers: (Start|End)Line is same as line, value is offset in columns - int nearestOffset = 0; - SequencePoint bestMatch = null; for (int i = 0; i < seqPoints.Length; i++) { var s = seqPoints[i]; if (s.ContainsLocation(line, column)) - return seqPoints[i]; - - if (bestMatch == null) { - bestMatch = s; - nearestOffset = GetOffsetValue(s, line, column); - } else { - int newOffset = GetOffsetValue(s, line, column); - if ((newOffset < 0 && nearestOffset < 0 && newOffset > nearestOffset) || (newOffset < nearestOffset)) { - bestMatch = s; - nearestOffset = newOffset; - } - } + return s; + if (s.StartLine > line) + return s; } - - return bestMatch; - } - - static int GetOffsetValue(SequencePoint s, int line, int column) - { - if (line == s.StartLine || s.EndLine == line) - return -Math.Min(Math.Abs(s.StartColumn - column), Math.Abs(s.EndColumn - column)); - return Math.Min(Math.Abs(s.StartLine - line), Math.Abs(s.EndLine - line)); + return null; } public IEnumerable GetIgnoredILRanges(IMethod method) From af0cc60416d5c40528f3c2b36b3dca0f6446ede2 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 2 Aug 2014 14:35:19 +0100 Subject: [PATCH 08/19] Fix Check with StyleCop menu not returning any StyleCop warnings. --- .../SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngine.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngine.cs b/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngine.cs index f4c9f5af5c..6142d601f2 100644 --- a/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngine.cs +++ b/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngine.cs @@ -94,6 +94,7 @@ namespace ICSharpCode.SharpDevelop.Project throw new ArgumentNullException("feedbackSink"); var additionalTargetFileList = additionalTargetFiles != null ? additionalTargetFiles.ToList() : new List(); + additionalTargetFileList.AddRange(AdditionalTargetFiles.Select(fileName => fileName.ToString())); if (project.MinimumSolutionVersion >= SolutionFormatVersion.VS2010) { additionalTargetFileList.Add(Path.Combine(Path.GetDirectoryName(typeof(MSBuildEngine).Assembly.Location), "SharpDevelop.TargetingPack.targets")); } From e5dde6f4aceae2e77957258307597c97cb90862d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 3 Aug 2014 19:37:25 +0200 Subject: [PATCH 09/19] Don't use lazy loading for built-in WPF commands. --- src/Main/Core/Project/Src/Util/CommandWrapper.cs | 11 +++++++++++ .../Menu/MenuCommand.cs | 7 ++----- .../Menu/MenuService.cs | 3 +-- .../ToolBar/ToolBarButton.cs | 7 ++----- .../ToolBar/ToolBarService.cs | 4 +--- .../ICSharpCode.Core.WinForms/Menu/MenuCommand.cs | 12 +----------- .../ICSharpCode.Core.WinForms/Menu/MenuService.cs | 2 +- 7 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/Main/Core/Project/Src/Util/CommandWrapper.cs b/src/Main/Core/Project/Src/Util/CommandWrapper.cs index 70009c5366..b2adc9479f 100644 --- a/src/Main/Core/Project/Src/Util/CommandWrapper.cs +++ b/src/Main/Core/Project/Src/Util/CommandWrapper.cs @@ -44,6 +44,17 @@ namespace ICSharpCode.Core /// public static ICommand CreateLazyCommand(Codon codon, IReadOnlyCollection conditions) { + if (codon.Properties["loadclasslazy"] == "false") { + // if lazy loading was explicitly disabled, create the actual command now + return CreateCommand(codon, conditions); + } + if (codon.Properties.Contains("command") && !codon.Properties.Contains("loadclasslazy")) { + // If we're using the 'command=' syntax, this is most likely a built-in command + // where lazy loading isn't useful (and hurts if CanExecute is used). + // Don't use lazy loading unless loadclasslazy is set explicitly. + return CreateCommand(codon, conditions); + } + // Create the wrapper that lazily loads the actual command. return new CommandWrapper(codon, conditions); } diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs index c96ed51a2b..d134811d71 100644 --- a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs +++ b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs @@ -32,13 +32,10 @@ namespace ICSharpCode.Core.Presentation { readonly string ActivationMethod; - public MenuCommand(UIElement inputBindingOwner, Codon codon, object caller, bool createCommand, string activationMethod, IReadOnlyCollection conditions) : base(codon, caller, conditions) + public MenuCommand(UIElement inputBindingOwner, Codon codon, object caller, string activationMethod, IReadOnlyCollection conditions) : base(codon, caller, conditions) { this.ActivationMethod = activationMethod; - if (createCommand) - this.Command = CommandWrapper.CreateCommand(codon, conditions); - else - this.Command = CommandWrapper.CreateLazyCommand(codon, conditions); + this.Command = CommandWrapper.CreateLazyCommand(codon, conditions); this.CommandParameter = caller; if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) { diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs index efdfb4209f..7f68990b38 100644 --- a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs +++ b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs @@ -211,7 +211,6 @@ namespace ICSharpCode.Core.Presentation { Codon codon = descriptor.Codon; string type = codon.Properties.Contains("type") ? codon.Properties["type"] : "Command"; - bool createCommand = codon.Properties["loadclasslazy"] == "false"; switch (type) { case "Separator": @@ -220,7 +219,7 @@ namespace ICSharpCode.Core.Presentation return new MenuCheckBox(context.InputBindingOwner, codon, descriptor.Parameter, descriptor.Conditions); case "Item": case "Command": - return new MenuCommand(context.InputBindingOwner, codon, descriptor.Parameter, createCommand, context.ActivationMethod, descriptor.Conditions); + return new MenuCommand(context.InputBindingOwner, codon, descriptor.Parameter, context.ActivationMethod, descriptor.Conditions); case "Menu": var item = new CoreMenuItem(codon, descriptor.Parameter, descriptor.Conditions) { ItemsSource = new object[1], diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs index 094a150956..4b4e4663ab 100644 --- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs +++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs @@ -36,16 +36,13 @@ namespace ICSharpCode.Core.Presentation readonly string inputGestureText; readonly IEnumerable conditions; - public ToolBarButton(UIElement inputBindingOwner, Codon codon, object caller, bool createCommand, IReadOnlyCollection conditions) + public ToolBarButton(UIElement inputBindingOwner, Codon codon, object caller, IReadOnlyCollection conditions) { ToolTipService.SetShowOnDisabled(this, true); this.codon = codon; this.caller = caller; - if (createCommand) - this.Command = CommandWrapper.CreateCommand(codon, conditions); - else - this.Command = CommandWrapper.CreateLazyCommand(codon, conditions); + this.Command = CommandWrapper.CreateLazyCommand(codon, conditions); this.CommandParameter = caller; this.Content = ToolBarService.CreateToolBarItemContent(codon); this.conditions = conditions; diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs index 9c0d128fe8..dce695ec80 100644 --- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs +++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs @@ -65,15 +65,13 @@ namespace ICSharpCode.Core.Presentation object caller = descriptor.Parameter; string type = codon.Properties.Contains("type") ? codon.Properties["type"] : "Item"; - bool createCommand = codon.Properties["loadclasslazy"] == "false"; - switch (type) { case "Separator": return new ConditionalSeparator(codon, caller, true, descriptor.Conditions); case "CheckBox": return new ToolBarCheckBox(codon, caller, descriptor.Conditions); case "Item": - return new ToolBarButton(inputBindingOwner, codon, caller, createCommand, descriptor.Conditions); + return new ToolBarButton(inputBindingOwner, codon, caller, descriptor.Conditions); case "DropDownButton": return new ToolBarDropDownButton( codon, caller, MenuService.CreateUnexpandedMenuItems( diff --git a/src/Main/ICSharpCode.Core.WinForms/Menu/MenuCommand.cs b/src/Main/ICSharpCode.Core.WinForms/Menu/MenuCommand.cs index b8d2fc061f..92169ca890 100644 --- a/src/Main/ICSharpCode.Core.WinForms/Menu/MenuCommand.cs +++ b/src/Main/ICSharpCode.Core.WinForms/Menu/MenuCommand.cs @@ -43,23 +43,13 @@ namespace ICSharpCode.Core.WinForms } public MenuCommand(Codon codon, object caller, IReadOnlyCollection conditions) - : this(codon, caller, false, conditions) - { - - } - - public MenuCommand(Codon codon, object caller, bool createCommand, IReadOnlyCollection conditions) { this.RightToLeft = RightToLeft.Inherit; this.caller = caller; this.codon = codon; this.conditions = conditions; - if (createCommand) { - this.command = CommandWrapper.CreateCommand(codon, conditions); - } else { - this.command = CommandWrapper.CreateLazyCommand(codon, conditions); - } + this.command = CommandWrapper.CreateLazyCommand(codon, conditions); UpdateText(); } diff --git a/src/Main/ICSharpCode.Core.WinForms/Menu/MenuService.cs b/src/Main/ICSharpCode.Core.WinForms/Menu/MenuService.cs index d6237501a1..f82aa51fb2 100644 --- a/src/Main/ICSharpCode.Core.WinForms/Menu/MenuService.cs +++ b/src/Main/ICSharpCode.Core.WinForms/Menu/MenuService.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.Core.WinForms return new MenuCheckBox(codon, descriptor.Parameter, descriptor.Conditions); case "Item": case "Command": - return new MenuCommand(codon, descriptor.Parameter, createCommand, descriptor.Conditions); + return new MenuCommand(codon, descriptor.Parameter, descriptor.Conditions); case "Menu": return new Menu(codon, descriptor.Parameter, ConvertSubItems(descriptor.SubItems), descriptor.Conditions); case "Builder": From 904373afe228f7340d3136a24ac18fa419c55e82 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 3 Aug 2014 20:06:12 +0200 Subject: [PATCH 10/19] fix #234: Short cuts/toolbar actions do not always work in non-WPF view contents --- .../Project/Src/View/HexEditContainer.cs | 4 --- .../HexEditor/Project/Src/View/HexEditView.cs | 25 ++++++++++--------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditContainer.cs b/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditContainer.cs index 3d06983640..2f4b077f7b 100644 --- a/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditContainer.cs +++ b/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditContainer.cs @@ -34,10 +34,6 @@ namespace HexEditor.View get { return hexEditControl.HasSomethingSelected; } } - public bool EditorFocused { - get { return hexEditControl.Focused; } - } - public bool CanUndo { get { return hexEditControl.CanUndo; } } diff --git a/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditView.cs b/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditView.cs index 63e4e00b04..bfe4d78981 100644 --- a/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditView.cs +++ b/src/AddIns/DisplayBindings/HexEditor/Project/Src/View/HexEditView.cs @@ -18,10 +18,8 @@ using System; using System.IO; -using ICSharpCode.Core; -using ICSharpCode.Core.WinForms; +using System.Windows.Input; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.WinForms; using ICSharpCode.SharpDevelop.Workbench; @@ -34,7 +32,8 @@ namespace HexEditor.View public HexEditView(OpenedFile file) { hexEditContainer = new HexEditContainer(); - hexEditContainer.hexEditControl.DocumentChanged += new EventHandler(DocumentChanged); + hexEditContainer.hexEditControl.DocumentChanged += DocumentChanged; + hexEditContainer.hexEditControl.Selection.SelectionChanged += SelectionChanged; this.Files.Add(file); @@ -67,23 +66,23 @@ namespace HexEditor.View #region IClipboardHandler public bool EnableCut { - get { return hexEditContainer.HasSomethingSelected & hexEditContainer.EditorFocused; } + get { return hexEditContainer.HasSomethingSelected; } } public bool EnableCopy { - get { return hexEditContainer.HasSomethingSelected & hexEditContainer.EditorFocused; } + get { return hexEditContainer.HasSomethingSelected; } } public bool EnablePaste { - get { return hexEditContainer.EditorFocused; } + get { return true; } } public bool EnableDelete { - get { return hexEditContainer.HasSomethingSelected & hexEditContainer.EditorFocused; } + get { return hexEditContainer.HasSomethingSelected; } } public bool EnableSelectAll { - get { return hexEditContainer.EditorFocused; } + get { return true; } } public void Cut() @@ -137,10 +136,12 @@ namespace HexEditor.View void DocumentChanged(object sender, EventArgs e) { if (PrimaryFile != null) PrimaryFile.MakeDirty(); + CommandManager.InvalidateRequerySuggested(); } - - public override bool IsDirty { - get { return base.IsDirty; } + + void SelectionChanged(object sender, System.EventArgs e) + { + CommandManager.InvalidateRequerySuggested(); } } } From 6c0d5d256102e7fe724899306d1abc5201744db5 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 9 Aug 2014 14:33:20 +0200 Subject: [PATCH 11/19] Remove weird extension method that was only used in a single place. --- .../FormsDesigner/Project/Src/ToolboxProvider.cs | 9 ++++++++- src/Main/Base/Project/Util/SharpDevelopExtensions.cs | 11 ----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/ToolboxProvider.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/ToolboxProvider.cs index 149daee471..2260b563ee 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/ToolboxProvider.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/ToolboxProvider.cs @@ -136,6 +136,13 @@ namespace ICSharpCode.FormsDesigner toolboxService.SetSelectedToolboxItem(null); } + static ICompilation GetCompilationForCurrentProject() + { + IProject project = SD.ProjectService.CurrentProject; + if (project == null) return null; + return SD.ParserService.GetCompilation(project); + } + static void SelectedToolUsedHandler(object sender, EventArgs e) { SD.Log.Debug("SelectedToolUsedHandler"); @@ -148,7 +155,7 @@ namespace ICSharpCode.FormsDesigner if (selectedItem != null && selectedItem.TypeName != null) { SD.Log.Debug("Checking for reference to CustomComponent: " + selectedItem.TypeName); // Check current project has the custom component first. - ICompilation currentCompilation = SD.ParserService.GetCompilationForCurrentProject(); + ICompilation currentCompilation = GetCompilationForCurrentProject(); var typeName = new FullTypeName(selectedItem.TypeName); if (currentCompilation != null && currentCompilation.FindType(typeName).Kind == TypeKind.Unknown) { // Check other projects in the solution. diff --git a/src/Main/Base/Project/Util/SharpDevelopExtensions.cs b/src/Main/Base/Project/Util/SharpDevelopExtensions.cs index 6f320ecf9f..81e1afb7a0 100644 --- a/src/Main/Base/Project/Util/SharpDevelopExtensions.cs +++ b/src/Main/Base/Project/Util/SharpDevelopExtensions.cs @@ -902,17 +902,6 @@ namespace ICSharpCode.SharpDevelop } #endregion - #region Service Extensions - public static ICompilation GetCompilationForCurrentProject(this IParserService svc) - { - if (svc == null) - throw new ArgumentNullException("svc"); - IProject project = SD.ProjectService.CurrentProject; - if (project == null) return null; - return SD.ParserService.GetCompilation(project); - } - #endregion - #region Resource Service Extensions /// /// Gets an from a resource. From e98a46da008e1b0a5c8a3f8b06873ee7ea943ddb Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 9 Aug 2014 08:22:55 +0200 Subject: [PATCH 12/19] allow public use of indentation-alignment logic from TextMarkerToolTipProvider --- .../Src/TextMarkerToolTipProvider.cs | 59 +------------ src/Main/Base/Project/Editor/ToolTipUtils.cs | 86 +++++++++++++++++++ .../Project/ICSharpCode.SharpDevelop.csproj | 1 + 3 files changed, 88 insertions(+), 58 deletions(-) create mode 100644 src/Main/Base/Project/Editor/ToolTipUtils.cs diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerToolTipProvider.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerToolTipProvider.cs index 3ca357cbca..75f85d8011 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerToolTipProvider.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerToolTipProvider.cs @@ -67,64 +67,7 @@ namespace ICSharpCode.AvalonEdit.AddIn string GetTooltipTextForCollapsedSection(ToolTipRequestEventArgs args, FoldingSection foldingSection) { - // This fixes SD-1394: - // Each line is checked for leading indentation whitespaces. If - // a line has the same or more indentation than the first line, - // it is reduced. If a line is less indented than the first line - // the indentation is removed completely. - // - // See the following example: - // line 1 - // line 2 - // line 3 - // line 4 - // - // is reduced to: - // line 1 - // line 2 - // line 3 - // line 4 - - const int maxLineCount = 15; - - TextDocument document = (TextDocument)args.Editor.Document; - int startOffset = foldingSection.StartOffset; - int endOffset = foldingSection.EndOffset; - - DocumentLine startLine = document.GetLineByOffset(startOffset); - DocumentLine endLine = document.GetLineByOffset(endOffset); - StringBuilder builder = new StringBuilder(); - - DocumentLine current = startLine; - ISegment startIndent = TextUtilities.GetLeadingWhitespace(document, startLine); - int lineCount = 0; - while (current != endLine.NextLine && lineCount < maxLineCount) { - ISegment currentIndent = TextUtilities.GetLeadingWhitespace(document, current); - - if (current == startLine && current == endLine) - builder.Append(document.GetText(startOffset, endOffset - startOffset)); - else if (current == startLine) { - if (current.EndOffset - startOffset > 0) - builder.AppendLine(document.GetText(startOffset, current.EndOffset - startOffset).TrimStart()); - } else if (current == endLine) { - if (startIndent.Length <= currentIndent.Length) - builder.Append(document.GetText(current.Offset + startIndent.Length, endOffset - current.Offset - startIndent.Length)); - else - builder.Append(document.GetText(current.Offset + currentIndent.Length, endOffset - current.Offset - currentIndent.Length)); - } else { - if (startIndent.Length <= currentIndent.Length) - builder.AppendLine(document.GetText(current.Offset + startIndent.Length, current.Length - startIndent.Length)); - else - builder.AppendLine(document.GetText(current.Offset + currentIndent.Length, current.Length - currentIndent.Length)); - } - - current = current.NextLine; - lineCount++; - } - if (current != endLine.NextLine) - builder.Append("..."); - - return builder.ToString(); + return ToolTipUtils.GetAlignedText(args.Editor.Document, foldingSection.StartOffset, foldingSection.EndOffset); } } } diff --git a/src/Main/Base/Project/Editor/ToolTipUtils.cs b/src/Main/Base/Project/Editor/ToolTipUtils.cs new file mode 100644 index 0000000000..34ab466ce1 --- /dev/null +++ b/src/Main/Base/Project/Editor/ToolTipUtils.cs @@ -0,0 +1,86 @@ +// 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.Text; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.NRefactory.Editor; + +namespace ICSharpCode.SharpDevelop.Editor +{ + public static class ToolTipUtils + { + public static string GetAlignedText(IDocument document, int startOffset, int endOffset, int maxLineCount = 15) + { + // This fixes SD-1394: + // Each line is checked for leading indentation whitespaces. If + // a line has the same or more indentation than the first line, + // it is reduced. If a line is less indented than the first line + // the indentation is removed completely. + // + // See the following example: + // line 1 + // line 2 + // line 3 + // line 4 + // + // is reduced to: + // line 1 + // line 2 + // line 3 + // line 4 + + if (maxLineCount < 1) + maxLineCount = int.MaxValue; + + IDocumentLine startLine = document.GetLineByOffset(startOffset); + IDocumentLine endLine = document.GetLineByOffset(endOffset); + StringBuilder builder = new StringBuilder(); + + IDocumentLine current = startLine; + ISegment startIndent = TextUtilities.GetWhitespaceAfter(document, startLine.Offset); + int lineCount = 0; + while (current != endLine.NextLine && lineCount < maxLineCount) { + ISegment currentIndent = TextUtilities.GetWhitespaceAfter(document, current.Offset); + + if (current == startLine && current == endLine) + builder.Append(document.GetText(startOffset, endOffset - startOffset)); + else if (current == startLine) { + if (current.EndOffset - startOffset > 0) + builder.AppendLine(document.GetText(startOffset, current.EndOffset - startOffset).TrimStart()); + } else if (current == endLine) { + if (startIndent.Length <= currentIndent.Length) + builder.Append(document.GetText(current.Offset + startIndent.Length, endOffset - current.Offset - startIndent.Length)); + else + builder.Append(document.GetText(current.Offset + currentIndent.Length, endOffset - current.Offset - currentIndent.Length)); + } else { + if (startIndent.Length <= currentIndent.Length) + builder.AppendLine(document.GetText(current.Offset + startIndent.Length, current.Length - startIndent.Length)); + else + builder.AppendLine(document.GetText(current.Offset + currentIndent.Length, current.Length - currentIndent.Length)); + } + + current = current.NextLine; + lineCount++; + } + if (current != endLine.NextLine) + builder.Append("..."); + + return builder.ToString(); + } + } +} diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index ee778929a9..8013c235ff 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -171,6 +171,7 @@ ToolTipService.cs + From 07870409a3a5a1840b2f0f1ae3e1af345e7a7fc8 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 10 Aug 2014 16:53:25 +0200 Subject: [PATCH 13/19] use "git add --intent-to-add" --- src/AddIns/VersionControl/GitAddIn/Src/Git.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AddIns/VersionControl/GitAddIn/Src/Git.cs b/src/AddIns/VersionControl/GitAddIn/Src/Git.cs index a7480c487f..d2a0e063fa 100644 --- a/src/AddIns/VersionControl/GitAddIn/Src/Git.cs +++ b/src/AddIns/VersionControl/GitAddIn/Src/Git.cs @@ -59,7 +59,7 @@ namespace ICSharpCode.GitAddIn string wcRoot = FindWorkingCopyRoot(fileName); if (wcRoot == null) return Task.FromResult(false); - return RunGitAsync(wcRoot, "add", AdaptFileName(wcRoot, fileName)); + return RunGitAsync(wcRoot, "add", "--intent-to-add", AdaptFileName(wcRoot, fileName)); } public static Task RemoveAsync(string fileName, bool indexOnly) From 5810bb51e036e13bccc17e78576a99834baee3b5 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 10 Aug 2014 18:22:43 +0200 Subject: [PATCH 14/19] Fix #529: CC item creating an event handler has confusing name 'HandleHandleClick' Because EventCreationCompletionData uses a new SDRefactoringContext with a different compilation, import the delegateType into the new compilation so that CreateShortType() works as expected. --- .../Completion/EventCreationCompletionData.cs | 44 ++++++------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/EventCreationCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/EventCreationCompletionData.cs index 01ab271a64..6c9af001b8 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/EventCreationCompletionData.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/EventCreationCompletionData.cs @@ -19,6 +19,7 @@ using System; using System.Linq; using System.Threading; +using System.Windows.Controls; using ICSharpCode.SharpDevelop; using CSharpBinding.Parser; using CSharpBinding.Refactoring; @@ -35,46 +36,27 @@ namespace CSharpBinding.Completion /// class EventCreationCompletionData : CompletionData { - IEvent eventDefinition; - string varName; - IType delegateType; - string parameterList; - IUnresolvedMember callingMember; - IUnresolvedTypeDefinition declaringType; - CSharpResolver contextAtCaret; + readonly string handlerName; + readonly ITypeReference delegateTypeReference; + readonly bool isStatic; - public EventCreationCompletionData(string varName, IType delegateType, IEvent evt, string parameterList, IUnresolvedMember callingMember, IUnresolvedTypeDefinition declaringType, CSharpResolver contextAtCaret) + public EventCreationCompletionData(string handlerName, IType delegateType, IEvent evt, string parameterList, IUnresolvedMember callingMember, IUnresolvedTypeDefinition declaringType, CSharpResolver contextAtCaret) { - if (string.IsNullOrEmpty(varName)) { - this.DisplayText = ""; + if (string.IsNullOrEmpty(handlerName)) { + handlerName = (evt != null ? evt.Name : "Handle"); } - else { - this.DisplayText = "Handle" + char.ToUpper(varName[0]) + varName.Substring(1) + (evt != null ? evt.Name : ""); - } - - this.varName = varName; - this.eventDefinition = evt; - this.delegateType = delegateType; - this.parameterList = parameterList; - this.callingMember = callingMember; - this.declaringType = declaringType; - this.contextAtCaret = contextAtCaret; + this.handlerName = handlerName; + this.DisplayText = ""; + this.delegateTypeReference = delegateType.ToTypeReference(); + this.isStatic = callingMember != null && callingMember.IsStatic; } public override void Complete(CompletionContext context) { - var invokeSignature = delegateType.GetMethods(m => m.Name == "Invoke").Single(); var refactoringContext = SDRefactoringContext.Create(context.Editor, CancellationToken.None); + var delegateType = delegateTypeReference.Resolve(refactoringContext.Compilation); + var invokeSignature = delegateType.GetMethods(m => m.Name == "Invoke").Single(); var builder = refactoringContext.CreateTypeSystemAstBuilder(); - string handlerName; - bool isStatic; - if (eventDefinition != null) { - handlerName = eventDefinition.Name; - isStatic = eventDefinition.IsStatic; - } else { - handlerName = varName; - isStatic = callingMember.IsStatic; - } var throwStatement = new ThrowStatement(); var decl = new MethodDeclaration { From 71e2387f0d91d58be4cba011fece6975ff066b59 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 10 Aug 2014 21:46:55 +0200 Subject: [PATCH 15/19] Fix part of #525 --- .../Project/Src/DesignerViewContent.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs index d96f5f47fc..7713964875 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs @@ -50,6 +50,7 @@ namespace ICSharpCode.FormsDesigner readonly Control pleaseWaitLabel = new Label() { Text = StringParser.Parse("${res:Global.PleaseWait}"), TextAlign=ContentAlignment.MiddleCenter }; DesignSurface designSurface; bool disposing; + Timer timer = new Timer { Interval = 200 }; readonly IViewContent primaryViewContent; readonly IDesignerLoaderProvider loaderProvider; @@ -142,10 +143,11 @@ namespace ICSharpCode.FormsDesigner this.IsActiveViewContentChanged += this.IsActiveViewContentChangedHandler; + timer.Tick += Timer_Tick; FileService.FileRemoving += this.FileServiceFileRemoving; SD.Debugger.DebugStarting += this.DebugStarting; } - + public FormsDesignerViewContent(IViewContent primaryViewContent, IDesignerLoaderProvider loaderProvider) : this(primaryViewContent) { @@ -168,6 +170,20 @@ namespace ICSharpCode.FormsDesigner this.Files.Add(primaryViewContent.PrimaryFile); } + void Timer_Tick(object sender, System.EventArgs e) + { + // The WinForms designer internally relies on Application.Idle for some actions, e.g. 'Show Code' + // This event does not get raised in a WPF application. + // While we do forward WPF's equivalent idle event to WinForms (see WorkbenchStartup.cs), + // it doesn't happen often enough -- in particular, it doesn't get raised while the mouse + // is over the WinForms design surface. + // This caused the bug: https://github.com/icsharpcode/SharpDevelop/issues/525 + // As a workaround, we use a timer to raise the event while the designer is open. + // Note: this timer is implemented in the WinForms designer and not globally in SharpDevelop + // so that we don't wake up the CPU unnecessarily when the designer is not in use. + Application.RaiseIdle(e); + } + bool inMasterLoadOperation; protected override void LoadInternal(OpenedFile file, System.IO.Stream stream) @@ -344,6 +360,7 @@ namespace ICSharpCode.FormsDesigner UpdatePropertyPad(); hasUnmergedChanges = false; + timer.Start(); LoggingService.Info("Form Designer: END INITIALIZE"); } @@ -404,6 +421,7 @@ namespace ICSharpCode.FormsDesigner { LoggingService.Debug("FormsDesigner unloading, setting ActiveDesignSurface to null"); designSurfaceManager.ActiveDesignSurface = null; + timer.Stop(); bool savedIsDirty = (this.DesignerCodeFile == null) ? false : this.DesignerCodeFile.IsDirty; this.UserContent = this.pleaseWaitLabel; From 4be799023b71f80306fe5ae7d8b128bcafb077e2 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 10 Aug 2014 22:31:43 +0200 Subject: [PATCH 16/19] Fix #533: Use a mutex to prevent concurrent git add/rm calls. --- src/AddIns/VersionControl/GitAddIn/Src/Git.cs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/AddIns/VersionControl/GitAddIn/Src/Git.cs b/src/AddIns/VersionControl/GitAddIn/Src/Git.cs index d2a0e063fa..48b2f66ff3 100644 --- a/src/AddIns/VersionControl/GitAddIn/Src/Git.cs +++ b/src/AddIns/VersionControl/GitAddIn/Src/Git.cs @@ -18,6 +18,7 @@ using System; using System.IO; +using System.Threading; using System.Threading.Tasks; using ICSharpCode.Core; using ICSharpCode.SharpDevelop; @@ -79,14 +80,24 @@ namespace ICSharpCode.GitAddIn return relFileName.Replace('\\', '/'); } - public static Task RunGitAsync(string workingDir, params string[] arguments) + static SemaphoreSlim gitMutex = new SemaphoreSlim(1); + + public static async Task RunGitAsync(string workingDir, params string[] arguments) { string git = FindGit(); if (git == null) - return Task.FromResult(9009); - ProcessRunner p = new ProcessRunner(); - p.WorkingDirectory = workingDir; - return p.RunInOutputPadAsync(GitMessageView.Category, git, arguments); + return 9009; + // Wait until other git calls have finished running + // This prevents git from failing due to a locked index when several files + // are added concurrently + await gitMutex.WaitAsync(); + try { + ProcessRunner p = new ProcessRunner(); + p.WorkingDirectory = workingDir; + await p.RunInOutputPadAsync(GitMessageView.Category, git, arguments); + } finally { + gitMutex.Release(); + } } /// From 582d996f284414c86e09de58d533dfef56019a44 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 10 Aug 2014 21:38:56 +0200 Subject: [PATCH 17/19] fix #530: Missing whitespace in XML Doc tooltips --- src/Main/Base/Project/Editor/DocumentationUIBuilder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Main/Base/Project/Editor/DocumentationUIBuilder.cs b/src/Main/Base/Project/Editor/DocumentationUIBuilder.cs index d26efceae3..5934abaa8f 100644 --- a/src/Main/Base/Project/Editor/DocumentationUIBuilder.cs +++ b/src/Main/Base/Project/Editor/DocumentationUIBuilder.cs @@ -453,6 +453,7 @@ namespace ICSharpCode.SharpDevelop.Editor AddBlock(para); } inlineCollection.Add(inline); + ignoreWhitespace = false; } public void AddBlock(Block block) From 2256606360b56a7a87b21fac65dd22275b145991 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 10 Aug 2014 22:29:00 +0200 Subject: [PATCH 18/19] raise FileCreated events for all newly-created files when creating a new solution/project --- src/Main/Base/Project/Templates/ProjectTemplate.cs | 1 + src/Main/SharpDevelop/Templates/Project/ProjectDescriptor.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/Main/Base/Project/Templates/ProjectTemplate.cs b/src/Main/Base/Project/Templates/ProjectTemplate.cs index bd02c5197f..9f27029185 100644 --- a/src/Main/Base/Project/Templates/ProjectTemplate.cs +++ b/src/Main/Base/Project/Templates/ProjectTemplate.cs @@ -70,6 +70,7 @@ namespace ICSharpCode.SharpDevelop.Templates if (SD.ProjectService.OpenSolution(createdSolution)) { solutionOpened = true; SD.GetRequiredService().RaiseSolutionCreated(new SolutionEventArgs(createdSolution)); + FileService.FireFileCreated(solutionFileName, false); return result; } else { return null; diff --git a/src/Main/SharpDevelop/Templates/Project/ProjectDescriptor.cs b/src/Main/SharpDevelop/Templates/Project/ProjectDescriptor.cs index 4b4a49761a..9804a08ef6 100644 --- a/src/Main/SharpDevelop/Templates/Project/ProjectDescriptor.cs +++ b/src/Main/SharpDevelop/Templates/Project/ProjectDescriptor.cs @@ -514,6 +514,7 @@ namespace ICSharpCode.SharpDevelop.Templates file.SetProjectItemProperties(projectFile); project.Items.Add(projectFile); + FileService.FireFileCreated(fileName, false); } } @@ -535,6 +536,7 @@ namespace ICSharpCode.SharpDevelop.Templates project.ProjectLoaded(); SD.GetRequiredService().RaiseProjectCreated(new ProjectEventArgs(project)); + FileService.FireFileCreated(project.FileName, false); templateResults.NewProjects.Add(project); success = true; return true; From 8ae347fd0ae218d2f2fff853dec2a4859165cd5b Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 10 Aug 2014 22:43:13 +0200 Subject: [PATCH 19/19] Fix build. --- src/AddIns/VersionControl/GitAddIn/Src/Git.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AddIns/VersionControl/GitAddIn/Src/Git.cs b/src/AddIns/VersionControl/GitAddIn/Src/Git.cs index 48b2f66ff3..8c2740fbe7 100644 --- a/src/AddIns/VersionControl/GitAddIn/Src/Git.cs +++ b/src/AddIns/VersionControl/GitAddIn/Src/Git.cs @@ -94,7 +94,7 @@ namespace ICSharpCode.GitAddIn try { ProcessRunner p = new ProcessRunner(); p.WorkingDirectory = workingDir; - await p.RunInOutputPadAsync(GitMessageView.Category, git, arguments); + return await p.RunInOutputPadAsync(GitMessageView.Category, git, arguments); } finally { gitMutex.Release(); }