Browse Source

Enable new context actions (Create Local, Extract Field, Implement Interface).

Allow clicking on track adorners.
Don't serialize project content on shutdown when it hasn't changed.
newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
80dc644829
  1. 14
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  3. 16
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRedundantUsingIssue.cs
  4. 50
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EnhancedScrollBar.cs
  5. 4
      src/Main/Base/Project/Src/Project/MSBuildInternals.cs
  6. 79
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

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

@ -145,7 +145,7 @@
<Class id = "RedundantThis" <Class id = "RedundantThis"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantThisIssue" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantThisIssue" />
<Class id = "RedundantUsing" <Class id = "RedundantUsing"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantUsingIssue" /> class = "CSharpBinding.Refactoring.SDRedundantUsingIssue" />
<Class id = "StringIsNullOrEmpty" <Class id = "StringIsNullOrEmpty"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringIsNullOrEmptyIssue" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringIsNullOrEmptyIssue" />
<Class id = "UseVarKeyword" <Class id = "UseVarKeyword"
@ -178,18 +178,20 @@
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateDelegateAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateDelegateAction" />
<CSharpCodeActionProvider id = "CreateEventInvocator" <CSharpCodeActionProvider id = "CreateEventInvocator"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateEventInvocatorAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateEventInvocatorAction" />
<CSharpCodeActionProvider id = "CreateLocalVariable"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateLocalVariableAction" />
<CSharpCodeActionProvider id = "CreateField" <CSharpCodeActionProvider id = "CreateField"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateFieldAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateFieldAction" />
<CSharpCodeActionProvider id = "CreateIndexer" <CSharpCodeActionProvider id = "CreateIndexer"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateIndexerAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateIndexerAction" />
<CSharpCodeActionProvider id = "CreateLocalVariable"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateLocalVariableAction" />
<CSharpCodeActionProvider id = "CreateMethodDeclaration" <CSharpCodeActionProvider id = "CreateMethodDeclaration"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateMethodDeclarationAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateMethodDeclarationAction" />
<CSharpCodeActionProvider id = "CreateProperty" <CSharpCodeActionProvider id = "CreateProperty"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreatePropertyAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreatePropertyAction" />
<CSharpCodeActionProvider id = "DeclareLocalVariable" <CSharpCodeActionProvider id = "DeclareLocalVariable"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.DeclareLocalVariableAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.DeclareLocalVariableAction" />
<CSharpCodeActionProvider id = "ExtractField"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtractFieldAction" />
<CSharpCodeActionProvider id = "FlipOperatorArguments" <CSharpCodeActionProvider id = "FlipOperatorArguments"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.FlipOperatorArgumentsAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.FlipOperatorArgumentsAction" />
<CSharpCodeActionProvider id = "GenerateGetter" <CSharpCodeActionProvider id = "GenerateGetter"
@ -198,6 +200,12 @@
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GeneratePropertyAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.GeneratePropertyAction" />
<CSharpCodeActionProvider id = "GenerateSwitchLabels" <CSharpCodeActionProvider id = "GenerateSwitchLabels"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateSwitchLabelsAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateSwitchLabelsAction" />
<CSharpCodeActionProvider id = "ImplementAbstractMembers"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ImplementAbstractMembersAction" />
<CSharpCodeActionProvider id = "ImplementInterface"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ImplementInterfaceAction" />
<CSharpCodeActionProvider id = "ImplementInterfaceExplicit"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ImplementInterfaceExplicitAction" />
<CSharpCodeActionProvider id = "InlineLocalVariable" <CSharpCodeActionProvider id = "InlineLocalVariable"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.InlineLocalVariableAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.InlineLocalVariableAction" />
<CSharpCodeActionProvider id = "InsertAnonymousMethodSignature" <CSharpCodeActionProvider id = "InsertAnonymousMethodSignature"

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

@ -74,6 +74,7 @@
<Compile Include="Src\Refactoring\CSharpContextActionWrapper.cs" /> <Compile Include="Src\Refactoring\CSharpContextActionWrapper.cs" />
<Compile Include="Src\Refactoring\IssueManager.cs" /> <Compile Include="Src\Refactoring\IssueManager.cs" />
<Compile Include="Src\Refactoring\IssueOptionsViewModel.cs" /> <Compile Include="Src\Refactoring\IssueOptionsViewModel.cs" />
<Compile Include="Src\Refactoring\SDRedundantUsingIssue.cs" />
<Compile Include="Src\Refactoring\SDScript.cs" /> <Compile Include="Src\Refactoring\SDScript.cs" />
<EmbeddedResource Include="Resources\BuildOptions.xfrm" /> <EmbeddedResource Include="Resources\BuildOptions.xfrm" />
<EmbeddedResource Include="Resources\MyNamespaceSupportForCSharp.cs" /> <EmbeddedResource Include="Resources\MyNamespaceSupportForCSharp.cs" />

