jkuehner 11 years ago
parent
commit
90f3fc3fe0
  1. 6
      src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsReader.cs
  2. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  3. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  4. 278
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
  5. 253
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpTextEditorExtension.cs
  6. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs
  7. 49
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs
  8. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
  9. 3
      src/AddIns/Debugger/Debugger.AddIn/Breakpoints/BreakpointEditorPopup.xaml.cs
  10. 18
      src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs
  11. 5
      src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs
  12. 156
      src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs
  13. 2
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  14. 3
      src/AddIns/VersionControl/GitAddIn/Src/Git.cs
  15. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Uncategorized/UseOfMemberOfNullReference.cs
  16. 3
      src/Libraries/SharpTreeView/ICSharpCode.TreeView/SharpTreeViewItem.cs
  17. 12
      src/Main/Base/Project/Parser/ProjectContentContainer.cs
  18. 2
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  19. 2
      src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs
  20. 5
      src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs
  21. 8
      src/Main/SharpDevelop/Parser/ParserService.cs
  22. 96
      src/Main/SharpDevelop/Parser/ParserServiceEntry.cs
  23. 12
      src/Tools/StressTest/StressTest.sln
  24. 3
      src/Tools/StressTest/StressTest/StressTest.csproj
  25. 1
      src/Tools/StressTest/StressTest/UserControl.xaml.cs

6
src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsReader.cs

@ -61,8 +61,10 @@ namespace ICSharpCode.UnitTesting
public void Dispose() public void Dispose()
{ {
reader.Dispose(); if (reader != null)
namedPipe.Dispose(); reader.Dispose();
if (namedPipe != null)
namedPipe.Dispose();
} }
public event EventHandler<TestFinishedEventArgs> TestFinished; public event EventHandler<TestFinishedEventArgs> TestFinished;

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin

@ -363,7 +363,6 @@
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseIsOperatorIssue" /> <Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseIsOperatorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseMethodAnyIssue" /> <Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseMethodAnyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseMethodIsInstanceOfTypeIssue" /> <Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseMethodIsInstanceOfTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseOfMemberOfNullReference" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ValueParameterNotUsedIssue" /> <Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ValueParameterNotUsedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.XmlDocIssue" /> <Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.XmlDocIssue" />
</Path> </Path>

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -91,6 +91,7 @@
<Compile Include="Src\CSharpSemanticHighlighterVisitor.cs"> <Compile Include="Src\CSharpSemanticHighlighterVisitor.cs">
<DependentUpon>CSharpSemanticHighlighter.cs</DependentUpon> <DependentUpon>CSharpSemanticHighlighter.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Src\CSharpTextEditorExtension.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingOptionsContainer.cs" /> <Compile Include="Src\FormattingStrategy\CSharpFormattingOptionsContainer.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormatter.cs" /> <Compile Include="Src\FormattingStrategy\CSharpFormatter.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingPolicies.cs" /> <Compile Include="Src\FormattingStrategy\CSharpFormattingPolicies.cs" />

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

