optimise updating document content in workspace
This commit is contained in:
@@ -603,10 +603,12 @@ public static class RoslynAnalysis
|
|||||||
public static async Task<(ISymbol?, LinePositionSpan?)> LookupSymbol(SharpIdeFile fileModel, LinePosition linePosition)
|
public static async Task<(ISymbol?, LinePositionSpan?)> LookupSymbol(SharpIdeFile fileModel, LinePosition linePosition)
|
||||||
{
|
{
|
||||||
await _solutionLoadedTcs.Task;
|
await _solutionLoadedTcs.Task;
|
||||||
var (symbol, linePositionSpan) =
|
var (symbol, linePositionSpan) = fileModel switch
|
||||||
fileModel.IsRazorFile ? await LookupSymbolInRazor(fileModel, linePosition)
|
{
|
||||||
: fileModel.IsCsharpFile ? await LookupSymbolInCs(fileModel, linePosition)
|
{ IsRazorFile: true } => await LookupSymbolInRazor(fileModel, linePosition),
|
||||||
: (null, null);
|
{ IsCsharpFile: true } => await LookupSymbolInCs(fileModel, linePosition),
|
||||||
|
_ => (null, null)
|
||||||
|
};
|
||||||
return (symbol, linePositionSpan);
|
return (symbol, linePositionSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,24 +682,37 @@ public static class RoslynAnalysis
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateDocument(SharpIdeFile fileModel, string newContent)
|
public static async Task UpdateDocument(SharpIdeFile fileModel, string newContent)
|
||||||
{
|
{
|
||||||
Guard.Against.Null(fileModel, nameof(fileModel));
|
Guard.Against.Null(fileModel, nameof(fileModel));
|
||||||
Guard.Against.NullOrEmpty(newContent, nameof(newContent));
|
Guard.Against.NullOrEmpty(newContent, nameof(newContent));
|
||||||
|
|
||||||
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath);
|
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath);
|
||||||
if (fileModel.IsRazorFile)
|
|
||||||
|
var sourceText = SourceText.From(newContent);
|
||||||
|
var document = fileModel switch
|
||||||
{
|
{
|
||||||
var razorDocument = project.AdditionalDocuments.Single(s => s.FilePath == fileModel.Path);
|
{ IsRazorFile: true } => project.AdditionalDocuments.Single(s => s.FilePath == fileModel.Path),
|
||||||
var newSolution = _workspace.CurrentSolution.WithAdditionalDocumentText(razorDocument.Id, SourceText.From(newContent));
|
{ IsCsharpFile: true } => project.Documents.Single(s => s.FilePath == fileModel.Path),
|
||||||
_workspace.TryApplyChanges(newSolution);
|
_ => throw new InvalidOperationException("UpdateDocument failed: File is not in workspace")
|
||||||
}
|
};
|
||||||
else
|
|
||||||
|
var oldText = await document.GetTextAsync();
|
||||||
|
|
||||||
|
// Compute minimal text changes
|
||||||
|
var changes = sourceText.GetChangeRanges(oldText);
|
||||||
|
if (changes.Count == 0)
|
||||||
|
return; // No changes, nothing to apply
|
||||||
|
|
||||||
|
var newText = oldText.WithChanges(sourceText.GetTextChanges(oldText));
|
||||||
|
|
||||||
|
var newSolution = fileModel switch
|
||||||
{
|
{
|
||||||
var document = project.Documents.Single(s => s.FilePath == fileModel.Path);
|
{ IsRazorFile: true } => _workspace.CurrentSolution.WithAdditionalDocumentText(document.Id, newText),
|
||||||
Guard.Against.Null(document, nameof(document));
|
{ IsCsharpFile: true } => _workspace.CurrentSolution.WithDocumentText(document.Id, newText),
|
||||||
var newSolution = _workspace.CurrentSolution.WithDocumentText(document.Id, SourceText.From(newContent));
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
_workspace.TryApplyChanges(newSolution);
|
};
|
||||||
}
|
|
||||||
|
_workspace.TryApplyChanges(newSolution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class IdeFileManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calling this assumes that the file is already open - may need to be revisited for code fixes and refactorings. I think all files involved in a multi-file fix/refactor shall just be saved to disk immediately.
|
// Calling this assumes that the file is already open - may need to be revisited for code fixes and refactorings. I think all files involved in a multi-file fix/refactor shall just be saved to disk immediately.
|
||||||
public void UpdateFileTextInMemory(SharpIdeFile file, string newText)
|
public async Task UpdateFileTextInMemory(SharpIdeFile file, string newText)
|
||||||
{
|
{
|
||||||
if (!_openFiles.ContainsKey(file)) throw new InvalidOperationException("File is not open in memory.");
|
if (!_openFiles.ContainsKey(file)) throw new InvalidOperationException("File is not open in memory.");
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ public class IdeFileManager
|
|||||||
// Potentially should be event based?
|
// Potentially should be event based?
|
||||||
if (file.IsRoslynWorkspaceFile)
|
if (file.IsRoslynWorkspaceFile)
|
||||||
{
|
{
|
||||||
RoslynAnalysis.UpdateDocument(file, newText);
|
await RoslynAnalysis.UpdateDocument(file, newText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ public class IdeFileManager
|
|||||||
if (file.IsRoslynWorkspaceFile)
|
if (file.IsRoslynWorkspaceFile)
|
||||||
{
|
{
|
||||||
var text = await textTask;
|
var text = await textTask;
|
||||||
RoslynAnalysis.UpdateDocument(file, text);
|
await RoslynAnalysis.UpdateDocument(file, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ public class IdeFileManager
|
|||||||
{
|
{
|
||||||
if (_openFiles.ContainsKey(file))
|
if (_openFiles.ContainsKey(file))
|
||||||
{
|
{
|
||||||
UpdateFileTextInMemory(file, newText);
|
await UpdateFileTextInMemory(file, newText);
|
||||||
await SaveFileAsync(file);
|
await SaveFileAsync(file);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
{
|
{
|
||||||
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
|
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
|
||||||
_currentFile.IsDirty.Value = true;
|
_currentFile.IsDirty.Value = true;
|
||||||
Singletons.FileManager.UpdateFileTextInMemory(_currentFile, Text);
|
await Singletons.FileManager.UpdateFileTextInMemory(_currentFile, Text);
|
||||||
_ = Task.GodotRun(async () =>
|
_ = Task.GodotRun(async () =>
|
||||||
{
|
{
|
||||||
var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile);
|
var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile);
|
||||||
|
|||||||
Reference in New Issue
Block a user