/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.CodeModelEventCollector.cs
985 строк
37 KB
Cyrus Najmabadi
Use file scoped namespaces. (#77854)
27 мар 2025, 09:55
Не верифицирован
27 мар 2025, 09:55
98d41b8
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // 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 // Taken from csharp\LanguageAnalysis\Compiler\IDE\LIB\CMEvents.cpp using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel; namespace Microsoft.VisualStudio.LanguageServices.CSharp.CodeModel; internal sealed partial class CSharpCodeModelService { protected override AbstractCodeModelEventCollector CreateCodeModelEventCollector() => new CodeModelEventCollector(this); private sealed class CodeModelEventCollector : AbstractCodeModelEventCollector { public CodeModelEventCollector(AbstractCodeModelService codeModelService) : base(codeModelService) { } private static IReadOnlyList<MemberDeclarationSyntax> GetValidMembers(SyntaxNode node) { return CSharpCodeModelService .GetChildMemberNodes(node) .Where(n => !n.IsKind(SyntaxKind.IncompleteMember)) .ToArray(); } private void CompareCompilationUnits( CompilationUnitSyntax oldCompilationUnit, CompilationUnitSyntax newCompilationUnit, CodeModelEventQueue eventQueue) { // Note: In the C# legacy code model, events are generated for the top-level // namespace that is at the root of every parse tree. In the Roslyn C# code model // implementation, we won't bother. CompareChildren( CompareNamespacesOrTypes, GetValidMembers(oldCompilationUnit), GetValidMembers(newCompilationUnit), (SyntaxNode)null, CodeModelEventType.Unknown, eventQueue); } private bool CompareAttributeLists( AttributeListSyntax oldAttributeList, AttributeListSyntax newAttributeList, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { return CompareChildren( CompareAttributes, oldAttributeList.Attributes.AsReadOnlyList(), newAttributeList.Attributes.AsReadOnlyList(), newNodeParent, CodeModelEventType.Unknown, eventQueue); } private bool CompareAttributes( AttributeSyntax oldAttribute, AttributeSyntax newAttribute, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldAttribute != null && newAttribute != null); var same = true; if (!CompareNames(oldAttribute.Name, newAttribute.Name)) { EnqueueChangeEvent(newAttribute, newNodeParent, CodeModelEventType.Rename, eventQueue); same = false; } // If arguments have changed enqueue a element changed (arguments changed) node if (!CompareAttributeArguments(oldAttribute.ArgumentList, newAttribute.ArgumentList)) { EnqueueChangeEvent(newAttribute, newNodeParent, CodeModelEventType.ArgChange, eventQueue); same = false; } return same; } private bool CompareAttributeArguments(AttributeArgumentListSyntax oldAttributeArguments, AttributeArgumentListSyntax newAttributeArguments) { if (oldAttributeArguments == null || newAttributeArguments == null) { return oldAttributeArguments == newAttributeArguments; } var oldArguments = oldAttributeArguments.Arguments; var newArguments = newAttributeArguments.Arguments; if (oldArguments.Count != newArguments.Count) { return false; } for (var i = 0; i < oldArguments.Count; i++) { var oldArgument = oldArguments[i]; var newArgument = newArguments[i]; if (!StringComparer.Ordinal.Equals(CodeModelService.GetName(oldArgument), CodeModelService.GetName(newArgument))) { return false; } if (!CompareExpressions(oldArgument.Expression, newArgument.Expression)) { return false; } } return true; } private bool CompareExpressions(ExpressionSyntax oldExpression, ExpressionSyntax newExpression) { if (oldExpression == null || newExpression == null) { return oldExpression == newExpression; } if (oldExpression.Kind() != newExpression.Kind()) { return false; } if (oldExpression is TypeSyntax typeSyntax) { return CompareTypes(typeSyntax, (TypeSyntax)newExpression); } if (oldExpression is LiteralExpressionSyntax) { return StringComparer.Ordinal.Equals(oldExpression.ToString(), newExpression.ToString()); } if (oldExpression is CastExpressionSyntax oldCast) { var newCast = (CastExpressionSyntax)newExpression; return CompareTypes(oldCast.Type, newCast.Type) && CompareExpressions(oldCast.Expression, newCast.Expression); } if (oldExpression is PrefixUnaryExpressionSyntax prefixUnary) { return CompareExpressions(prefixUnary.Operand, ((PrefixUnaryExpressionSyntax)newExpression).Operand); } if (oldExpression is AwaitExpressionSyntax awaitExpression) { return CompareExpressions(awaitExpression.Expression, ((AwaitExpressionSyntax)newExpression).Expression); } if (oldExpression is PostfixUnaryExpressionSyntax postfixUnary) { return CompareExpressions(postfixUnary.Operand, ((PostfixUnaryExpressionSyntax)newExpression).Operand); } if (oldExpression is BinaryExpressionSyntax oldBinaryExpression) { var newBinaryExpression = (BinaryExpressionSyntax)newExpression; return CompareExpressions(oldBinaryExpression.Left, newBinaryExpression.Left) && CompareExpressions(oldBinaryExpression.Right, newBinaryExpression.Right); } if (oldExpression is AssignmentExpressionSyntax oldAssignmentExpression) { var newAssignmentExpression = (AssignmentExpressionSyntax)newExpression; return CompareExpressions(oldAssignmentExpression.Left, newAssignmentExpression.Left) && CompareExpressions(oldAssignmentExpression.Right, newAssignmentExpression.Right); } if (oldExpression is MemberAccessExpressionSyntax oldMemberAccessExpression) { var newMemberAccessExpression = (MemberAccessExpressionSyntax)newExpression; return CompareExpressions(oldMemberAccessExpression.Expression, newMemberAccessExpression.Expression) && CompareExpressions(oldMemberAccessExpression.Name, newMemberAccessExpression.Name); } return true; } private bool CompareParameters(ParameterSyntax oldParameter, ParameterSyntax newParameter, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldParameter != null && newParameter != null); var same = true; if (!StringComparer.Ordinal.Equals(CodeModelService.GetName(oldParameter), CodeModelService.GetName(newParameter))) { EnqueueChangeEvent(newParameter, newNodeParent, CodeModelEventType.Rename, eventQueue); same = false; } // If modifiers or the type have changed enqueue a element changed (unknown change) node if (!CompareModifiers(oldParameter, newParameter) || !CompareTypes(oldParameter.Type, newParameter.Type)) { EnqueueChangeEvent(newParameter, newNodeParent, CodeModelEventType.Unknown, eventQueue); same = false; } return same; } private bool CompareMemberDeclarations( MemberDeclarationSyntax oldMember, MemberDeclarationSyntax newMember, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldMember != null && newMember != null); // If the kind doesn't match, it has to be a remove/add. if (oldMember.Kind() != newMember.Kind()) { EnqueueRemoveEvent(oldMember, newNodeParent, eventQueue); EnqueueAddEvent(newMember, newNodeParent, eventQueue); return false; } if (oldMember is BaseTypeDeclarationSyntax or DelegateDeclarationSyntax) { return CompareTypeDeclarations(oldMember, newMember, newNodeParent, eventQueue); } else if (oldMember is BaseMethodDeclarationSyntax baseMethod) { return CompareMethodDeclarations(baseMethod, (BaseMethodDeclarationSyntax)newMember, newNodeParent, eventQueue); } else if (oldMember is BaseFieldDeclarationSyntax baseField) { return CompareFieldDeclarations(baseField, (BaseFieldDeclarationSyntax)newMember, newNodeParent, eventQueue); } else if (oldMember is BasePropertyDeclarationSyntax baseProperty) { return ComparePropertyDeclarations(baseProperty, (BasePropertyDeclarationSyntax)newMember, newNodeParent, eventQueue); } else if (oldMember is EnumMemberDeclarationSyntax enumMember) { return CompareEnumMemberDeclarations(enumMember, (EnumMemberDeclarationSyntax)newMember, newNodeParent, eventQueue); } throw new NotImplementedException(); } private bool CompareEnumMemberDeclarations( EnumMemberDeclarationSyntax oldEnumMember, EnumMemberDeclarationSyntax newEnumMember, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldEnumMember != null && newEnumMember != null); var same = true; if (!StringComparer.Ordinal.Equals(CodeModelService.GetName(oldEnumMember), CodeModelService.GetName(newEnumMember))) { EnqueueChangeEvent(newEnumMember, newNodeParent, CodeModelEventType.Rename, eventQueue); same = false; } same &= CompareChildren( CompareAttributeLists, oldEnumMember.AttributeLists.AsReadOnlyList(), newEnumMember.AttributeLists.AsReadOnlyList(), newEnumMember, CodeModelEventType.Unknown, eventQueue); return same; } private bool ComparePropertyDeclarations( BasePropertyDeclarationSyntax oldProperty, BasePropertyDeclarationSyntax newProperty, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldProperty != null && newProperty != null); var same = true; if (!StringComparer.Ordinal.Equals(CodeModelService.GetName(oldProperty), CodeModelService.GetName(newProperty))) { EnqueueChangeEvent(newProperty, newNodeParent, CodeModelEventType.Rename, eventQueue); same = false; } // If modifiers have changed enqueue a element changed (unknown change) node if (!CompareModifiers(oldProperty, newProperty)) { EnqueueChangeEvent(newProperty, newNodeParent, CodeModelEventType.Unknown, eventQueue); same = false; } // If return type had changed enqueue a element changed (typeref changed) node if (!CompareTypes(oldProperty.Type, newProperty.Type)) { EnqueueChangeEvent(newProperty, newNodeParent, CodeModelEventType.TypeRefChange, eventQueue); same = false; } same &= CompareChildren( CompareAttributeLists, oldProperty.AttributeLists.AsReadOnlyList(), newProperty.AttributeLists.AsReadOnlyList(), newProperty, CodeModelEventType.Unknown, eventQueue); if (oldProperty is IndexerDeclarationSyntax oldIndexer) { var newIndexer = (IndexerDeclarationSyntax)newProperty; same &= CompareChildren( CompareParameters, oldIndexer.ParameterList.Parameters.AsReadOnlyList(), newIndexer.ParameterList.Parameters.AsReadOnlyList(), newIndexer, CodeModelEventType.SigChange, eventQueue); } return same; } private bool CompareVariableDeclarators( VariableDeclaratorSyntax oldVariableDeclarator, VariableDeclaratorSyntax newVariableDeclarator, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldVariableDeclarator != null && newVariableDeclarator != null); if (!StringComparer.Ordinal.Equals(CodeModelService.GetName(oldVariableDeclarator), CodeModelService.GetName(newVariableDeclarator))) { EnqueueChangeEvent(newVariableDeclarator, newNodeParent, CodeModelEventType.Rename, eventQueue); return false; } return true; } private bool CompareFieldDeclarations( BaseFieldDeclarationSyntax oldField, BaseFieldDeclarationSyntax newField, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldField != null && newField != null); var same = true; same &= CompareChildren( CompareVariableDeclarators, oldField.Declaration.Variables.AsReadOnlyList(), newField.Declaration.Variables.AsReadOnlyList(), newNodeParent, CodeModelEventType.Unknown, eventQueue); // If modifiers have changed enqueue a element changed (unknown change) node if (oldField.Kind() != newField.Kind() || !CompareModifiers(oldField, newField)) { EnqueueChangeEvent(newField, newNodeParent, CodeModelEventType.Unknown, eventQueue); same = false; } // If type had changed enqueue a element changed (typeref changed) node if (!CompareTypes(oldField.Declaration.Type, newField.Declaration.Type)) { EnqueueChangeEvent(newField, newNodeParent, CodeModelEventType.TypeRefChange, eventQueue); same = false; } same &= CompareChildren( CompareAttributeLists, oldField.AttributeLists.AsReadOnlyList(), newField.AttributeLists.AsReadOnlyList(), newField, CodeModelEventType.Unknown, eventQueue); return same; } private bool CompareMethodDeclarations( BaseMethodDeclarationSyntax oldMethod, BaseMethodDeclarationSyntax newMethod, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldMethod != null && newMethod != null); if (!StringComparer.Ordinal.Equals(CodeModelService.GetName(oldMethod), CodeModelService.GetName(newMethod))) { var change = CompareRenamedDeclarations( CompareParameters, oldMethod.ParameterList.Parameters.AsReadOnlyList(), newMethod.ParameterList.Parameters.AsReadOnlyList(), oldMethod, newMethod, newNodeParent, eventQueue); if (change == DeclarationChange.NameOnly) { EnqueueChangeEvent(newMethod, newNodeParent, CodeModelEventType.Rename, eventQueue); } return false; } else { var same = true; if (!CompareModifiers(oldMethod, newMethod)) { same = false; EnqueueChangeEvent(newMethod, newNodeParent, CodeModelEventType.Unknown, eventQueue); } if (!CompareTypes(GetReturnType(oldMethod), GetReturnType(newMethod))) { same = false; EnqueueChangeEvent(newMethod, newNodeParent, CodeModelEventType.TypeRefChange, eventQueue); } same &= CompareChildren( CompareAttributeLists, oldMethod.AttributeLists.AsReadOnlyList(), newMethod.AttributeLists.AsReadOnlyList(), newMethod, CodeModelEventType.Unknown, eventQueue); same &= CompareChildren( CompareParameters, oldMethod.ParameterList.Parameters.AsReadOnlyList(), newMethod.ParameterList.Parameters.AsReadOnlyList(), newMethod, CodeModelEventType.SigChange, eventQueue); return same; } } private bool CompareNamespaceDeclarations( BaseNamespaceDeclarationSyntax oldNamespace, BaseNamespaceDeclarationSyntax newNamespace, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldNamespace != null && newNamespace != null); // Check if the namespace nodes are identical w.r.t Name if (!CompareNames(oldNamespace.Name, newNamespace.Name)) { var change = CompareRenamedDeclarations( CompareNamespacesOrTypes, GetValidMembers(oldNamespace), GetValidMembers(newNamespace), oldNamespace, newNamespace, newNodeParent, eventQueue); if (change == DeclarationChange.NameOnly) { EnqueueChangeEvent(newNamespace, newNodeParent, CodeModelEventType.Rename, eventQueue); } return false; } return CompareChildren( CompareNamespacesOrTypes, GetValidMembers(oldNamespace), GetValidMembers(newNamespace), newNamespace, CodeModelEventType.Unknown, eventQueue); } private bool CompareTypeDeclarations( MemberDeclarationSyntax oldMember, MemberDeclarationSyntax newMember, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { Debug.Assert(oldMember != null && newMember != null); Debug.Assert(oldMember is BaseTypeDeclarationSyntax or DelegateDeclarationSyntax); Debug.Assert(newMember is BaseTypeDeclarationSyntax or DelegateDeclarationSyntax); // If the kind doesn't match, it has to be a remove/add. if (oldMember.Kind() != newMember.Kind()) { EnqueueRemoveEvent(oldMember, newNodeParent, eventQueue); EnqueueAddEvent(newMember, newNodeParent, eventQueue); return false; } if (oldMember is BaseTypeDeclarationSyntax oldType) { var newType = (BaseTypeDeclarationSyntax)newMember; var oldMembers = GetValidMembers(oldType); var newMembers = GetValidMembers(newType); var same = true; // If the type name is different, it might mean that the whole type has been removed and a new one added. // In that case, we shouldn't do any other checks and instead return immediately. if (!StringComparer.Ordinal.Equals(oldType.Identifier.ToString(), newType.Identifier.ToString())) { var change = CompareRenamedDeclarations( CompareMemberDeclarations, oldMembers, newMembers, oldType, newType, newNodeParent, eventQueue); if (change == DeclarationChange.WholeDeclaration) { return false; } same = false; EnqueueChangeEvent(newType, newNodeParent, CodeModelEventType.Rename, eventQueue); } if (!CompareModifiers(oldType, newType)) { same = false; EnqueueChangeEvent(newType, newNodeParent, CodeModelEventType.Unknown, eventQueue); } if (!CompareBaseLists(oldType, newType)) { same = false; EnqueueChangeEvent(newType, newNodeParent, CodeModelEventType.BaseChange, eventQueue); } same &= CompareChildren( CompareAttributeLists, oldType.AttributeLists.AsReadOnlyList(), newType.AttributeLists.AsReadOnlyList(), newType, CodeModelEventType.Unknown, eventQueue); same &= CompareChildren( CompareMemberDeclarations, oldMembers, newMembers, newType, CodeModelEventType.Unknown, eventQueue); return same; } else if (oldMember is DelegateDeclarationSyntax oldDelegate) { var newDelegate = (DelegateDeclarationSyntax)newMember; var same = true; // If the delegate name is different, it might mean that the whole delegate has been removed and a new one added. // In that case, we shouldn't do any other checks and instead return immediately. if (!StringComparer.Ordinal.Equals(oldDelegate.Identifier.ToString(), newDelegate.Identifier.ToString())) { var change = CompareRenamedDeclarations( CompareParameters, oldDelegate.ParameterList.Parameters.AsReadOnlyList(), newDelegate.ParameterList.Parameters.AsReadOnlyList(), oldDelegate, newDelegate, newNodeParent, eventQueue); if (change == DeclarationChange.WholeDeclaration) { return false; } same = false; EnqueueChangeEvent(newDelegate, newNodeParent, CodeModelEventType.Rename, eventQueue); } if (!CompareModifiers(oldDelegate, newDelegate)) { same = false; EnqueueChangeEvent(newDelegate, newNodeParent, CodeModelEventType.Unknown, eventQueue); } if (!CompareTypes(oldDelegate.ReturnType, newDelegate.ReturnType)) { same = false; EnqueueChangeEvent(newDelegate, newNodeParent, CodeModelEventType.TypeRefChange, eventQueue); } same &= CompareChildren( CompareAttributeLists, oldDelegate.AttributeLists.AsReadOnlyList(), newDelegate.AttributeLists.AsReadOnlyList(), newDelegate, CodeModelEventType.Unknown, eventQueue); same &= CompareChildren( CompareParameters, oldDelegate.ParameterList.Parameters.AsReadOnlyList(), newDelegate.ParameterList.Parameters.AsReadOnlyList(), newDelegate, CodeModelEventType.SigChange, eventQueue); return same; } return false; } private bool CompareNamespacesOrTypes( MemberDeclarationSyntax oldNamespaceOrType, MemberDeclarationSyntax newNamespaceOrType, SyntaxNode newNodeParent, CodeModelEventQueue eventQueue) { // If the kind doesn't match, it has to be a remove/add. if (oldNamespaceOrType.Kind() != newNamespaceOrType.Kind()) { EnqueueRemoveEvent(oldNamespaceOrType, newNodeParent, eventQueue); EnqueueAddEvent(newNamespaceOrType, newNodeParent, eventQueue); return false; } if (oldNamespaceOrType is BaseTypeDeclarationSyntax or DelegateDeclarationSyntax) { return CompareTypeDeclarations(oldNamespaceOrType, newNamespaceOrType, newNodeParent, eventQueue); } else if (oldNamespaceOrType is BaseNamespaceDeclarationSyntax namespaceDecl) { return CompareNamespaceDeclarations(namespaceDecl, (BaseNamespaceDeclarationSyntax)newNamespaceOrType, newNodeParent, eventQueue); } return false; } private bool CompareBaseLists(BaseTypeDeclarationSyntax oldType, BaseTypeDeclarationSyntax newType) { if (oldType.BaseList == null && newType.BaseList == null) { return true; } if (oldType.BaseList != null && newType.BaseList != null) { var oldTypes = oldType.BaseList.Types; var newTypes = newType.BaseList.Types; if (oldTypes.Count != newTypes.Count) { return false; } for (var i = 0; i < oldTypes.Count; i++) { if (!CompareTypes(oldTypes[i].Type, newTypes[i].Type)) { return false; } } return true; } // In this case, one of the base lists is null. return false; } private static bool CompareModifiers(MemberDeclarationSyntax oldMember, MemberDeclarationSyntax newMember) => oldMember.GetModifierFlags() == newMember.GetModifierFlags(); private static bool CompareModifiers(ParameterSyntax oldParameter, ParameterSyntax newParameter) => oldParameter.GetParameterFlags() == newParameter.GetParameterFlags(); private bool CompareNames(NameSyntax oldName, NameSyntax newName) { if (oldName.Kind() != newName.Kind()) { return false; } switch (oldName.Kind()) { case SyntaxKind.IdentifierName: var oldIdentifierName = (IdentifierNameSyntax)oldName; var newIdentifierName = (IdentifierNameSyntax)newName; return StringComparer.Ordinal.Equals(oldIdentifierName.Identifier.ToString(), newIdentifierName.Identifier.ToString()); case SyntaxKind.QualifiedName: var oldQualifiedName = (QualifiedNameSyntax)oldName; var newQualifiedName = (QualifiedNameSyntax)newName; return CompareNames(oldQualifiedName.Left, newQualifiedName.Left) && CompareNames(oldQualifiedName.Right, oldQualifiedName.Right); case SyntaxKind.GenericName: var oldGenericName = (GenericNameSyntax)oldName; var newGenericName = (GenericNameSyntax)newName; if (!StringComparer.Ordinal.Equals(oldGenericName.Identifier.ToString(), newGenericName.Identifier.ToString())) { return false; } if (oldGenericName.Arity != newGenericName.Arity) { return false; } for (var i = 0; i < oldGenericName.Arity; i++) { if (!CompareTypes(oldGenericName.TypeArgumentList.Arguments[i], newGenericName.TypeArgumentList.Arguments[i])) { return false; } } return true; case SyntaxKind.AliasQualifiedName: var oldAliasQualifiedName = (AliasQualifiedNameSyntax)oldName; var newAliasQualifiedName = (AliasQualifiedNameSyntax)newName; return CompareNames(oldAliasQualifiedName.Alias, newAliasQualifiedName.Alias) && CompareNames(oldAliasQualifiedName.Name, newAliasQualifiedName.Name); } Debug.Fail("Unknown kind: " + oldName.Kind()); return false; } private bool CompareTypes(TypeSyntax oldType, TypeSyntax newType) { // Type nodes can be NULL for ctor/dtor/operators ... if (oldType == null || newType == null) { return oldType == newType; } if (oldType.Kind() != newType.Kind()) { return false; } switch (oldType.Kind()) { case SyntaxKind.PredefinedType: var oldPredefinedType = (PredefinedTypeSyntax)oldType; var newPredefinedType = (PredefinedTypeSyntax)newType; return oldPredefinedType.Keyword.RawKind == newPredefinedType.Keyword.RawKind; case SyntaxKind.ArrayType: var oldArrayType = (ArrayTypeSyntax)oldType; var newArrayType = (ArrayTypeSyntax)newType; return oldArrayType.RankSpecifiers.Count == newArrayType.RankSpecifiers.Count && CompareTypes(oldArrayType.ElementType, newArrayType.ElementType); case SyntaxKind.PointerType: var oldPointerType = (PointerTypeSyntax)oldType; var newPointerType = (PointerTypeSyntax)newType; return CompareTypes(oldPointerType.ElementType, newPointerType.ElementType); case SyntaxKind.NullableType: var oldNullableType = (NullableTypeSyntax)oldType; var newNullableType = (NullableTypeSyntax)newType; return CompareTypes(oldNullableType.ElementType, newNullableType.ElementType); case SyntaxKind.IdentifierName: case SyntaxKind.QualifiedName: case SyntaxKind.AliasQualifiedName: case SyntaxKind.GenericName: var oldName = (NameSyntax)oldType; var newName = (NameSyntax)newType; return CompareNames(oldName, newName); } Debug.Fail("Unknown kind: " + oldType.Kind()); return false; } private static TypeSyntax GetReturnType(BaseMethodDeclarationSyntax method) { if (method is MethodDeclarationSyntax methodDecl) { return methodDecl.ReturnType; } else if (method is OperatorDeclarationSyntax operatorDecl) { return operatorDecl.ReturnType; } // TODO(DustinCa): What about conversion operators? How does the legacy code base handle those? return null; } protected override void CollectCore(SyntaxNode oldRoot, SyntaxNode newRoot, CodeModelEventQueue eventQueue) => CompareCompilationUnits((CompilationUnitSyntax)oldRoot, (CompilationUnitSyntax)newRoot, eventQueue); protected override void EnqueueAddEvent(SyntaxNode node, SyntaxNode parent, CodeModelEventQueue eventQueue) { if (eventQueue == null) { return; } if (node is IncompleteMemberSyntax) { return; } if (node is BaseFieldDeclarationSyntax baseField) { foreach (var variableDeclarator in baseField.Declaration.Variables) { eventQueue.EnqueueAddEvent(variableDeclarator, parent); } } else if (node is AttributeListSyntax attributeList) { foreach (var attribute in attributeList.Attributes) { AddEventToEventQueueForAttributes(attribute, parent, eventQueue.EnqueueAddEvent); } } else if (node is AttributeSyntax attribute) { AddEventToEventQueueForAttributes(attribute, parent, eventQueue.EnqueueAddEvent); } else { eventQueue.EnqueueAddEvent(node, parent); } } protected override void EnqueueChangeEvent(SyntaxNode node, SyntaxNode parent, CodeModelEventType eventType, CodeModelEventQueue eventQueue) { if (eventQueue == null) { return; } if (node is IncompleteMemberSyntax) { return; } if (node is BaseFieldDeclarationSyntax baseField) { foreach (var variableDeclarator in baseField.Declaration.Variables) { eventQueue.EnqueueChangeEvent(variableDeclarator, parent, eventType); } } else if (node is AttributeListSyntax attributeList) { foreach (var attribute in attributeList.Attributes) { ChangeEventQueueForAttributes(attribute, parent, eventType, eventQueue); } } else if (node is AttributeSyntax attribute) { ChangeEventQueueForAttributes(attribute, parent, eventType, eventQueue); } else { eventQueue.EnqueueChangeEvent(node, parent, eventType); } } private static void ChangeEventQueueForAttributes(AttributeSyntax attribute, SyntaxNode parent, CodeModelEventType eventType, CodeModelEventQueue eventQueue) { if (parent is BaseFieldDeclarationSyntax baseField) { foreach (var variableDeclarator in baseField.Declaration.Variables) { eventQueue.EnqueueChangeEvent(attribute, variableDeclarator, eventType); } } else { eventQueue.EnqueueChangeEvent(attribute, parent, eventType); } } protected override void EnqueueRemoveEvent(SyntaxNode node, SyntaxNode parent, CodeModelEventQueue eventQueue) { if (eventQueue == null) { return; } if (node is IncompleteMemberSyntax) { return; } if (node is BaseFieldDeclarationSyntax baseField) { foreach (var variableDeclarator in baseField.Declaration.Variables) { eventQueue.EnqueueRemoveEvent(variableDeclarator, parent); } } else if (node is AttributeListSyntax attributeList) { foreach (var attribute in attributeList.Attributes) { AddEventToEventQueueForAttributes(attribute, parent, eventQueue.EnqueueRemoveEvent); } } else if (node is AttributeSyntax attribute) { AddEventToEventQueueForAttributes(attribute, parent, eventQueue.EnqueueRemoveEvent); } else { eventQueue.EnqueueRemoveEvent(node, parent); } } private static void AddEventToEventQueueForAttributes(AttributeSyntax attribute, SyntaxNode parent, Action<SyntaxNode, SyntaxNode> enqueueAddOrRemoveEvent) { if (parent is BaseFieldDeclarationSyntax baseField) { foreach (var variableDeclarator in baseField.Declaration.Variables) { enqueueAddOrRemoveEvent(attribute, variableDeclarator); } } else { enqueueAddOrRemoveEvent(attribute, parent); } } } }