@ -20,13 +20,18 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.SharpDevelop.Project;
using CSharpBinding.Completion; using CSharpBinding.Completion;
using CSharpBinding.FormattingStrategy; using CSharpBinding.FormattingStrategy;
using CSharpBinding.Refactoring; using CSharpBinding.Refactoring;
@ -50,223 +55,98 @@ namespace CSharpBinding
this.container.AddService(typeof(System.CodeDom.Compiler.CodeDomProvider), new Microsoft.CSharp.CSharpCodeProvider()); this.container.AddService(typeof(System.CodeDom.Compiler.CodeDomProvider), new Microsoft.CSharp.CSharpCodeProvider());
} }
public override ICodeCompletionBinding CreateCompletionBinding(FileName fileName, TextLocation currentLocation, ICSharpCode.NRefactory.Editor.ITextSource fileContent) public override ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context)
{ {
if (fileName == null) if (fileName == null)
throw new ArgumentNullException("fileName"); throw new ArgumentNullException("fileName");
return new CSharpCompletionBinding(fileName, currentLocation, fileContent); if (context == null)
throw new ArgumentNullException("context");
string content = GeneratePartialClassContextStub(fileName, location, 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());
} }
}
public class CSharpTextEditorExtension : ITextEditorExtension
{
ITextEditor editor;
IssueManager inspectionManager;
IList<IContextActionProvider> contextActionProviders;
CodeManipulation codeManipulation;
CaretReferenceHighlightRenderer renderer;
CodeEditorFormattingOptionsAdapter options;
TextEditorOptions originalEditorOptions;
public void Attach(ITextEditor editor)
{
this.editor = editor;
inspectionManager = new IssueManager(editor);
codeManipulation = new CodeManipulation(editor);
renderer = new CaretReferenceHighlightRenderer(editor);
// Patch editor options (indentation) to project-specific settings
if (!editor.ContextActionProviders.IsReadOnly) {
contextActionProviders = AddInTree.BuildItems<IContextActionProvider>("/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));
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
options = new CodeEditorFormattingOptionsAdapter(textEditor.Options, editor.Options, formattingPolicy.OptionsContainer);
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.TextEditorOptions;
}
}
public void Detach()
{
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
var textView = textEditor.TextArea.TextView;
// Unregister our ITextEditorOptions instance from editor
var optionsService = textView.GetService<ITextEditorOptions>();
if ((optionsService != null) && (optionsService == options))
textView.Services.RemoveService(typeof(ITextEditorOptions));
// Reset TextEditor options, too?
if ((textEditor.Options != null) && (textEditor.Options == options.TextEditorOptions))
textEditor.Options = originalEditorOptions;
}
codeManipulation.Dispose();
if (inspectionManager != null) {
inspectionManager.Dispose();
inspectionManager = null;
}
if (contextActionProviders != null) {
editor.ContextActionProviders.RemoveAll(contextActionProviders.Contains);
}
renderer.Dispose();
options = null;
this.editor = null;
}
}
class CodeEditorFormattingOptionsAdapter : ITextEditorOptions, INotifyPropertyChanged
{
CSharpFormattingOptionsContainer container;
readonly TextEditorOptions avalonEditOptions;
readonly TextEditorOptions originalAvalonEditOptions;
readonly ITextEditorOptions originalSDOptions;
public CodeEditorFormattingOptionsAdapter(TextEditorOptions originalAvalonEditOptions, ITextEditorOptions originalSDOptions, CSharpFormattingOptionsContainer container)
{
if (originalAvalonEditOptions == null)
throw new ArgumentNullException("originalAvalonEditOptions");
if (originalSDOptions == null)
throw new ArgumentNullException("originalSDOptions");
if (container == null)
throw new ArgumentNullException("container");
this.originalAvalonEditOptions = originalAvalonEditOptions;
this.avalonEditOptions = new TextEditorOptions(originalAvalonEditOptions);
this.originalSDOptions = originalSDOptions;
this.container = container;
// Update overridden options once static string GeneratePartialClassContextStub(FileName fileName, TextLocation location, ICodeContext context)
UpdateOverriddenProperties();
CSharpFormattingPolicies.Instance.FormattingPolicyUpdated += OnFormattingPolicyUpdated;
this.originalAvalonEditOptions.PropertyChanged += OnOrigAvalonOptionsPropertyChanged;
this.originalSDOptions.PropertyChanged += OnSDOptionsPropertyChanged;
}
void OnFormattingPolicyUpdated(object sender, CSharpBinding.FormattingStrategy.CSharpFormattingPolicyUpdateEventArgs e)
{ {
// Update editor options from changed policy var compilation = SD.ParserService.GetCompilationForFile(fileName);
UpdateOverriddenProperties(); var file = SD.ParserService.GetExistingUnresolvedFile(fileName);
if (compilation == null || file == null)
OnPropertyChanged("IndentationSize"); return "";
OnPropertyChanged("IndentationString"); var unresolvedMember = file.GetMember(location);
OnPropertyChanged("ConvertTabsToSpaces"); if (unresolvedMember == null)
} return "";
var member = unresolvedMember.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly));
void UpdateOverriddenProperties() if (member == null)
{ return "";
avalonEditOptions.IndentationSize = container.GetEffectiveIndentationSize() ?? originalSDOptions.IndentationSize; var builder = new TypeSystemAstBuilder();
avalonEditOptions.ConvertTabsToSpaces = container.GetEffectiveConvertTabsToSpaces() ?? originalSDOptions.ConvertTabsToSpaces; MethodDeclaration decl;
} if (unresolvedMember is IMethod) {
// If it's a method, convert it directly (including parameters + type parameters)
void OnOrigAvalonOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) decl = (MethodDeclaration)builder.ConvertEntity(member);
{
if ((e.PropertyName != "IndentationSize") && (e.PropertyName != "IndentationString") && (e.PropertyName != "ConvertTabsToSpaces")) {
// Update values in our own TextEditorOptions instance
PropertyInfo propertyInfo = typeof(TextEditorOptions).GetProperty(e.PropertyName);
if (propertyInfo != null) {
propertyInfo.SetValue(avalonEditOptions, propertyInfo.GetValue(originalAvalonEditOptions));
}
} else { } else {
UpdateOverriddenProperties(); // Otherwise, create a method anyways, and copy the parameters
decl = new MethodDeclaration();
if (member is IParameterizedMember) {
foreach (var p in ((IParameterizedMember)member).Parameters) {
decl.Parameters.Add(builder.ConvertParameter(p));
}
}
} }
OnPropertyChanged(e.PropertyName); decl.Name = "__DebuggerStub__";
decl.ReturnType = builder.ConvertType(member.ReturnType);
decl.Modifiers = unresolvedMember.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();
} }
void OnSDOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) static BlockStatement GenerateBodyFromContext(TypeSystemAstBuilder builder, IVariable[] variables)
{ {
OnPropertyChanged(e.PropertyName); var body = new BlockStatement();
foreach (var v in variables)
body.Statements.Add(new VariableDeclarationStatement(builder.ConvertType(v.Type), v.Name));
body.Statements.Add(new ExpressionStatement(new IdentifierExpression("$__Caret_Point__$")));
return body;
} }
public event PropertyChangedEventHandler PropertyChanged; static AstNode WrapInType(IUnresolvedTypeDefinition entity, EntityDeclaration decl)
void OnPropertyChanged(string propertyName)
{ {
if (PropertyChanged != null) { if (entity == null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); return decl;
} // Wrap decl in TypeDeclaration
decl = new TypeDeclaration {
ClassType = GetClassType(entity),
Modifiers = Modifiers.Partial,
Name = entity.Name,
Members = { decl }
};
if (entity.DeclaringTypeDefinition != null) {
// Handle nested types
return WrapInType(entity.DeclaringTypeDefinition, decl);
}
if (string.IsNullOrEmpty(entity.Namespace))
return decl;
return new NamespaceDeclaration(entity.Namespace) {
Members = {
decl
}
};
} }
public TextEditorOptions TextEditorOptions static ClassType GetClassType(IUnresolvedTypeDefinition entity)
{ {
get { switch (entity.Kind) {
return avalonEditOptions; case TypeKind.Interface:
} return ClassType.Interface;
} case TypeKind.Struct:
return ClassType.Struct;
#region Overridden properties default:
return ClassType.Class;
public int IndentationSize {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationSize;
} }
} }
public string IndentationString {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationString;
}
}
public bool ConvertTabsToSpaces {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.ConvertTabsToSpaces;
}
}
#endregion
#region Rest of ITextEditorOptions implementation
public bool AutoInsertBlockEnd {
get {
return originalSDOptions.AutoInsertBlockEnd;
}
}
public int VerticalRulerColumn {
get {
return originalSDOptions.VerticalRulerColumn;
}
}
public bool UnderlineErrors {
get {
return originalSDOptions.UnderlineErrors;
}
}
public string FontFamily {
get {
return originalSDOptions.FontFamily;
}
}
public double FontSize {
get {
return originalSDOptions.FontSize;
}
}
#endregion
} }
} }

253
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpTextEditorExtension.cs

