public static async Task <bool> IsValidNewMemberNameAsync(SemanticModel semanticModel, ISymbol symbol, string name, CancellationToken cancellationToken) { if (symbol.Kind == SymbolKind.NamedType) { TypeKind typeKind = ((INamedTypeSymbol)symbol).TypeKind; // If the symbol is a class or struct, the name can't be the same as any of its members. if (typeKind == TypeKind.Class || typeKind == TypeKind.Struct) { var members = ((INamedTypeSymbol)symbol).GetMembers(name); if (!members.IsDefaultOrEmpty) { return(false); } } } var containingSymbol = symbol.ContainingSymbol; var containingNamespaceOrTypeSymbol = containingSymbol as INamespaceOrTypeSymbol; if (containingNamespaceOrTypeSymbol != null) { if (containingNamespaceOrTypeSymbol.Kind == SymbolKind.Namespace) { // Make sure to use the compilation namespace so interfaces in referenced assemblies are considered containingNamespaceOrTypeSymbol = semanticModel.Compilation.GetCompilationNamespace((INamespaceSymbol)containingNamespaceOrTypeSymbol); } else if (containingNamespaceOrTypeSymbol.Kind == SymbolKind.NamedType) { TypeKind typeKind = ((INamedTypeSymbol)containingNamespaceOrTypeSymbol).TypeKind; // If the containing type is a class or struct, the name can't be the same as the name of the containing // type. if ((typeKind == TypeKind.Class || typeKind == TypeKind.Struct) && containingNamespaceOrTypeSymbol.Name == name) { return(false); } } // The name can't be the same as the name of an other member of the same type. At this point no special // consideration is given to overloaded methods. ImmutableArray <ISymbol> siblings = containingNamespaceOrTypeSymbol.GetMembers(name); if (!siblings.IsDefaultOrEmpty) { return(false); } return(true); } else if (containingSymbol.Kind == SymbolKind.Method) { IMethodSymbol methodSymbol = (IMethodSymbol)containingSymbol; if (methodSymbol.Parameters.Any(i => i.Name == name) || methodSymbol.TypeParameters.Any(i => i.Name == name)) { return(false); } IMethodSymbol outermostMethod = methodSymbol; while (outermostMethod.ContainingSymbol.Kind == SymbolKind.Method) { outermostMethod = (IMethodSymbol)outermostMethod.ContainingSymbol; if (outermostMethod.Parameters.Any(i => i.Name == name) || outermostMethod.TypeParameters.Any(i => i.Name == name)) { return(false); } } foreach (var syntaxReference in outermostMethod.DeclaringSyntaxReferences) { SyntaxNode syntaxNode = await syntaxReference.GetSyntaxAsync(cancellationToken).ConfigureAwait(false); LocalNameFinder localNameFinder = new LocalNameFinder(name); localNameFinder.Visit(syntaxNode); if (localNameFinder.Found) { return(false); } } return(true); } else { return(true); } }
public static async Task<bool> IsValidNewMemberNameAsync(SemanticModel semanticModel, ISymbol symbol, string name, CancellationToken cancellationToken) { if (symbol.Kind == SymbolKind.NamedType) { TypeKind typeKind = ((INamedTypeSymbol)symbol).TypeKind; // If the symbol is a class or struct, the name can't be the same as any of its members. if (typeKind == TypeKind.Class || typeKind == TypeKind.Struct) { var members = (symbol as INamedTypeSymbol)?.GetMembers(name); if (members.HasValue && !members.Value.IsDefaultOrEmpty) { return false; } } } var containingSymbol = symbol.ContainingSymbol; var containingNamespaceOrTypeSymbol = containingSymbol as INamespaceOrTypeSymbol; if (containingNamespaceOrTypeSymbol != null) { if (containingNamespaceOrTypeSymbol.Kind == SymbolKind.Namespace) { // Make sure to use the compilation namespace so interfaces in referenced assemblies are considered containingNamespaceOrTypeSymbol = semanticModel.Compilation.GetCompilationNamespace((INamespaceSymbol)containingNamespaceOrTypeSymbol); } else if (containingNamespaceOrTypeSymbol.Kind == SymbolKind.NamedType) { TypeKind typeKind = ((INamedTypeSymbol)containingNamespaceOrTypeSymbol).TypeKind; // If the containing type is a class or struct, the name can't be the same as the name of the containing // type. if ((typeKind == TypeKind.Class || typeKind == TypeKind.Struct) && containingNamespaceOrTypeSymbol.Name == name) { return false; } } // The name can't be the same as the name of an other member of the same type. At this point no special // consideration is given to overloaded methods. ImmutableArray<ISymbol> siblings = containingNamespaceOrTypeSymbol.GetMembers(name); if (!siblings.IsDefaultOrEmpty) { return false; } return true; } else if (containingSymbol.Kind == SymbolKind.Method) { IMethodSymbol methodSymbol = (IMethodSymbol)containingSymbol; if (methodSymbol.Parameters.Any(i => i.Name == name) || methodSymbol.TypeParameters.Any(i => i.Name == name)) { return false; } IMethodSymbol outermostMethod = methodSymbol; while (outermostMethod.ContainingSymbol.Kind == SymbolKind.Method) { outermostMethod = (IMethodSymbol)outermostMethod.ContainingSymbol; if (outermostMethod.Parameters.Any(i => i.Name == name) || outermostMethod.TypeParameters.Any(i => i.Name == name)) { return false; } } foreach (var syntaxReference in outermostMethod.DeclaringSyntaxReferences) { SyntaxNode syntaxNode = await syntaxReference.GetSyntaxAsync(cancellationToken).ConfigureAwait(false); LocalNameFinder localNameFinder = new LocalNameFinder(name); localNameFinder.Visit(syntaxNode); if (localNameFinder.Found) { return false; } } return true; } else { return true; } }