Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/Compilers/Test/Core/FX/EncodingUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System.Text;

namespace Roslyn.Test.Utilities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,25 @@ public async ValueTask<ManagedHotReloadUpdates> GetUpdatesAsync(ImmutableArray<s
break;
}

UpdateApplyChangesDiagnostics(result.Diagnostics);
ArrayBuilder<DiagnosticData>? deletedDocumentRudeEdits = null;
foreach (var rudeEdit in result.RudeEdits)
{
if (await solution.GetDocumentAsync(rudeEdit.DocumentId, includeSourceGenerated: true, cancellationToken).ConfigureAwait(false) == null)
{
deletedDocumentRudeEdits ??= ArrayBuilder<DiagnosticData>.GetInstance();
deletedDocumentRudeEdits.Add(rudeEdit);
}
}

if (deletedDocumentRudeEdits != null)
{
deletedDocumentRudeEdits.AddRange(result.Diagnostics);
UpdateApplyChangesDiagnostics(deletedDocumentRudeEdits.ToImmutableAndFree());
}
else
{
UpdateApplyChangesDiagnostics(result.Diagnostics);
}

return new ManagedHotReloadUpdates(
result.ModuleUpdates.Updates.FromContract(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,14 @@ await localWorkspace.ChangeSolutionAsync(localWorkspace.CurrentSolution
var projectDiagnostic = CodeAnalysis.Diagnostic.Create(diagnosticDescriptor1, Location.None, ["proj", "error 2"]);
var syntaxError = CodeAnalysis.Diagnostic.Create(diagnosticDescriptor1, Location.Create(syntaxTree, TextSpan.FromBounds(1, 2)), ["doc", "syntax error 3"]);
var rudeEditDiagnostic = new RudeEditDiagnostic(RudeEditKind.Delete, TextSpan.FromBounds(2, 3), arguments: ["x"]).ToDiagnostic(syntaxTree);
var deletedDocumentRudeEdit = new RudeEditDiagnostic(RudeEditKind.Delete, TextSpan.FromBounds(2, 3), arguments: ["<deleted>"]).ToDiagnostic(tree: null);

return new()
{
Solution = solution,
ModuleUpdates = new ModuleUpdates(ModuleUpdateStatus.Ready, []),
Diagnostics = [new ProjectDiagnostics(project.Id, [documentDiagnostic, projectDiagnostic])],
RudeEdits = [new ProjectDiagnostics(project.Id, [rudeEditDiagnostic])],
RudeEdits = [new ProjectDiagnostics(project.Id, [rudeEditDiagnostic, deletedDocumentRudeEdit])],
SyntaxError = syntaxError,
ProjectsToRebuild = [project.Id],
ProjectsToRestart = ImmutableDictionary<ProjectId, ImmutableArray<ProjectId>>.Empty.Add(project.Id, [])
Expand All @@ -185,6 +186,7 @@ await localWorkspace.ChangeSolutionAsync(localWorkspace.CurrentSolution

AssertEx.Equal(
[
$"Error ENC0033: {project.FilePath}(0, 0, 0, 0): {string.Format(FeaturesResources.Deleting_0_requires_restarting_the_application, "<deleted>")}",
$"Error ENC1001: {document.FilePath}(0, 1, 0, 2): {string.Format(FeaturesResources.ErrorReadingFile, "doc", "error 1")}",
$"Error ENC1001: {project.FilePath}(0, 0, 0, 0): {string.Format(FeaturesResources.ErrorReadingFile, "proj", "error 2")}"
], sessionState.ApplyChangesDiagnostics.Select(Inspect));
Expand All @@ -194,7 +196,8 @@ await localWorkspace.ChangeSolutionAsync(localWorkspace.CurrentSolution
$"Error ENC1001: {document.FilePath}(0, 1, 0, 2): {string.Format(FeaturesResources.ErrorReadingFile, "doc", "error 1")}",
$"Error ENC1001: {project.FilePath}(0, 0, 0, 0): {string.Format(FeaturesResources.ErrorReadingFile, "proj", "error 2")}",
$"Error ENC1001: {document.FilePath}(0, 1, 0, 2): {string.Format(FeaturesResources.ErrorReadingFile, "doc", "syntax error 3")}",
$"RestartRequired ENC0033: {document.FilePath}(0, 2, 0, 3): {string.Format(FeaturesResources.Deleting_0_requires_restarting_the_application, "x")}"
$"RestartRequired ENC0033: {document.FilePath}(0, 2, 0, 3): {string.Format(FeaturesResources.Deleting_0_requires_restarting_the_application, "x")}",
$"RestartRequired ENC0033: {project.FilePath}(0, 0, 0, 0): {string.Format(FeaturesResources.Deleting_0_requires_restarting_the_application, "<deleted>")}",
], updates.Diagnostics.Select(Inspect));

Assert.True(sessionState.IsSessionActive);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,22 +179,6 @@ internal override bool IsDeclarationWithSharedBody(SyntaxNode declaration, ISymb
protected override bool AreHandledEventsEqual(IMethodSymbol oldMethod, IMethodSymbol newMethod)
=> true;

protected override IEnumerable<SyntaxNode> GetVariableUseSites(IEnumerable<SyntaxNode> roots, ISymbol localOrParameter, SemanticModel model, CancellationToken cancellationToken)
{
Debug.Assert(localOrParameter is IParameterSymbol or ILocalSymbol or IRangeVariableSymbol);

// not supported (it's non trivial to find all places where "this" is used):
Debug.Assert(!localOrParameter.IsThisParameter());

return from root in roots
from node in root.DescendantNodesAndSelf()
where node.IsKind(SyntaxKind.IdentifierName)
let nameSyntax = (IdentifierNameSyntax)node
where (string?)nameSyntax.Identifier.Value == localOrParameter.Name &&
(model.GetSymbolInfo(nameSyntax, cancellationToken).Symbol?.Equals(localOrParameter) ?? false)
select node;
}

internal static SyntaxNode FindStatementAndPartner(
TextSpan span,
SyntaxNode body,
Expand Down Expand Up @@ -1042,8 +1026,8 @@ WellKnownMemberNames.ObjectToString or
EditKind editKind,
SyntaxNode? oldNode,
SyntaxNode? newNode,
SemanticModel? oldModel,
SemanticModel newModel,
DocumentSemanticModel oldModel,
DocumentSemanticModel newModel,
CancellationToken cancellationToken)
{
// Chnage in type of a field affects all its variable declarations.
Expand All @@ -1060,21 +1044,19 @@ WellKnownMemberNames.ObjectToString or

OneOrMany<(ISymbol? oldSymbol, ISymbol? newSymbol)> AddFieldSymbolUpdates(SeparatedSyntaxList<VariableDeclaratorSyntax> oldVariables, SeparatedSyntaxList<VariableDeclaratorSyntax> newVariables)
{
Debug.Assert(oldModel != null);

if (oldVariables.Count == 1 && newVariables.Count == 1)
{
return OneOrMany.Create((GetDeclaredSymbol(oldModel, oldVariables[0], cancellationToken), GetDeclaredSymbol(newModel, newVariables[0], cancellationToken)));
return OneOrMany.Create((GetDeclaredSymbol(oldModel.RequiredModel, oldVariables[0], cancellationToken), GetDeclaredSymbol(newModel.RequiredModel, newVariables[0], cancellationToken)));
}

return OneOrMany.Create(
(from oldVariable in oldVariables
join newVariable in newVariables on oldVariable.Identifier.Text equals newVariable.Identifier.Text
select (GetDeclaredSymbol(oldModel, oldVariable, cancellationToken), GetDeclaredSymbol(newModel, newVariable, cancellationToken))).ToImmutableArray());
select (GetDeclaredSymbol(oldModel.RequiredModel, oldVariable, cancellationToken), GetDeclaredSymbol(newModel.RequiredModel, newVariable, cancellationToken))).ToImmutableArray());
}

var oldSymbol = (oldNode != null) ? GetSymbolForEdit(oldNode, oldModel!, cancellationToken) : null;
var newSymbol = (newNode != null) ? GetSymbolForEdit(newNode, newModel, cancellationToken) : null;
var oldSymbol = (oldNode != null) ? GetSymbolForEdit(oldNode, oldModel.RequiredModel, cancellationToken) : null;
var newSymbol = (newNode != null) ? GetSymbolForEdit(newNode, newModel.RequiredModel, cancellationToken) : null;

return (oldSymbol == null && newSymbol == null)
? OneOrMany<(ISymbol?, ISymbol?)>.Empty
Expand All @@ -1088,8 +1070,8 @@ protected override void AddSymbolEdits(
ISymbol? oldSymbol,
SyntaxNode? newNode,
ISymbol? newSymbol,
SemanticModel? oldModel,
SemanticModel newModel,
DocumentSemanticModel oldModel,
DocumentSemanticModel newModel,
Match<SyntaxNode> topMatch,
IReadOnlyDictionary<SyntaxNode, EditKind> editMap,
SymbolInfoCache symbolCache,
Expand All @@ -1101,7 +1083,7 @@ protected override void AddSymbolEdits(
var oldContainingMemberOrType = GetParameterContainingMemberOrType(oldNode, newNode, oldModel, topMatch.ReverseMatches, cancellationToken);
var newContainingMemberOrType = GetParameterContainingMemberOrType(newNode, oldNode, newModel, topMatch.Matches, cancellationToken);

var matchingNewContainingMemberOrType = GetSemanticallyMatchingNewSymbol(oldContainingMemberOrType, newContainingMemberOrType, newModel, symbolCache, cancellationToken);
var matchingNewContainingMemberOrType = GetSemanticallyMatchingNewSymbol(oldContainingMemberOrType, newContainingMemberOrType, newModel.Compilation, symbolCache, cancellationToken);

// Create candidate symbol edits to analyze:
// 1) An update of the containing member or type
Expand Down Expand Up @@ -1189,7 +1171,6 @@ newContainingMemberOrType is IPropertySymbol newPropertySymbol &&
case EditKind.Update:
Contract.ThrowIfNull(oldNode);
Contract.ThrowIfNull(newNode);
Contract.ThrowIfNull(oldModel);

// Updates of a property/indexer/event node might affect its accessors.
// Return all affected symbols for these updates so that the changes in the accessor bodies get analyzed.
Expand Down Expand Up @@ -1372,7 +1353,6 @@ newNode is TypeDeclarationSyntax newTypeDeclaration &&
case EditKind.Move:
Contract.ThrowIfNull(oldNode);
Contract.ThrowIfNull(newNode);
Contract.ThrowIfNull(oldModel);

Debug.Assert(oldNode.RawKind == newNode.RawKind);
Debug.Assert(SupportsMove(oldNode));
Expand Down Expand Up @@ -1432,7 +1412,7 @@ newNode is TypeDeclarationSyntax newTypeDeclaration &&
return GetDeclaredSymbol(model, node, cancellationToken);
}

private ISymbol? GetParameterContainingMemberOrType(SyntaxNode? node, SyntaxNode? otherNode, SemanticModel? model, IReadOnlyDictionary<SyntaxNode, SyntaxNode> fromOtherMap, CancellationToken cancellationToken)
private ISymbol? GetParameterContainingMemberOrType(SyntaxNode? node, SyntaxNode? otherNode, DocumentSemanticModel model, IReadOnlyDictionary<SyntaxNode, SyntaxNode> fromOtherMap, CancellationToken cancellationToken)
{
Debug.Assert(node is null or ParameterSyntax or TypeParameterSyntax or TypeParameterConstraintClauseSyntax);

Expand All @@ -1457,7 +1437,7 @@ newNode is TypeDeclarationSyntax newTypeDeclaration &&
declaration = declaration.Parent;
}

return (declaration != null) ? GetDeclaredSymbol(model!, declaration, cancellationToken) : null;
return (declaration != null) ? GetDeclaredSymbol(model.RequiredModel, declaration, cancellationToken) : null;

static SyntaxNode GetContainingDeclaration(SyntaxNode node)
=> node is TypeParameterSyntax ? node.Parent!.Parent! : node!.Parent!;
Expand Down Expand Up @@ -2857,10 +2837,10 @@ internal override void ReportOtherRudeEditsAroundActiveStatement(
IReadOnlyDictionary<SyntaxNode, SyntaxNode> reverseMap,
SyntaxNode oldActiveStatement,
DeclarationBody oldBody,
SemanticModel oldModel,
DocumentSemanticModel oldModel,
SyntaxNode newActiveStatement,
DeclarationBody newBody,
SemanticModel newModel,
DocumentSemanticModel newModel,
bool isNonLeaf,
CancellationToken cancellationToken)
{
Expand Down Expand Up @@ -2991,10 +2971,10 @@ private void ReportRudeEditsForAncestorsDeclaringInterStatementTemps(
IReadOnlyDictionary<SyntaxNode, SyntaxNode> reverseMap,
SyntaxNode oldActiveStatement,
SyntaxNode oldEncompassingAncestor,
SemanticModel oldModel,
DocumentSemanticModel oldModel,
SyntaxNode newActiveStatement,
SyntaxNode newEncompassingAncestor,
SemanticModel newModel,
DocumentSemanticModel newModel,
CancellationToken cancellationToken)
{
// Rude Edits for fixed/using/lock/foreach statements that are added/updated around an active statement.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,9 @@ private static TestWorkspace CreateWorkspace()
=> new(composition: s_composition);

private static Solution AddDefaultTestProject(Solution solution, string source)
{
var projectId = ProjectId.CreateNewId();

return solution.
AddProject(ProjectInfo.Create(projectId, VersionStamp.Create(), "proj", "proj", LanguageNames.CSharp)).GetProject(projectId).
AddDocument("test.cs", SourceText.From(source, Encoding.UTF8), filePath: Path.Combine(TempRoot.Root, "test.cs")).Project.Solution;
}
=> solution.
AddTestProject("proj", LanguageNames.CSharp).
AddTestDocument(source, path: Path.Combine(TempRoot.Root, "test.cs")).Project.Solution;

private static void TestSpans(string source, Func<SyntaxNode, bool> hasLabel)
{
Expand Down Expand Up @@ -126,7 +122,7 @@ private static async Task<DocumentAnalysisResults> AnalyzeDocumentAsync(
var baseActiveStatements = AsyncLazy.Create(activeStatementMap ?? ActiveStatementsMap.Empty);
var lazyCapabilities = AsyncLazy.Create(capabilities);
var log = new TraceLog("Test");
return await analyzer.AnalyzeDocumentAsync(oldProject, baseActiveStatements, newDocument, newActiveStatementSpans.NullToEmpty(), lazyCapabilities, log, CancellationToken.None);
return await analyzer.AnalyzeDocumentAsync(newDocument.Id, oldProject, newDocument.Project, baseActiveStatements, newActiveStatementSpans.NullToEmpty(), lazyCapabilities, log, CancellationToken.None);
}

#endregion
Expand Down Expand Up @@ -455,14 +451,12 @@ public static void Main()
";
var experimentalFeatures = new Dictionary<string, string>(); // no experimental features to enable
var experimental = TestOptions.Regular.WithFeatures(experimentalFeatures);
var root = SyntaxFactory.ParseCompilationUnit(source, options: experimental);

using var workspace = CreateWorkspace();

var projectId = ProjectId.CreateNewId();
var oldSolution = workspace.CurrentSolution.
AddProject(ProjectInfo.Create(projectId, VersionStamp.Create(), "proj", "proj", LanguageNames.CSharp)).GetProject(projectId).
AddDocument("test.cs", root, filePath: Path.Combine(TempRoot.Root, "test.cs")).Project.Solution;
AddTestProject("proj", LanguageNames.CSharp).WithParseOptions(experimental).
AddTestDocument(source, path: Path.Combine(TempRoot.Root, "test.cs")).Project.Solution;

var oldProject = oldSolution.Projects.Single();
var oldDocument = oldProject.Documents.Single();
Expand Down Expand Up @@ -760,7 +754,7 @@ public async Task AnalyzeDocumentAsync_InternalError(bool outOfMemory)
};

var log = new TraceLog("Test");
var result = await analyzer.AnalyzeDocumentAsync(oldProject, baseActiveStatements, newDocument, [], capabilities, log, CancellationToken.None);
var result = await analyzer.AnalyzeDocumentAsync(newDocument.Id, oldProject, newDocument.Project, baseActiveStatements, [], capabilities, log, CancellationToken.None);

var expectedDiagnostic = outOfMemory
? $"ENC0089: {string.Format(FeaturesResources.Modifying_source_file_0_requires_restarting_the_application_because_the_file_is_too_big, filePath)}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal partial class AbstractEditAndContinueAnalyzer
/// Constructor to which field/property initializers are emitted is active if its body or any of the field/property initializers has an active statement outside of a lambda.
/// Fields and properties with initializers are considered active if any of the constructors that these initializers are emitted to are active.
/// </summary>
private readonly struct ActiveMembersBuilder(AbstractEditAndContinueAnalyzer analyzer, SemanticModel? oldModel, SemanticModel newModel, CancellationToken cancellationToken) : IDisposable
private readonly struct ActiveMembersBuilder(AbstractEditAndContinueAnalyzer analyzer, DocumentSemanticModel oldModel, DocumentSemanticModel newModel, CancellationToken cancellationToken) : IDisposable
{
private readonly PooledHashSet<IMethodSymbol> _methods = PooledHashSet<IMethodSymbol>.GetInstance();
private readonly PooledDictionary<SyntaxNode, SyntaxNode> _declarations = PooledDictionary<SyntaxNode, SyntaxNode>.GetInstance();
Expand Down
Loading