@ -0,0 +1,253 @@
// 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 System.ComponentModel;
using System.Linq;
using System.Reflection;
using ICSharpCode.AvalonEdit;
using CSharpBinding.FormattingStrategy;
using CSharpBinding.Refactoring;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
namespace CSharpBinding
{
public class CSharpTextEditorExtension : ITextEditorExtension
{
ITextEditor editor;
IssueManager inspectionManager;
IList<IContextActionProvider> contextActionProviders;
CodeManipulation codeManipulation;
CaretReferenceHighlightRenderer renderer;
CodeEditorFormattingOptionsAdapter options;
TextEditorOptions originalEditorOptions;
public void Attach(ITextEditor editor)
{
this.editor = editor;
inspectionManager = new IssueManager(editor);
codeManipulation = new CodeManipulation(editor);
renderer = new CaretReferenceHighlightRenderer(editor);
// Patch editor options (indentation) to project-specific settings
if (!editor.ContextActionProviders.IsReadOnly) {
contextActionProviders = AddInTree.BuildItems<IContextActionProvider>("/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));
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
options = new CodeEditorFormattingOptionsAdapter(textEditor.Options, editor.Options, formattingPolicy.OptionsContainer);
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.TextEditorOptions;
}
}
public void Detach()
{
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
var textView = textEditor.TextArea.TextView;
// Unregister our ITextEditorOptions instance from editor
var optionsService = textView.GetService<ITextEditorOptions>();
if ((optionsService != null) && (optionsService == options))
textView.Services.RemoveService(typeof(ITextEditorOptions));
// Reset TextEditor options, too?
if ((textEditor.Options != null) && (textEditor.Options == options.TextEditorOptions))
textEditor.Options = originalEditorOptions;
}
codeManipulation.Dispose();
if (inspectionManager != null) {
inspectionManager.Dispose();
inspectionManager = null;
}
if (contextActionProviders != null) {
editor.ContextActionProviders.RemoveAll(contextActionProviders.Contains);
}
renderer.Dispose();
options = null;
this.editor = null;
}
}
class CodeEditorFormattingOptionsAdapter : ITextEditorOptions, INotifyPropertyChanged
{
CSharpFormattingOptionsContainer container;
readonly TextEditorOptions avalonEditOptions;
readonly TextEditorOptions originalAvalonEditOptions;
readonly ITextEditorOptions originalSDOptions;
public CodeEditorFormattingOptionsAdapter(TextEditorOptions originalAvalonEditOptions, ITextEditorOptions originalSDOptions, CSharpFormattingOptionsContainer container)
{
if (originalAvalonEditOptions == null)
throw new ArgumentNullException("originalAvalonEditOptions");
if (originalSDOptions == null)
throw new ArgumentNullException("originalSDOptions");
if (container == null)
throw new ArgumentNullException("container");
this.originalAvalonEditOptions = originalAvalonEditOptions;
this.avalonEditOptions = new TextEditorOptions(originalAvalonEditOptions);
this.originalSDOptions = originalSDOptions;
this.container = container;
// Update overridden options once
UpdateOverriddenProperties();
CSharpFormattingPolicies.Instance.FormattingPolicyUpdated += OnFormattingPolicyUpdated;
this.originalAvalonEditOptions.PropertyChanged += OnOrigAvalonOptionsPropertyChanged;
this.originalSDOptions.PropertyChanged += OnSDOptionsPropertyChanged;
}
void OnFormattingPolicyUpdated(object sender, CSharpBinding.FormattingStrategy.CSharpFormattingPolicyUpdateEventArgs e)
{
// Update editor options from changed policy
UpdateOverriddenProperties();
OnPropertyChanged("IndentationSize");
OnPropertyChanged("IndentationString");
OnPropertyChanged("ConvertTabsToSpaces");
}
void UpdateOverriddenProperties()
{
avalonEditOptions.IndentationSize = container.GetEffectiveIndentationSize() ?? originalSDOptions.IndentationSize;
avalonEditOptions.ConvertTabsToSpaces = container.GetEffectiveConvertTabsToSpaces() ?? originalSDOptions.ConvertTabsToSpaces;
}
void OnOrigAvalonOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if ((e.PropertyName != "IndentationSize") && (e.PropertyName != "IndentationString") && (e.PropertyName != "ConvertTabsToSpaces")) {
// Update values in our own TextEditorOptions instance
PropertyInfo propertyInfo = typeof(TextEditorOptions).GetProperty(e.PropertyName);
if (propertyInfo != null) {
propertyInfo.SetValue(avalonEditOptions, propertyInfo.GetValue(originalAvalonEditOptions));
}
} else {
UpdateOverriddenProperties();
}
OnPropertyChanged(e.PropertyName);
}
void OnSDOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public ICSharpCode.AvalonEdit.TextEditorOptions TextEditorOptions
{
get {
return avalonEditOptions;
}
}
#region Overridden properties
public int IndentationSize {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationSize;
}
}
public string IndentationString {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationString;
}
}
public bool ConvertTabsToSpaces {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.ConvertTabsToSpaces;
}
}
#endregion
#region Rest of ITextEditorOptions implementation
public bool AutoInsertBlockEnd {
get {
return originalSDOptions.AutoInsertBlockEnd;
}
}
public int VerticalRulerColumn {
get {
return originalSDOptions.VerticalRulerColumn;
}
}
public bool UnderlineErrors {
get {
return originalSDOptions.UnderlineErrors;
}
}
public string FontFamily {
get {
return originalSDOptions.FontFamily;
}
}
public double FontSize {
get {
return originalSDOptions.FontSize;
}
}
#endregion
}
}

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs

@ -24,10 +24,8 @@ using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Completion; using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;

49
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs

@ -17,17 +17,19 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.SharpDevelop.Project;
using CSharpBinding.Parser;
using ICSharpCode.NRefactory.CSharp.Completion; using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using CSharpBinding.Parser;
namespace CSharpBinding.Completion namespace CSharpBinding.Completion
{ {
@ -35,7 +37,7 @@ namespace CSharpBinding.Completion
{ {
public readonly ITextEditor Editor; public readonly ITextEditor Editor;
public readonly IDocument Document; public readonly IDocument Document;
public readonly CSharpFullParseInformation ParseInformation; public readonly IList<string> ConditionalSymbols;
public readonly ICompilation Compilation; public readonly ICompilation Compilation;
public readonly IProjectContent ProjectContent; public readonly IProjectContent ProjectContent;
public readonly CSharpTypeResolveContext TypeResolveContextAtCaret; public readonly CSharpTypeResolveContext TypeResolveContextAtCaret;
@ -56,7 +58,7 @@ namespace CSharpBinding.Completion
if (projectContent == null) if (projectContent == null)
return null; return null;
return new CSharpCompletionContext(editor, parseInfo, compilation, projectContent, editor.Document, editor.Caret.Location); 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, ITextSource fileContent, TextLocation currentLocation, FileName fileName)
@ -64,33 +66,50 @@ namespace CSharpBinding.Completion
IDocument document = new ReadOnlyDocument(fileContent); IDocument document = new ReadOnlyDocument(fileContent);
// Don't require the very latest parse information, an older cached version is OK. // Don't require the very latest parse information, an older cached version is OK.
var parseInfo = SD.ParserService.Parse(fileName, document) as CSharpFullParseInformation; var parseInfo = SD.ParserService.GetCachedParseInformation(fileName) as CSharpFullParseInformation;
if (parseInfo == null) {
parseInfo = SD.ParserService.Parse(fileName) as CSharpFullParseInformation;
}
if (parseInfo == null) if (parseInfo == null)
return null; return null;
ICompilation compilation = SD.ParserService.GetCompilationForFile(fileName);
var projectContent = compilation.MainAssembly.UnresolvedAssembly as IProjectContent; var project = SD.ProjectService.FindProjectContainingFile(fileName)as CSharpProject;
if (project == null)
return null;
var solutionSnapshot = SD.ParserService.GetCurrentSolutionSnapshot();
var projectContent = solutionSnapshot.GetProjectContent(project);
if (projectContent == null) if (projectContent == null)
return null; return null;
return new CSharpCompletionContext(editor, parseInfo, compilation, projectContent, document, currentLocation); CSharpParser parser = new CSharpParser(project.CompilerSettings);
parser.GenerateTypeSystemMode = false;
SyntaxTree cu = parser.Parse(fileContent, Path.GetRandomFileName() + ".cs");
cu.Freeze();
CSharpUnresolvedFile unresolvedFile = cu.ToTypeSystem();
ICompilation compilation = projectContent.AddOrUpdateFiles(unresolvedFile).CreateCompilation(solutionSnapshot);
return new CSharpCompletionContext(editor, parseInfo.SyntaxTree.ConditionalSymbols, compilation, projectContent, document, unresolvedFile, currentLocation);
} }
private CSharpCompletionContext(ITextEditor editor, CSharpFullParseInformation parseInfo, ICompilation compilation, IProjectContent projectContent, IDocument document, TextLocation caretLocation) private CSharpCompletionContext(ITextEditor editor, IList<string> conditionalSymbols, ICompilation compilation, IProjectContent projectContent, IDocument document, CSharpUnresolvedFile unresolvedFile, TextLocation caretLocation)
{ {
Debug.Assert(editor != null); Debug.Assert(editor != null);
Debug.Assert(parseInfo != null); Debug.Assert(unresolvedFile != null);
Debug.Assert(compilation != null); Debug.Assert(compilation != null);
Debug.Assert(projectContent != null); Debug.Assert(projectContent != null);
Debug.Assert(document != null); Debug.Assert(document != null);
this.Editor = editor; this.Editor = editor;
this.Document = document; this.Document = document;
this.ParseInformation = parseInfo; this.ConditionalSymbols = conditionalSymbols;
this.Compilation = compilation; this.Compilation = compilation;
this.ProjectContent = projectContent; this.ProjectContent = projectContent;
this.TypeResolveContextAtCaret = parseInfo.UnresolvedFile.GetTypeResolveContext(compilation, caretLocation); this.TypeResolveContextAtCaret = unresolvedFile.GetTypeResolveContext(compilation, caretLocation);
this.CompletionContextProvider = new DefaultCompletionContextProvider(document, parseInfo.UnresolvedFile); this.CompletionContextProvider = new DefaultCompletionContextProvider(document, unresolvedFile);
this.CompletionContextProvider.ConditionalSymbols.AddRange(parseInfo.SyntaxTree.ConditionalSymbols); this.CompletionContextProvider.ConditionalSymbols.AddRange(conditionalSymbols);
} }
} }
} }

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs

