Browse Source

Change "SymbolUnderCaretMenuCommand" into "ResolveResultMenuCommand".

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
2828c9e904
  1. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs
  2. 3
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  3. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/FindBaseClasses.cs
  4. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/FindDerivedClassesOrOverrides.cs
  5. 30
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/XmlDoc/XmlDocTooltipProvider.cs
  6. 18
      src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin
  7. 49
      src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/OpenInILSpyCommand.cs
  8. 6
      src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs
  9. 2
      src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
  10. 5
      src/Main/Base/Project/Src/Editor/Commands/FindReferencesCommand.cs
  11. 4
      src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs
  12. 48
      src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs
  13. 11
      src/Main/Base/Project/Src/Project/CompilableProject.cs
  14. 2
      src/Main/Base/Project/Src/Services/AmbienceService/AmbienceService.cs
  15. 26
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs

@ -214,7 +214,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
else else
col += 1; col += 1;
} }
WorkbenchSingleton.StatusBar.SetCaretPosition(col, this.Line, chOffset); SD.StatusBar.SetCaretPosition(col, this.Line, chOffset);
} }
public override bool IsReadOnly { public override bool IsReadOnly {

3
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -455,8 +455,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (position == null) if (position == null)
return; return;
SD.AnalyticsMonitor.TrackFeature(typeof(GoToDefinition).FullName, "Ctrl+Click"); SD.AnalyticsMonitor.TrackFeature(typeof(GoToDefinition).FullName, "Ctrl+Click");
var resolveResult = SD.ParserService.Resolve(Adapter, position.Value.Location);
var goToDefinitionCommand = new GoToDefinition(); var goToDefinitionCommand = new GoToDefinition();
goToDefinitionCommand.Run(this.Adapter, this.Document.GetOffset(position.Value.Location)); goToDefinitionCommand.Run(resolveResult);
e.Handled = true; e.Handled = true;
} }
} }

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/FindBaseClasses.cs