16
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRedundantUsingIssue.cs

@ -0,0 +1,16 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace CSharpBinding.Refactoring
{
public class SDRedundantUsingIssue : RedundantUsingIssue
{
public SDRedundantUsingIssue()
{
base.NamespacesToKeep.Add("System");
}
}
}

50
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EnhancedScrollBar.cs

@ -214,6 +214,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.editor = enhanchedScrollBar.editor; this.editor = enhanchedScrollBar.editor;
this.textMarkerService = enhanchedScrollBar.textMarkerService; this.textMarkerService = enhanchedScrollBar.textMarkerService;
this.Cursor = Cursors.Hand;
triangleGeometry = new StreamGeometry(); triangleGeometry = new StreamGeometry();
using (var ctx = triangleGeometry.Open()) { using (var ctx = triangleGeometry.Open()) {
const double triangleSize = 6.5; const double triangleSize = 6.5;
@ -247,7 +249,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
var textView = editor.TextArea.TextView; var textView = editor.TextArea.TextView;
double documentHeight = textView.DocumentHeight; double documentHeight = textView.DocumentHeight;
foreach (var marker in textMarkerService.TextMarkers) { foreach (var marker in textMarkerService.TextMarkers) {
if ((marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle | TextMarkerTypes.ScrollBarRightTriangle)) == 0) if (!IsVisibleInAdorner(marker))
continue; continue;
var location = document.GetLocation(marker.StartOffset); var location = document.GetLocation(marker.StartOffset);
double visualTop = textView.GetVisualTopByDocumentLine(location.Line); double visualTop = textView.GetVisualTopByDocumentLine(location.Line);
@ -271,6 +273,52 @@ namespace ICSharpCode.AvalonEdit.AddIn
drawingContext.Pop(); drawingContext.Pop();
} }
} }
bool IsVisibleInAdorner(ITextMarker marker)
{
return (marker.MarkerTypes & (TextMarkerTypes.ScrollBarLeftTriangle | TextMarkerTypes.ScrollBarRightTriangle)) != 0;
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
var marker = FindNextMarker(e);
if (marker != null) {
var location = editor.Document.GetLocation(marker.StartOffset);
// Use JumpTo() if possible
var textEditor = editor.TextArea.GetService(typeof(ITextEditor)) as ITextEditor;
if (textEditor != null)
textEditor.JumpTo(location.Line, location.Column);
else
editor.ScrollTo(location.Line, location.Column);
}
}
ITextMarker FindNextMarker(MouseButtonEventArgs e)
{
var mousePos = e.GetPosition(this);
var renderSize = this.RenderSize;
var document = editor.Document;
var textView = editor.TextArea.TextView;
double documentHeight = textView.DocumentHeight;
ITextMarker bestMarker = null;
double bestDistance = double.PositiveInfinity;
foreach (var marker in textMarkerService.TextMarkers) {
if (!IsVisibleInAdorner(marker))
continue;
var location = document.GetLocation(marker.StartOffset);
double visualTop = textView.GetVisualTopByDocumentLine(location.Line);
double renderPos = visualTop / documentHeight * renderSize.Height;
double distance = Math.Abs(renderPos - mousePos.Y);
if (distance < bestDistance) {
bestDistance = distance;
bestMarker = marker;
}
}
return bestMarker;
}
} }
#endregion #endregion
} }

4
src/Main/Base/Project/Src/Project/MSBuildInternals.cs

@ -220,11 +220,11 @@ namespace ICSharpCode.SharpDevelop.Project
BuildParameters parameters = new BuildParameters(baseProject.MSBuildProjectCollection); BuildParameters parameters = new BuildParameters(baseProject.MSBuildProjectCollection);
parameters.Loggers = loggers; parameters.Loggers = loggers;
LoggingService.Debug("Started build for ResolveAssemblyReferences"); //LoggingService.Debug("Started build for ResolveAssemblyReferences");
BuildResult result = BuildManager.DefaultBuildManager.Build(parameters, requestData); BuildResult result = BuildManager.DefaultBuildManager.Build(parameters, requestData);
if (result == null) if (result == null)
throw new InvalidOperationException("BuildResult is null"); throw new InvalidOperationException("BuildResult is null");
LoggingService.Debug("Build for ResolveAssemblyReferences finished: " + result.OverallResult); //LoggingService.Debug("Build for ResolveAssemblyReferences finished: " + result.OverallResult);
} }
IEnumerable<ProjectItemInstance> resolvedAssemblyProjectItems = project.GetItems("_ResolveAssemblyReferenceResolvedFiles"); IEnumerable<ProjectItemInstance> resolvedAssemblyProjectItems = project.GetItems("_ResolveAssemblyReferenceResolvedFiles");

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