@ -148,7 +148,7 @@ namespace CSharpBinding.Completion
IEnumerable<ICompletionData> ICompletionDataFactory.CreatePreProcessorDefinesCompletionData() IEnumerable<ICompletionData> ICompletionDataFactory.CreatePreProcessorDefinesCompletionData()
{ {
return completionContext.ParseInformation.SyntaxTree.ConditionalSymbols.Select(def => new CompletionData(def)); return completionContext.ConditionalSymbols.Select(def => new CompletionData(def));
} }
ICompletionData ICompletionDataFactory.CreateImportCompletionData(IType type, bool useFullName, bool addForTypeCreation) ICompletionData ICompletionDataFactory.CreateImportCompletionData(IType type, bool useFullName, bool addForTypeCreation)

3
src/AddIns/Debugger/Debugger.AddIn/Breakpoints/BreakpointEditorPopup.xaml.cs

@ -41,7 +41,8 @@ namespace Debugger.AddIn.Breakpoints
{ {
InitializeComponent(); InitializeComponent();
this.DataContext = target; this.DataContext = target;
condition.DebugContext = new DebuggerCompletionContext(target.FileName, target.Location); condition.ContextFileName = target.FileName;
condition.ContextTextLocation = target.Location;
condition.FontFamily = new FontFamily(SD.EditorControlService.GlobalOptions.FontFamily); condition.FontFamily = new FontFamily(SD.EditorControlService.GlobalOptions.FontFamily);
condition.FontSize = SD.EditorControlService.GlobalOptions.FontSize; condition.FontSize = SD.EditorControlService.GlobalOptions.FontSize;
if (target.Condition == null) if (target.Condition == null)

18
src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs

@ -64,7 +64,8 @@ namespace Debugger.AddIn.Pads.Controls
set { SetValue(IsEditableProperty, value); } set { SetValue(IsEditableProperty, value); }
} }
public DebuggerCompletionContext DebugContext { get; set; } public FileName ContextFileName { get; set; }
public TextLocation ContextTextLocation { get; set; }
static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
@ -127,20 +128,15 @@ namespace Debugger.AddIn.Pads.Controls
void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e) void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
{ {
if (e.Text == ".") { if (e.Text == ".") {
DebuggerCompletionContext context = null;
StackFrame frame = WindowsDebugger.CurrentStackFrame; StackFrame frame = WindowsDebugger.CurrentStackFrame;
if (frame == null) { if (frame != null) {
if (DebugContext != null) { ContextFileName = new FileName(frame.NextStatement.Filename);
context = DebugContext; ContextTextLocation = new TextLocation(frame.NextStatement.StartLine, frame.NextStatement.StartColumn);
}
} else {
context = new DebuggerCompletionContext(frame);
} }
if (context == null) return; if (ContextFileName == null) return;
var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), context); var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), ContextFileName, ContextTextLocation, SD.ParserService.ResolveContext(ContextFileName, ContextTextLocation));
if (binding == null) return; if (binding == null) return;
binding.HandleKeyPressed(editorAdapter, '.'); binding.HandleKeyPressed(editorAdapter, '.');
SD.ParserService.ParseFileAsync(context.FileName).FireAndForget();
} else { } else {
// TODO : implement automated error checking CSharpParser.ParseExpression does not report useful error messages. // TODO : implement automated error checking CSharpParser.ParseExpression does not report useful error messages.
// Error[] errors; // Error[] errors;

5
src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs

@ -86,10 +86,11 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
void ShowDotCompletion(StackFrame frame, string currentText) void ShowDotCompletion(StackFrame frame, string currentText)
{ {
var binding = DebuggerDotCompletion.PrepareDotCompletion(currentText, new DebuggerCompletionContext(frame)); 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));
if (binding == null) return; if (binding == null) return;
binding.HandleKeyPressed(console.TextEditor, '.'); binding.HandleKeyPressed(console.TextEditor, '.');
SD.ParserService.ParseFileAsync(new ICSharpCode.Core.FileName(frame.NextStatement.Filename)).FireAndForget();
} }
protected override ToolBar BuildToolBar() protected override ToolBar BuildToolBar()

156
src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs

@ -41,162 +41,12 @@ namespace Debugger.AddIn.Pads.Controls
return !errors.Any(); return !errors.Any();
} }
public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, DebuggerCompletionContext context) public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context)
{ {
var lang = SD.LanguageService.GetLanguageByFileName(context.FileName); var lang = SD.LanguageService.GetLanguageByFileName(fileName);
if (lang == null) if (lang == null)
return null; return null;
string content = GeneratePartialClassContextStub(context); return lang.CreateCompletionBinding(expressionToComplete, fileName, location, 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 lang.CreateCompletionBinding(context.FileName, doc.GetLocation(caretOffset), doc.CreateSnapshot());
}
static string GeneratePartialClassContextStub(DebuggerCompletionContext context)
{
var compilation = SD.ParserService.GetCompilationForFile(context.FileName);
var file = SD.ParserService.GetExistingUnresolvedFile(context.FileName);
if (compilation == null || file == null)
return "";
var unresolvedMember = file.GetMember(context.Location);
if (unresolvedMember == null)
return "";
var member = unresolvedMember.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly));
if (member == null)
return "";
var builder = new TypeSystemAstBuilder();
MethodDeclaration decl;
if (unresolvedMember is IMethod) {
// If it's a method, convert it directly (including parameters + type parameters)
decl = (MethodDeclaration)builder.ConvertEntity(member);
} else {
// Otherwise, create a method anyways, and copy the parameters
decl = new MethodDeclaration();
if (member is IParameterizedMember) {
foreach (var p in ((IParameterizedMember)member).Parameters) {
decl.Parameters.Add(builder.ConvertParameter(p));
}
}
}
decl.Name = "__DebuggerStub__";
decl.ReturnType = builder.ConvertType(member.ReturnType);
decl.Modifiers = unresolvedMember.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);
return WrapInType(unresolvedMember.DeclaringTypeDefinition, decl).ToString();
}
static BlockStatement GenerateBodyFromContext(TypeSystemAstBuilder builder, DebuggerCompletionContext context)
{
var body = new BlockStatement();
foreach (var v in context.Variables)
body.Statements.Add(new VariableDeclarationStatement(builder.ConvertType(v.Type), v.Name));
body.Statements.Add(new ExpressionStatement(new IdentifierExpression("$__Caret_Point__$")));
return body;
}
static AstNode WrapInType(IUnresolvedTypeDefinition entity, EntityDeclaration decl)
{
if (entity == null)
return decl;
// Wrap decl in TypeDeclaration
decl = new TypeDeclaration {
ClassType = GetClassType(entity),
Modifiers = Modifiers.Partial,
Name = entity.Name,
Members = { decl }
};
if (entity.DeclaringTypeDefinition != null) {
// Handle nested types
return WrapInType(entity.DeclaringTypeDefinition, decl);
}
if (string.IsNullOrEmpty(entity.Namespace))
return decl;
return new NamespaceDeclaration(entity.Namespace) {
Members = {
decl
}
};
}
static ClassType GetClassType(IUnresolvedTypeDefinition entity)
{
switch (entity.Kind) {
case TypeKind.Interface:
return ClassType.Interface;
case TypeKind.Struct:
return ClassType.Struct;
default:
return ClassType.Class;
}
}
}
public class LocalVariable
{
readonly IType type;
public IType Type {
get {
return type;
}
}
readonly string name;
public string Name {
get {
return name;
}
}
public LocalVariable(IType type, string name)
{
this.type = type;
this.name = name;
}
}
public class DebuggerCompletionContext
{
readonly FileName fileName;
TextLocation location;
readonly LocalVariable[] variables;
public DebuggerCompletionContext(StackFrame frame)
{
fileName = new FileName(frame.NextStatement.Filename);
location = new TextLocation(frame.NextStatement.StartLine, frame.NextStatement.StartColumn);
variables = frame.GetLocalVariables().Select(v => new LocalVariable(v.Type, v.Name)).ToArray();
}
public DebuggerCompletionContext(FileName fileName, TextLocation location)
{
this.fileName = fileName;
this.location = location;
this.variables = SD.ParserService.ResolveContext(fileName, location)
.LocalVariables.Select(v => new LocalVariable(v.Type, v.Name)).ToArray();
}
public FileName FileName {
get {
return fileName;
}
}
public TextLocation Location {
get {
return location;
}
}
public LocalVariable[] Variables {
get {
return variables;
}
} }
} }
} }

2
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -633,6 +633,8 @@ namespace ICSharpCode.SharpDevelop.Services
return; return;
if (CurrentStackFrame == null) if (CurrentStackFrame == null)
return; return;
if (!e.InDocument)
return;
var resolveResult = SD.ParserService.Resolve(e.Editor, e.LogicalPosition, CurrentStackFrame.AppDomain.Compilation); var resolveResult = SD.ParserService.Resolve(e.Editor, e.LogicalPosition, CurrentStackFrame.AppDomain.Compilation);
if (resolveResult == null) if (resolveResult == null)
return; return;

3
src/AddIns/VersionControl/GitAddIn/Src/Git.cs