@ -15,9 +15,9 @@ using ICSharpCode.SharpDevelop.Editor.Commands;
namespace ICSharpCode.AvalonEdit.AddIn.ContextActions namespace ICSharpCode.AvalonEdit.AddIn.ContextActions
{ {
public class FindBaseClasses : SymbolUnderCaretMenuCommand public class FindBaseClasses : ResolveResultMenuCommand
{ {
protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) public override void Run(ResolveResult symbol)
{ {
IEntity entityUnderCaret = GetEntity(symbol); IEntity entityUnderCaret = GetEntity(symbol);
if (entityUnderCaret is ITypeDefinition) { if (entityUnderCaret is ITypeDefinition) {

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/FindDerivedClassesOrOverrides.cs

@ -16,9 +16,9 @@ using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.AvalonEdit.AddIn.ContextActions namespace ICSharpCode.AvalonEdit.AddIn.ContextActions
{ {
public class FindDerivedClassesOrOverrides : SymbolUnderCaretMenuCommand public class FindDerivedClassesOrOverrides : ResolveResultMenuCommand
{ {
protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) public override void Run(ResolveResult symbol)
{ {
IEntity entityUnderCaret = GetEntity(symbol); IEntity entityUnderCaret = GetEntity(symbol);
if (entityUnderCaret is ITypeDefinition && !entityUnderCaret.IsSealed) { if (entityUnderCaret is ITypeDefinition && !entityUnderCaret.IsSealed) {

30
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/XmlDoc/XmlDocTooltipProvider.cs

@ -41,6 +41,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.XmlDoc
public FlowDocumentTooltip(FlowDocument document) public FlowDocumentTooltip(FlowDocument document)
{ {
TextOptions.SetTextFormattingMode(this, TextFormattingMode.Display);
viewer = new FlowDocumentScrollViewer(); viewer = new FlowDocumentScrollViewer();
viewer.Document = document; viewer.Document = document;
Border border = new Border { Border border = new Border {
@ -55,8 +56,6 @@ namespace ICSharpCode.AvalonEdit.AddIn.XmlDoc
document.FontSize = CodeEditorOptions.Instance.FontSize; document.FontSize = CodeEditorOptions.Instance.FontSize;
} }
public event RoutedEventHandler Closed { add {} remove {} }
public bool CloseOnHoverEnd { public bool CloseOnHoverEnd {
get { return true; } get { return true; }
} }
@ -65,42 +64,45 @@ namespace ICSharpCode.AvalonEdit.AddIn.XmlDoc
object CreateTooltip(IType type) object CreateTooltip(IType type)
{ {
var ambience = AmbienceService.GetCurrentAmbience(); var ambience = AmbienceService.GetCurrentAmbience();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowDeclaringType;
string header = ambience.ConvertType(type); string header;
if (type is ITypeDefinition)
header = ambience.ConvertEntity((ITypeDefinition)type);
else
header = ambience.ConvertType(type);
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
DocumentationUIBuilder b = new DocumentationUIBuilder(ambience);
b.AddCodeBlock(header, keepLargeMargin: true);
ITypeDefinition entity = type.GetDefinition(); ITypeDefinition entity = type.GetDefinition();
if (entity != null) { if (entity != null) {
var documentation = XmlDocumentationElement.Get(entity); var documentation = XmlDocumentationElement.Get(entity);
if (documentation != null) { if (documentation != null) {
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
DocumentationUIBuilder b = new DocumentationUIBuilder(ambience);
b.AddCodeBlock(header, keepLargeMargin: true);
foreach (var child in documentation.Children) { foreach (var child in documentation.Children) {
b.AddDocumentationElement(child); b.AddDocumentationElement(child);
} }
return new FlowDocumentTooltip(b.FlowDocument);
} }
} }
return header; return new FlowDocumentTooltip(b.FlowDocument);
} }
object CreateTooltip(IEntity entity) object CreateTooltip(IEntity entity)
{ {
var ambience = AmbienceService.GetCurrentAmbience(); var ambience = AmbienceService.GetCurrentAmbience();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowDeclaringType;
string header = ambience.ConvertEntity(entity); string header = ambience.ConvertEntity(entity);
var documentation = XmlDocumentationElement.Get(entity); var documentation = XmlDocumentationElement.Get(entity);
if (documentation != null) {
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
DocumentationUIBuilder b = new DocumentationUIBuilder(ambience); DocumentationUIBuilder b = new DocumentationUIBuilder(ambience);
b.AddCodeBlock(header, keepLargeMargin: true); b.AddCodeBlock(header, keepLargeMargin: true);
if (documentation != null) {
foreach (var child in documentation.Children) { foreach (var child in documentation.Children) {
b.AddDocumentationElement(child); b.AddDocumentationElement(child);
} }
return new FlowDocumentTooltip(b.FlowDocument);
} else {
return header;
} }
return new FlowDocumentTooltip(b.FlowDocument);
} }
} }
} }

18
src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin

@ -17,21 +17,7 @@
</Path> </Path>
<!-- Text editor context menu: Launch ILSpy command --> <!-- Text editor context menu: Launch ILSpy command -->
<!-- <Path name="/SharpDevelop/ViewContent/TextEditor/EntityContextMenu">
<Path name = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassMemberContextMenu"> <MenuItem id="ILSpy" icon="ILSpy" type="Item" label="${res:ILSpyAddIn.OpenILSpyCommand}" class="ICSharpCode.ILSpyAddIn.OpenInILSpyCommand"/>
<MenuItem id="ILSpy" icon="ILSpy" type="Item" label="${res:ILSpyAddIn.OpenILSpyCommand}" class="ICSharpCode.ILSpyAddIn.TextEditorContextMenuCommand"/>
</Path> </Path>
<Path name = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassBookmarkContextMenu">
<MenuItem id="ILSpy" icon="ILSpy" type="Item" label="${res:ILSpyAddIn.OpenILSpyCommand}" class="ICSharpCode.ILSpyAddIn.TextEditorContextMenuCommand"/>
</Path>
<Path name = "/SharpDevelop/Pads/ClassBrowser/MemberContextMenu">
<MenuItem id="ILSpy" icon="ILSpy" type="Item" label="${res:ILSpyAddIn.OpenILSpyCommand}" class="ICSharpCode.ILSpyAddIn.TextEditorContextMenuCommand"/>
</Path>
<Path name = "/SharpDevelop/Pads/ClassBrowser/ClassContextMenu">
<MenuItem id="ILSpy" icon="ILSpy" type="Item" label="${res:ILSpyAddIn.OpenILSpyCommand}" class="ICSharpCode.ILSpyAddIn.TextEditorContextMenuCommand"/>
</Path>
-->
</AddIn> </AddIn>

49
src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/OpenInILSpyCommand.cs

@ -3,7 +3,9 @@
using System; using System;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.SharpDevelop.Bookmarks; using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Editor.Commands;
namespace ICSharpCode.ILSpyAddIn namespace ICSharpCode.ILSpyAddIn
{ {
@ -11,53 +13,14 @@ namespace ICSharpCode.ILSpyAddIn
/// Implements a menu command to position .NET ILSpy on a class /// Implements a menu command to position .NET ILSpy on a class
/// or class member. /// or class member.
/// </summary> /// </summary>
public sealed class OpenInILSpyCommand : AbstractMenuCommand public sealed class OpenInILSpyCommand : ResolveResultMenuCommand
{ {
public override void Run() public override void Run(ResolveResult symbol)
{ {
throw new NotImplementedException(); var entity = GetEntity(symbol);
#warning implement OpenInILSpyCommand
/*IClass c;
IMember m;
MemberNode mn = this.Owner as MemberNode;
if (mn != null) {
m = mn.Member;
c = m.DeclaringType;
} else {
ClassNode cn = this.Owner as ClassNode;
if (cn != null) {
c = cn.Class;
m = null;
} else {
ClassMemberBookmark cmbm = this.Owner as ClassMemberBookmark;
if (cmbm != null) {
m = cmbm.Member;
c = m.DeclaringType;
} else {
ClassBookmark cbm = this.Owner as ClassBookmark;
if (cbm != null) {
c = cbm.Class;
m = null;
} else {
MessageService.ShowWarning("ILSpy AddIn: Could not determine the class for the selected element. Owner: " + ((this.Owner == null) ? "<null>" : this.Owner.ToString()));
return;
}
}
}
}
if (c == null) {
MessageService.ShowWarning("ILSpy AddIn: Could not determine the class for the selected element (known owner). Owner: " + this.Owner.ToString());
return;
}
AbstractEntity entity = m as AbstractEntity;
if (entity == null)
entity = c as AbstractEntity;
if (entity != null) { if (entity != null) {
ILSpyController.OpenInILSpy(entity); ILSpyController.OpenInILSpy(entity);
}*/ }
} }
} }
} }

6
src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpyAddIn
{ {
readonly FileName assemblyFile; readonly FileName assemblyFile;
readonly string fullTypeName; readonly string fullTypeName;
readonly string uri; readonly FileName virtualFileName;
/// <summary> /// <summary>
/// Entity to jump to once decompilation has finished. /// Entity to jump to once decompilation has finished.
@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpyAddIn
#region Constructor #region Constructor
public DecompiledViewContent(FileName assemblyFile, string fullTypeName, string entityTag) public DecompiledViewContent(FileName assemblyFile, string fullTypeName, string entityTag)
{ {
this.uri = string.Format("ilspy://{0}|{1}", assemblyFile, fullTypeName); this.virtualFileName = FileName.Create("ilspy://" + assemblyFile + ">" + fullTypeName);
this.codeView = new CodeView(); this.codeView = new CodeView();
this.assemblyFile = assemblyFile; this.assemblyFile = assemblyFile;
@ -273,7 +273,7 @@ namespace ICSharpCode.ILSpyAddIn
void BookmarkManager_Added(object sender, BookmarkEventArgs e) void BookmarkManager_Added(object sender, BookmarkEventArgs e)
{ {
var mark = e.Bookmark; var mark = e.Bookmark;
if (mark != null && mark is BreakpointBookmark && mark.FileName == uri) { if (mark != null && mark is BreakpointBookmark && mark.FileName == virtualFileName) {
codeView.IconBarManager.Bookmarks.Add(mark); codeView.IconBarManager.Bookmarks.Add(mark);
mark.Document = this.codeView.Document; mark.Document = this.codeView.Document;
} }

2
src/Main/Base/Project/ICSharpCode.SharpDevelop.addin

@ -1930,7 +1930,7 @@
<Path name = "/SharpDevelop/ViewContent/TextEditor/EntityContextMenu"> <Path name = "/SharpDevelop/ViewContent/TextEditor/EntityContextMenu">
<MenuItem id = "FindReferences" <MenuItem id = "FindReferences"
label = "${res:SharpDevelop.Refactoring.FindReferencesCommand}" label = "${res:SharpDevelop.Refactoring.FindReferencesCommand}"
class = "ICSharpCode.SharpDevelop.Refactoring.FindLocalVariableReferencesCommand"/> class = "ICSharpCode.SharpDevelop.Editor.Commands.FindReferencesCommand"/>
</Path> </Path>
<Path name = "/SharpDevelop/ViewContent/DefaultTextEditor/Refactoring/Common"> <Path name = "/SharpDevelop/ViewContent/DefaultTextEditor/Refactoring/Common">

5
src/Main/Base/Project/Src/Editor/Commands/FindReferencesCommand.cs

@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
@ -10,9 +11,9 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
/// <summary> /// <summary>
/// Runs the find references command. /// Runs the find references command.
/// </summary> /// </summary>
public class FindReferencesCommand : SymbolUnderCaretMenuCommand public class FindReferencesCommand : ResolveResultMenuCommand
{ {
protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) public override void Run(ResolveResult symbol)
{ {
var entity = GetEntity(symbol); var entity = GetEntity(symbol);
if (entity != null) { if (entity != null) {

4
src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs

@ -12,9 +12,9 @@ using Mono.Cecil;
namespace ICSharpCode.SharpDevelop.Editor.Commands namespace ICSharpCode.SharpDevelop.Editor.Commands
{ {
public class GoToDefinition : SymbolUnderCaretMenuCommand public class GoToDefinition : ResolveResultMenuCommand
{ {
protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) public override void Run(ResolveResult symbol)
{ {
if (symbol == null) if (symbol == null)
return; return;

48
src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs

@ -12,26 +12,54 @@ using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop.Editor.Commands namespace ICSharpCode.SharpDevelop.Editor.Commands
{ {
/// <summary> /// <summary>
/// A menu command that uses the symbol under the editor's caret. /// A menu command that operates on a <see cref="ResolveResult"/>.
///
/// Supports the following types as <see cref="Owner"/>:
/// - IUnresolvedTypeDefinition (as used by EntityBookmark)
/// - IUnresolvedMember (as used by EntityBookmark)
///
/// If the owner isn't one of the types above, the command operates on the caret position in the current editor.
/// </summary> /// </summary>
public abstract class SymbolUnderCaretMenuCommand : AbstractMenuCommand public abstract class ResolveResultMenuCommand : AbstractMenuCommand
{ {
public abstract void Run(ResolveResult symbol);
public override void Run() public override void Run()
{ {
ITextEditor editor = SD.GetActiveViewContentService<ITextEditor>(); ITextEditor editor = SD.GetActiveViewContentService<ITextEditor>();
if (editor != null) { ResolveResult resolveResult = GetResolveResult(editor, Owner);
Run(editor, editor.Caret.Offset); Run(resolveResult);
}
} }
public void Run(ITextEditor editor, int caretOffset) public static ResolveResult GetResolveResult(ITextEditor editor, object owner)
{ {
var location = editor.Document.GetLocation(caretOffset); if (owner is IUnresolvedTypeDefinition || owner is IUnresolvedMember) {
var resolveResult = SD.ParserService.Resolve(editor, location); return GetResolveResultFromUnresolvedEntity((IUnresolvedEntity)owner);
RunImpl(editor, editor.Caret.Offset, resolveResult); } else if (editor != null) {
return SD.ParserService.Resolve(editor, editor.Caret.Location);
} else {
return ErrorResolveResult.UnknownError;
}
} }
protected abstract void RunImpl(ITextEditor editor, int caretOffset, ResolveResult symbol); static ResolveResult GetResolveResultFromUnresolvedEntity(IUnresolvedEntity entity)
{
if (entity.UnresolvedFile == null)
return ErrorResolveResult.UnknownError;
ICompilation compilation = SD.ParserService.GetCompilationForFile(FileName.Create(entity.UnresolvedFile.FileName));
var context = new SimpleTypeResolveContext(compilation.MainAssembly);
if (entity is IUnresolvedMember) {
var member = ((IUnresolvedMember)entity).Resolve(context);
if (member != null) {
return new MemberResolveResult(null, member);
} else {
return ErrorResolveResult.UnknownError;
}
} else { // IUnresolvedTypeDefinition
var type = ((IUnresolvedTypeDefinition)entity).Resolve(context);
return new TypeResolveResult(type);
}
}
protected IEntity GetEntity(ResolveResult symbol) protected IEntity GetEntity(ResolveResult symbol)
{ {

11
src/Main/Base/Project/Src/Project/CompilableProject.cs

@ -224,12 +224,9 @@ namespace ICSharpCode.SharpDevelop.Project
if (e.PropertyName == "TargetFrameworkVersion") if (e.PropertyName == "TargetFrameworkVersion")
CreateItemsListFromMSBuild(); CreateItemsListFromMSBuild();
if (!isLoading) { if (!isLoading) {
if (reparseReferencesSensitiveProperties.Contains(e.PropertyName)) { bool reparseReferences = reparseReferencesSensitiveProperties.Contains(e.PropertyName);
Reparse(true, false); bool reparseCode = reparseCodeSensitiveProperties.Contains(e.PropertyName);
} Reparse(reparseReferences, reparseCode);
if (reparseCodeSensitiveProperties.Contains(e.PropertyName)) {
Reparse(false, true);
}
} }
} }
@ -238,6 +235,8 @@ namespace ICSharpCode.SharpDevelop.Project
lock (SyncRoot) { lock (SyncRoot) {
if (parseProjectContentContainer == null) if (parseProjectContentContainer == null)
return; // parsing hasn't started yet; no need to re-parse return; // parsing hasn't started yet; no need to re-parse
parseProjectContentContainer.SetAssemblyName(this.AssemblyName);
parseProjectContentContainer.SetLocation(this.OutputAssemblyFullPath);
if (references) { if (references) {
parseProjectContentContainer.ReparseReferences(); parseProjectContentContainer.ReparseReferences();
} }

2
src/Main/Base/Project/Src/Services/AmbienceService/AmbienceService.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.SharpDevelop
/// This method is thread-safe. /// This method is thread-safe.
/// </summary> /// </summary>
/// <returns>Returns a new ambience object (ambience objects are never reused to ensure their thread-safety). /// <returns>Returns a new ambience object (ambience objects are never reused to ensure their thread-safety).
/// Never returns null, in case of errors the <see cref="CSharpAmbience"/> is used.</returns> /// Never returns null, in case of errors the <see cref="DefaultAmbience"/> is used.</returns>
public static IAmbience GetCurrentAmbience() public static IAmbience GetCurrentAmbience()
{ {
if (UseProjectAmbienceIfPossible) { if (UseProjectAmbienceIfPossible) {

26
src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.SharpDevelop.Parser
if (project == null) if (project == null)
throw new ArgumentNullException("project"); throw new ArgumentNullException("project");
this.project = project; this.project = project;
this.projectContent = initialProjectContent.SetAssemblyName(project.AssemblyName); this.projectContent = initialProjectContent.SetAssemblyName(project.AssemblyName).SetLocation(project.OutputAssemblyFullPath);
this.cacheFileName = GetCacheFileName(FileName.Create(project.FileName)); this.cacheFileName = GetCacheFileName(FileName.Create(project.FileName));
@ -240,6 +240,30 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
public void SetAssemblyName(string newAssemblyName)
{
lock (lockObj) {
if (!disposed) {
if (projectContent.FullAssemblyName == newAssemblyName)
return;
projectContent = projectContent.SetAssemblyName(newAssemblyName);
SD.ParserService.InvalidateCurrentSolutionSnapshot();
}
}
}
public void SetLocation(string newLocation)
{
lock (lockObj) {
if (!disposed) {
if (projectContent.Location == newLocation)
return;
projectContent = projectContent.SetLocation(newLocation);
SD.ParserService.InvalidateCurrentSolutionSnapshot();
}
}
}
public void SetCompilerSettings(object compilerSettings) public void SetCompilerSettings(object compilerSettings)
{ {
lock (lockObj) { lock (lockObj) {

Loading…
Cancel
Save