@ -33,6 +33,14 @@ namespace ICSharpCode.SharpDevelop.Parser
IAssemblyReference[] references = { MinimalCorlib.Instance }; IAssemblyReference[] references = { MinimalCorlib.Instance };
bool disposed; bool disposed;
/// <summary>
/// Counter that gets decremented whenever a file gets parsed.
/// Once the counter reaches zero, it stays at zero and triggers
/// serialization of the project content on disposal.
/// This is intended to prevent serialization of (almost) unchanged projects.
/// </summary>
bool serializedProjectContentIsUpToDate;
// time necessary for loading references, in relation to time for a single C# file // time necessary for loading references, in relation to time for a single C# file
const int LoadingReferencesWorkAmount = 15; const int LoadingReferencesWorkAmount = 15;
@ -69,37 +77,55 @@ namespace ICSharpCode.SharpDevelop.Parser
{ {
ProjectService.ProjectItemAdded -= OnProjectItemAdded; ProjectService.ProjectItemAdded -= OnProjectItemAdded;
ProjectService.ProjectItemRemoved -= OnProjectItemRemoved; ProjectService.ProjectItemRemoved -= OnProjectItemRemoved;
IProjectContent pc;
bool serializeOnDispose;
lock (lockObj) { lock (lockObj) {
if (disposed) if (disposed)
return; return;
disposed = true; disposed = true;
pc = this.projectContent;
serializeOnDispose = !this.serializedProjectContentIsUpToDate;
} }
foreach (var parsedFile in projectContent.Files) { foreach (var parsedFile in pc.Files) {
SD.ParserService.RemoveOwnerProject(FileName.Create(parsedFile.FileName), project); SD.ParserService.RemoveOwnerProject(FileName.Create(parsedFile.FileName), project);
} }
var pc = projectContent; if (serializeOnDispose)
Task.Run( SerializeAsync(cacheFileName, pc).FireAndForget();
}
#region Caching logic (serialization)
static Task SerializeAsync(string cacheFileName, IProjectContent pc)
{
if (cacheFileName == null)
return Task.FromResult<object>(null);
return Task.Run(
delegate { delegate {
pc = pc.RemoveAssemblyReferences(pc.AssemblyReferences); pc = pc.RemoveAssemblyReferences(pc.AssemblyReferences);
int serializableFileCount = 0; int serializableFileCount = 0;
List<IParsedFile> nonSerializableParsedFiles = new List<IParsedFile>(); List<IParsedFile> nonSerializableParsedFiles = new List<IParsedFile>();
foreach (var parsedFile in pc.Files) { foreach (var parsedFile in pc.Files) {
if (!parsedFile.GetType().IsSerializable || parsedFile.LastWriteTime == default(DateTime)) if (IsSerializable(parsedFile))
nonSerializableParsedFiles.Add(parsedFile);
else
serializableFileCount++; serializableFileCount++;
else
nonSerializableParsedFiles.Add(parsedFile);
} }
// remove non-serializable parsed files // remove non-serializable parsed files
if (nonSerializableParsedFiles.Count > 0) if (nonSerializableParsedFiles.Count > 0)
pc = pc.UpdateProjectContent(nonSerializableParsedFiles, null); pc = pc.UpdateProjectContent(nonSerializableParsedFiles, null);
if (serializableFileCount > 3) if (serializableFileCount > 3) {
LoggingService.Debug("Serializing " + serializableFileCount + " files to " + cacheFileName);
SaveToCache(cacheFileName, pc); SaveToCache(cacheFileName, pc);
else } else {
RemoveCache(cacheFileName); RemoveCache(cacheFileName);
}).FireAndForget(); }
});
} }
#region Caching logic (serialization) static bool IsSerializable(IParsedFile parsedFile)
{
return parsedFile != null && parsedFile.GetType().IsSerializable && parsedFile.LastWriteTime != default(DateTime);
}
static string GetCacheFileName(FileName projectFileName) static string GetCacheFileName(FileName projectFileName)
{ {
@ -139,9 +165,6 @@ namespace ICSharpCode.SharpDevelop.Parser
static void SaveToCache(string cacheFileName, IProjectContent pc) static void SaveToCache(string cacheFileName, IProjectContent pc)
{ {
if (cacheFileName == null)
return;
LoggingService.Debug("Serializing to " + cacheFileName);
try { try {
Directory.CreateDirectory(Path.GetDirectoryName(cacheFileName)); Directory.CreateDirectory(Path.GetDirectoryName(cacheFileName));
using (FileStream fs = new FileStream(cacheFileName, FileMode.Create, FileAccess.Write)) { using (FileStream fs = new FileStream(cacheFileName, FileMode.Create, FileAccess.Write)) {
@ -160,7 +183,7 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
void RemoveCache(string cacheFileName) static void RemoveCache(string cacheFileName)
{ {
if (cacheFileName == null) if (cacheFileName == null)
return; return;
@ -187,8 +210,10 @@ namespace ICSharpCode.SharpDevelop.Parser
{ {
// This method is called by the parser service within the parser service (per-file) lock. // This method is called by the parser service within the parser service (per-file) lock.
lock (lockObj) { lock (lockObj) {
if (!disposed) if (!disposed) {
projectContent = projectContent.UpdateProjectContent(oldFile, newFile); projectContent = projectContent.UpdateProjectContent(oldFile, newFile);
serializedProjectContentIsUpToDate = false;
}
SD.ParserService.InvalidateCurrentSolutionSnapshot(); SD.ParserService.InvalidateCurrentSolutionSnapshot();
} }
} }
@ -228,6 +253,9 @@ namespace ICSharpCode.SharpDevelop.Parser
object progressLock = new object(); object progressLock = new object();
double fileCountInverse = 1.0 / filesToParse.Count; double fileCountInverse = 1.0 / filesToParse.Count;
int fileCountLoadedFromCache = 0;
int fileCountParsed = 0;
int fileCountParsedAndSerializable = 0;
Parallel.ForEach( Parallel.ForEach(
filesToParse, filesToParse,
new ParallelOptions { new ParallelOptions {
@ -237,8 +265,9 @@ namespace ICSharpCode.SharpDevelop.Parser
fileName => { fileName => {
ITextSource content = finder.CreateForOpenFile(fileName); ITextSource content = finder.CreateForOpenFile(fileName);
bool wasLoadedFromCache = false; bool wasLoadedFromCache = false;
IParsedFile parsedFile = null;
if (content == null && cachedPC != null) { if (content == null && cachedPC != null) {
IParsedFile parsedFile = cachedPC.GetFile(fileName); parsedFile = cachedPC.GetFile(fileName);
if (parsedFile != null && parsedFile.LastWriteTime == File.GetLastWriteTimeUtc(fileName)) { if (parsedFile != null && parsedFile.LastWriteTime == File.GetLastWriteTimeUtc(fileName)) {
SD.ParserService.RegisterParsedFile(fileName, project, parsedFile); SD.ParserService.RegisterParsedFile(fileName, project, parsedFile);
wasLoadedFromCache = true; wasLoadedFromCache = true;
@ -253,14 +282,26 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
if (content != null) { if (content != null) {
SD.ParserService.ParseFile(fileName, content, project); parsedFile = SD.ParserService.ParseFile(fileName, content, project);
} }
} }
lock (progressLock) { lock (progressLock) {
if (wasLoadedFromCache) {
fileCountLoadedFromCache++;
} else {
fileCountParsed++;
if (IsSerializable(parsedFile))
fileCountParsedAndSerializable++;
}
progressMonitor.Progress += fileCountInverse; progressMonitor.Progress += fileCountInverse;
} }
} });
); LoggingService.Debug(projectContent.AssemblyName + ": ParseFiles() finished. "
+ fileCountLoadedFromCache + " files were re-used from CC cache; "
+ fileCountParsed + " files were parsed (" + fileCountParsedAndSerializable + " of those are serializable)");
lock (lockObj) {
serializedProjectContentIsUpToDate = (fileCountLoadedFromCache > 0 && fileCountParsedAndSerializable == 0);
}
} }
Task ResolveReferencesAsync(ICollection<ProjectItem> projectItems, IProgressMonitor progressMonitor) Task ResolveReferencesAsync(ICollection<ProjectItem> projectItems, IProgressMonitor progressMonitor)

Loading…
Cancel
Save