@ -94,7 +94,8 @@ namespace ICSharpCode.GitAddIn
/// </summary> /// </summary>
public static string FindGit() public static string FindGit()
{ {
string[] paths = Environment.GetEnvironmentVariable("PATH").Split(';'); string pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
string[] paths = pathVariable.Split(new char[]{';'}, StringSplitOptions.RemoveEmptyEntries);
foreach (string path in paths) { foreach (string path in paths) {
try { try {
string exe = Path.Combine(path, "git.exe"); string exe = Path.Combine(path, "git.exe");

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Uncategorized/UseOfMemberOfNullReference.cs

@ -34,10 +34,10 @@ using ICSharpCode.NRefactory.CSharp.Analysis;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
[IssueDescription("Use of (non-extension method) member of null value will cause a NullReferenceException", // [IssueDescription("Use of (non-extension method) member of null value will cause a NullReferenceException",
Description = "Detects when a member of a null value is used", // Description = "Detects when a member of a null value is used",
Category = IssueCategories.CodeQualityIssues, // Category = IssueCategories.CodeQualityIssues,
Severity = Severity.Warning)] // Severity = Severity.Warning)]
public class UseOfMemberOfNullReference : GatherVisitorCodeIssueProvider public class UseOfMemberOfNullReference : GatherVisitorCodeIssueProvider
{ {
static readonly ISet<NullValueStatus> ProblematicNullStates = new HashSet<NullValueStatus> { static readonly ISet<NullValueStatus> ProblematicNullStates = new HashSet<NullValueStatus> {

3
src/Libraries/SharpTreeView/ICSharpCode.TreeView/SharpTreeViewItem.cs

@ -118,7 +118,8 @@ namespace ICSharpCode.TreeView
protected override void OnContextMenuOpening(ContextMenuEventArgs e) protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{ {
Node.ShowContextMenu(e); if (Node != null)
Node.ShowContextMenu(e);
} }
#endregion #endregion

12
src/Main/Base/Project/Parser/ProjectContentContainer.cs

@ -463,9 +463,15 @@ namespace ICSharpCode.SharpDevelop.Parser
foreach (var file in assemblyFiles) { foreach (var file in assemblyFiles) {
progressMonitor.CancellationToken.ThrowIfCancellationRequested(); progressMonitor.CancellationToken.ThrowIfCancellationRequested();
if (File.Exists(file)) { if (File.Exists(file)) {
var pc = SD.AssemblyParserService.GetAssembly(file, false, progressMonitor.CancellationToken); try {
if (pc != null) { var pc = SD.AssemblyParserService.GetAssembly(file, false, progressMonitor.CancellationToken);
newReferences.Add(pc); if (pc != null) {
newReferences.Add(pc);
}
} catch (IOException ex) {
LoggingService.Warn(ex);
} catch (BadImageFormatException ex) {
LoggingService.Warn(ex);
} }
} }
progressMonitor.Progress += (1.0 - assemblyResolvingProgress) / assemblyFiles.Count; progressMonitor.Progress += (1.0 - assemblyResolvingProgress) / assemblyFiles.Count;

2
src/Main/Base/Project/Src/Project/AbstractProject.cs

@ -188,7 +188,7 @@ namespace ICSharpCode.SharpDevelop.Project
try { try {
FileAttributes attributes = File.GetAttributes(FileName); FileAttributes attributes = File.GetAttributes(FileName);
return ((FileAttributes.ReadOnly & attributes) == FileAttributes.ReadOnly); return ((FileAttributes.ReadOnly & attributes) == FileAttributes.ReadOnly);
} catch (FileNotFoundException) { } catch (UnauthorizedAccessException) {
return false; return false;
} catch (IOException) { } catch (IOException) {
// directory not found, network path not available, etc. // directory not found, network path not available, etc.

2
src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs

@ -75,7 +75,7 @@ namespace ICSharpCode.SharpDevelop
} }
} }
public virtual ICodeCompletionBinding CreateCompletionBinding(FileName fileName, TextLocation currentLocation, ITextSource fileContent) public virtual ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
} }

5
src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Linq;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
@ -62,8 +63,8 @@ namespace ICSharpCode.SharpDevelop
} }
/// <summary> /// <summary>
/// Creates a completion binding which works with a fileName and a location as context. /// Creates a completion binding for a given expression and context.
/// </summary> /// </summary>
ICodeCompletionBinding CreateCompletionBinding(FileName fileName, TextLocation currentLocation, ITextSource fileContent); ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context);
} }
} }

8
src/Main/SharpDevelop/Parser/ParserService.cs

@ -174,7 +174,7 @@ namespace ICSharpCode.SharpDevelop.Parser
internal void RemoveEntry(ParserServiceEntry entry) internal void RemoveEntry(ParserServiceEntry entry)
{ {
Debug.Assert(Monitor.IsEntered(entry)); Debug.Assert(entry.rwLock.IsWriteLockHeld);
lock (fileEntryDict) { lock (fileEntryDict) {
ParserServiceEntry entryAtKey; ParserServiceEntry entryAtKey;
if (fileEntryDict.TryGetValue(entry.fileName, out entryAtKey)) { if (fileEntryDict.TryGetValue(entry.fileName, out entryAtKey)) {
@ -190,7 +190,7 @@ namespace ICSharpCode.SharpDevelop.Parser
internal void RegisterForCacheExpiry(ParserServiceEntry entry) internal void RegisterForCacheExpiry(ParserServiceEntry entry)
{ {
// This method should not be called within any locks // This method should not be called within any locks
Debug.Assert(!Monitor.IsEntered(entry)); Debug.Assert(!(entry.rwLock.IsReadLockHeld || entry.rwLock.IsUpgradeableReadLockHeld || entry.rwLock.IsWriteLockHeld));
ParserServiceEntry expiredItem = null; ParserServiceEntry expiredItem = null;
lock (cacheExpiryQueue) { lock (cacheExpiryQueue) {
cacheExpiryQueue.Remove(entry); // remove entry from queue if it's already enqueued cacheExpiryQueue.Remove(entry); // remove entry from queue if it's already enqueued
@ -278,7 +278,7 @@ namespace ICSharpCode.SharpDevelop.Parser
public ResolveResult Resolve(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken) public ResolveResult Resolve(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{ {
var entry = GetFileEntry(fileName, true); var entry = GetFileEntry(fileName, true);
if (entry.parser == null) if (entry.parser == null || location.IsEmpty)
return ErrorResolveResult.UnknownError; return ErrorResolveResult.UnknownError;
IProject project = compilation != null ? compilation.GetProject() : null; IProject project = compilation != null ? compilation.GetProject() : null;
var parseInfo = entry.Parse(fileContent, project, cancellationToken); var parseInfo = entry.Parse(fileContent, project, cancellationToken);
@ -334,7 +334,7 @@ namespace ICSharpCode.SharpDevelop.Parser
public Task<ResolveResult> ResolveAsync(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken) public Task<ResolveResult> ResolveAsync(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{ {
var entry = GetFileEntry(fileName, true); var entry = GetFileEntry(fileName, true);
if (entry.parser == null) if (entry.parser == null || location.IsEmpty)
return Task.FromResult<ResolveResult>(ErrorResolveResult.UnknownError); return Task.FromResult<ResolveResult>(ErrorResolveResult.UnknownError);
IProject project = compilation != null ? compilation.GetProject() : null; IProject project = compilation != null ? compilation.GetProject() : null;
return entry.ParseAsync(fileContent, project, cancellationToken).ContinueWith( return entry.ParseAsync(fileContent, project, cancellationToken).ContinueWith(

96
src/Main/SharpDevelop/Parser/ParserServiceEntry.cs

@ -54,6 +54,10 @@ namespace ICSharpCode.SharpDevelop.Parser
List<ProjectEntry> entries = new List<ProjectEntry> { default(ProjectEntry) }; List<ProjectEntry> entries = new List<ProjectEntry> { default(ProjectEntry) };
ITextSourceVersion currentVersion; ITextSourceVersion currentVersion;
// Lock ordering: runningAsyncParseLock, rwLock, lock(parserService.fileEntryDict)
// (to avoid deadlocks, the locks may only be acquired in this order)
internal readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
public ParserServiceEntry(ParserService parserService, FileName fileName) public ParserServiceEntry(ParserService parserService, FileName fileName)
{ {
this.parserService = parserService; this.parserService = parserService;
@ -68,6 +72,7 @@ namespace ICSharpCode.SharpDevelop.Parser
int FindIndexForProject(IProject parentProject) int FindIndexForProject(IProject parentProject)
{ {
Debug.Assert(rwLock.IsReadLockHeld || rwLock.IsUpgradeableReadLockHeld || rwLock.IsWriteLockHeld);
if (parentProject == null) if (parentProject == null)
return 0; return 0;
for (int i = 0; i < entries.Count; i++) { for (int i = 0; i < entries.Count; i++) {
@ -81,7 +86,8 @@ namespace ICSharpCode.SharpDevelop.Parser
public void AddOwnerProject(IProject project, bool isLinkedFile) public void AddOwnerProject(IProject project, bool isLinkedFile)
{ {
Debug.Assert(project != null); Debug.Assert(project != null);
lock (this) { rwLock.EnterWriteLock();
try {
if (FindIndexForProject(project) >= 0) if (FindIndexForProject(project) >= 0)
throw new InvalidOperationException("The project alreadys owns the file"); throw new InvalidOperationException("The project alreadys owns the file");
ProjectEntry newEntry = new ProjectEntry(project, null, null); ProjectEntry newEntry = new ProjectEntry(project, null, null);
@ -92,6 +98,8 @@ namespace ICSharpCode.SharpDevelop.Parser
} else { } else {
entries.Insert(0, newEntry); entries.Insert(0, newEntry);
} }
} finally {
rwLock.ExitWriteLock();
} }
} }
@ -100,7 +108,8 @@ namespace ICSharpCode.SharpDevelop.Parser
Debug.Assert(project != null); Debug.Assert(project != null);
ProjectEntry oldEntry; ProjectEntry oldEntry;
bool removedLastOwner = false; bool removedLastOwner = false;
lock (this) { rwLock.EnterWriteLock();
try {
int index = FindIndexForProject(project); int index = FindIndexForProject(project);
if (index < 0) if (index < 0)
throw new InvalidOperationException("The project does not own the file"); throw new InvalidOperationException("The project does not own the file");
@ -111,6 +120,8 @@ namespace ICSharpCode.SharpDevelop.Parser
} else { } else {
entries.RemoveAt(index); entries.RemoveAt(index);
} }
} finally {
rwLock.ExitWriteLock();
} }
if (oldEntry.UnresolvedFile != null) { if (oldEntry.UnresolvedFile != null) {
project.OnParseInformationUpdated(new ParseInformationEventArgs(project, oldEntry.UnresolvedFile, null)); project.OnParseInformationUpdated(new ParseInformationEventArgs(project, oldEntry.UnresolvedFile, null));
@ -128,6 +139,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// </summary> /// </summary>
int CompareVersions(ITextSourceVersion newVersion) int CompareVersions(ITextSourceVersion newVersion)
{ {
Debug.Assert(rwLock.IsReadLockHeld || rwLock.IsUpgradeableReadLockHeld || rwLock.IsWriteLockHeld);
if (currentVersion != null && newVersion != null && currentVersion.BelongsToSameDocumentAs(newVersion)) if (currentVersion != null && newVersion != null && currentVersion.BelongsToSameDocumentAs(newVersion))
return currentVersion.CompareAge(newVersion); return currentVersion.CompareAge(newVersion);
else else
@ -137,7 +149,8 @@ namespace ICSharpCode.SharpDevelop.Parser
#region Expire Cache + GetExistingUnresolvedFile + GetCachedParseInformation #region Expire Cache + GetExistingUnresolvedFile + GetCachedParseInformation
public void ExpireCache() public void ExpireCache()
{ {
lock (this) { rwLock.EnterWriteLock();
try {
if (PrimaryProject == null) { if (PrimaryProject == null) {
parserService.RemoveEntry(this); parserService.RemoveEntry(this);
} else { } else {
@ -148,12 +161,15 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
// force re-parse on next ParseFile() call even if unchanged // force re-parse on next ParseFile() call even if unchanged
this.currentVersion = null; this.currentVersion = null;
} finally {
rwLock.ExitWriteLock();
} }
} }
public IUnresolvedFile GetExistingUnresolvedFile(ITextSourceVersion version, IProject parentProject) public IUnresolvedFile GetExistingUnresolvedFile(ITextSourceVersion version, IProject parentProject)
{ {
lock (this) { rwLock.EnterReadLock();
try {
if (version != null && CompareVersions(version) != 0) { if (version != null && CompareVersions(version) != 0) {
return null; return null;
} }
@ -161,12 +177,15 @@ namespace ICSharpCode.SharpDevelop.Parser
if (index < 0) if (index < 0)
return null; return null;
return entries[index].UnresolvedFile; return entries[index].UnresolvedFile;
} finally {
rwLock.ExitReadLock();
} }
} }
public ParseInformation GetCachedParseInformation(ITextSourceVersion version, IProject parentProject) public ParseInformation GetCachedParseInformation(ITextSourceVersion version, IProject parentProject)
{ {
lock (this) { rwLock.EnterReadLock();
try {
if (version != null && CompareVersions(version) != 0) { if (version != null && CompareVersions(version) != 0) {
return null; return null;
} }
@ -174,6 +193,8 @@ namespace ICSharpCode.SharpDevelop.Parser
if (index < 0) if (index < 0)
return null; return null;
return entries[index].CachedParseInformation; return entries[index].CachedParseInformation;
} finally {
rwLock.ExitReadLock();
} }
} }
#endregion #endregion
@ -218,7 +239,8 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
ProjectEntry result; ProjectEntry result;
lock (this) { rwLock.EnterUpgradeableReadLock();
try {
int index = FindIndexForProject(parentProject); int index = FindIndexForProject(parentProject);
int versionComparison = CompareVersions(fileContent.Version); int versionComparison = CompareVersions(fileContent.Version);
if (versionComparison > 0 || index < 0) { if (versionComparison > 0 || index < 0) {
@ -253,24 +275,32 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
// Only if all parse runs succeeded, register the parse information. // Only if all parse runs succeeded, register the parse information.
currentVersion = fileContent.Version; rwLock.EnterWriteLock();
for (int i = 0; i < entries.Count; i++) { try {
if (fullParseInformationRequested || (entries[i].CachedParseInformation != null && results[i].NewParseInformation.IsFullParseInformation)) currentVersion = fileContent.Version;
entries[i] = new ProjectEntry(entries[i].Project, results[i].NewUnresolvedFile, results[i].NewParseInformation); for (int i = 0; i < entries.Count; i++) {
else if (fullParseInformationRequested || (entries[i].CachedParseInformation != null && results[i].NewParseInformation.IsFullParseInformation))
entries[i] = new ProjectEntry(entries[i].Project, results[i].NewUnresolvedFile, null); entries[i] = new ProjectEntry(entries[i].Project, results[i].NewUnresolvedFile, results[i].NewParseInformation);
if (entries[i].Project != null) else
entries[i].Project.OnParseInformationUpdated(results[i]); entries[i] = new ProjectEntry(entries[i].Project, results[i].NewUnresolvedFile, null);
parserService.RaiseParseInformationUpdated(results[i]); if (entries[i].Project != null)
entries[i].Project.OnParseInformationUpdated(results[i]);
parserService.RaiseParseInformationUpdated(results[i]);
}
result = entries[index];
} finally {
rwLock.ExitWriteLock();
} }
result = entries[index]; } finally {
} // exit lock rwLock.ExitUpgradeableReadLock();
}
parserService.RegisterForCacheExpiry(this); parserService.RegisterForCacheExpiry(this);
return result; return result;
} }
ParseInformation ParseWithExceptionHandling(ITextSource fileContent, bool fullParseInformationRequested, IProject project, CancellationToken cancellationToken) ParseInformation ParseWithExceptionHandling(ITextSource fileContent, bool fullParseInformationRequested, IProject project, CancellationToken cancellationToken)
{ {
Debug.Assert(rwLock.IsUpgradeableReadLockHeld && !rwLock.IsWriteLockHeld);
#if DEBUG #if DEBUG
if (Debugger.IsAttached) if (Debugger.IsAttached)
return parser.Parse(fileName, fileContent, fullParseInformationRequested, project, cancellationToken); return parser.Parse(fileName, fileContent, fullParseInformationRequested, project, cancellationToken);
@ -285,6 +315,8 @@ namespace ICSharpCode.SharpDevelop.Parser
#endregion #endregion
#region ParseAsync #region ParseAsync
/// <summary>lock object for protecting the runningAsyncParse* fields</summary>
object runningAsyncParseLock = new object();
Task<ProjectEntry> runningAsyncParseTask; Task<ProjectEntry> runningAsyncParseTask;
ITextSourceVersion runningAsyncParseFileContentVersion; ITextSourceVersion runningAsyncParseFileContentVersion;
IProject runningAsyncParseProject; IProject runningAsyncParseProject;
@ -324,19 +356,24 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
Task<ProjectEntry> task; Task<ProjectEntry> task;
lock (this) { lock (runningAsyncParseLock) {
if (fileContent != null) { if (fileContent != null) {
// Optimization: // Optimization:
// don't start a background task if fileContent was specified and up-to-date parse info is available // don't start a background task if fileContent was specified and up-to-date parse info is available
int index = FindIndexForProject(parentProject); rwLock.EnterReadLock();
int versionComparison = CompareVersions(fileContent.Version); try {
if (versionComparison == 0 && index >= 0) { int index = FindIndexForProject(parentProject);
// Ensure we have parse info for the specified project (entry.UnresolvedFile is null for newly registered projects) int versionComparison = CompareVersions(fileContent.Version);
// If full parse info is requested, ensure we have full parse info. if (versionComparison == 0 && index >= 0) {
if (entries[index].UnresolvedFile != null && !(requestFullParseInformation && entries[index].CachedParseInformation == null)) { // Ensure we have parse info for the specified project (entry.UnresolvedFile is null for newly registered projects)
// We already have the requested version parsed, just return it: // If full parse info is requested, ensure we have full parse info.
return Task.FromResult(entries[index]); if (entries[index].UnresolvedFile != null && !(requestFullParseInformation && entries[index].CachedParseInformation == null)) {
// We already have the requested version parsed, just return it:
return Task.FromResult(entries[index]);
}
} }
} finally {
rwLock.ExitReadLock();
} }
// Optimization: // Optimization:
// if an equivalent task is already running, return that one instead // if an equivalent task is already running, return that one instead
@ -356,7 +393,7 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
return DoParse(fileContent, parentProject, requestFullParseInformation, cancellationToken); return DoParse(fileContent, parentProject, requestFullParseInformation, cancellationToken);
} finally { } finally {
lock (this) { lock (runningAsyncParseLock) {
runningAsyncParseTask = null; runningAsyncParseTask = null;
runningAsyncParseFileContentVersion = null; runningAsyncParseFileContentVersion = null;
runningAsyncParseProject = null; runningAsyncParseProject = null;
@ -383,7 +420,8 @@ namespace ICSharpCode.SharpDevelop.Parser
throw new ArgumentNullException("unresolvedFile"); throw new ArgumentNullException("unresolvedFile");
FreezableHelper.Freeze(unresolvedFile); FreezableHelper.Freeze(unresolvedFile);
var newParseInfo = new ParseInformation(unresolvedFile, null, false); var newParseInfo = new ParseInformation(unresolvedFile, null, false);
lock (this) { rwLock.EnterWriteLock();
try {
int index = FindIndexForProject(project); int index = FindIndexForProject(project);
if (index >= 0) { if (index >= 0) {
currentVersion = null; currentVersion = null;
@ -392,6 +430,8 @@ namespace ICSharpCode.SharpDevelop.Parser
project.OnParseInformationUpdated(args); project.OnParseInformationUpdated(args);
parserService.RaiseParseInformationUpdated(args); parserService.RaiseParseInformationUpdated(args);
} }
} finally {
rwLock.ExitWriteLock();
} }
} }
} }

12
src/Tools/StressTest/StressTest.sln

@ -1,7 +1,9 @@
 
Microsoft Visual Studio Solution File, Format Version 11.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2010 # Visual Studio 2012
# SharpDevelop 4.3 # SharpDevelop 5.0
VisualStudioVersion = 12.0.20827.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StressTest", "StressTest\StressTest.csproj", "{30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StressTest", "StressTest\StressTest.csproj", "{30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}"
EndProject EndProject
Global Global
@ -10,9 +12,9 @@ Global
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Debug|x86.Build.0 = Debug|x86
{30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Debug|x86.ActiveCfg = Debug|x86 {30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Debug|x86.ActiveCfg = Debug|x86
{30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Release|x86.Build.0 = Release|x86 {30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Debug|x86.Build.0 = Debug|x86
{30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Release|x86.ActiveCfg = Release|x86 {30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Release|x86.ActiveCfg = Release|x86
{30D10654-A5F5-4AC5-A370-E6DD4D0FAC50}.Release|x86.Build.0 = Release|x86
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

3
src/Tools/StressTest/StressTest/StressTest.csproj

@ -98,9 +98,6 @@
<ItemGroup> <ItemGroup>
<Page Include="UserControl.xaml" /> <Page Include="UserControl.xaml" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="ProfilingSessions\Session20100225_205054.sdps" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<StartArguments>/addindir:"$(MsBuildProjectDirectory)\$(OutputPath)"</StartArguments> <StartArguments>/addindir:"$(MsBuildProjectDirectory)\$(OutputPath)"</StartArguments>
</PropertyGroup> </PropertyGroup>

1
src/Tools/StressTest/StressTest/UserControl.xaml.cs

@ -35,6 +35,7 @@ using ICSharpCode.Core;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Workbench;
namespace StressTest namespace StressTest
{ {

Loading…
Cancel
Save