protected override bool TryInitializeState( Document document, SemanticModel model, SyntaxNode node, CancellationToken cancellationToken, out INamedTypeSymbol classType, out INamedTypeSymbol abstractClassType) { var baseClassNode = node as TypeSyntax; if (baseClassNode != null && baseClassNode.Parent is BaseTypeSyntax && baseClassNode.Parent.IsParentKind(SyntaxKind.BaseList) && ((BaseTypeSyntax)baseClassNode.Parent).Type == baseClassNode) { if (baseClassNode.Parent.Parent.IsParentKind(SyntaxKind.ClassDeclaration)) { abstractClassType = model.GetTypeInfo(baseClassNode, cancellationToken).Type as INamedTypeSymbol; cancellationToken.ThrowIfCancellationRequested(); if (abstractClassType.IsAbstractClass()) { var classDecl = baseClassNode.Parent.Parent.Parent as ClassDeclarationSyntax; classType = model.GetDeclaredSymbol(classDecl, cancellationToken) as INamedTypeSymbol; return classType != null && abstractClassType != null; } } } classType = null; abstractClassType = null; return false; }
public void AnalyzeCodeBlock(SyntaxNode codeBlock, ISymbol ownerSymbol, SemanticModel semanticModel, Action<Diagnostic> addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) { if (IsEmptyFinalizer(codeBlock, semanticModel)) { addDiagnostic(ownerSymbol.CreateDiagnostic(Rule)); } }
private IEnumerable<SignatureHelpParameter> GetDelegateTypeParameters(IMethodSymbol invokeMethod, SemanticModel semanticModel, int position, CancellationToken cancellationToken) { const string TargetName = "target"; var parts = new List<SymbolDisplayPart>(); parts.AddRange(invokeMethod.ReturnType.ToMinimalDisplayParts(semanticModel, position)); parts.Add(Space()); parts.Add(Punctuation(SyntaxKind.OpenParenToken)); var first = true; foreach (var parameter in invokeMethod.Parameters) { if (!first) { parts.Add(Punctuation(SyntaxKind.CommaToken)); parts.Add(Space()); } first = false; parts.AddRange(parameter.Type.ToMinimalDisplayParts(semanticModel, position)); } parts.Add(Punctuation(SyntaxKind.CloseParenToken)); parts.Add(Space()); parts.Add(new SymbolDisplayPart(SymbolDisplayPartKind.ParameterName, null, TargetName)); yield return new SignatureHelpParameter( TargetName, isOptional: false, documentationFactory: null, displayParts: parts); }
public Walker(SemanticModel semanticModel, SemanticMap map, CancellationToken cancellationToken) : base(SyntaxWalkerDepth.Token) { _semanticModel = semanticModel; _map = map; _cancellationToken = cancellationToken; }
private IEnumerable<SignatureHelpItem> GetDelegateInvokeItems( InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, ISymbolDisplayService symbolDisplayService, IAnonymousTypeDisplayService anonymousTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService, ISymbol within, INamedTypeSymbol delegateType, CancellationToken cancellationToken) { var invokeMethod = delegateType.DelegateInvokeMethod; if (invokeMethod == null) { return null; } // Events can only be invoked directly from the class they were declared in. var expressionSymbol = semanticModel.GetSymbolInfo(invocationExpression.Expression, cancellationToken).GetAnySymbol(); if (expressionSymbol.IsKind(SymbolKind.Event) && !expressionSymbol.ContainingType.OriginalDefinition.Equals(within.OriginalDefinition)) { return null; } var position = invocationExpression.SpanStart; var item = CreateItem( invokeMethod, semanticModel, position, symbolDisplayService, anonymousTypeDisplayService, isVariadic: invokeMethod.IsParams(), documentation: SpecializedCollections.EmptyEnumerable<SymbolDisplayPart>(), prefixParts: GetDelegateInvokePreambleParts(invokeMethod, semanticModel, position), separatorParts: GetSeparatorParts(), suffixParts: GetDelegateInvokePostambleParts(), parameters: GetDelegateInvokeParameters(invokeMethod, semanticModel, position, documentationCommentFormattingService, cancellationToken)); return SpecializedCollections.SingletonEnumerable(item); }
public bool IsExpressionContext(SemanticModel semanticModel, int position, CancellationToken cancellationToken) { return semanticModel.SyntaxTree.IsExpressionContext( position, semanticModel.SyntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken), attributes: true, cancellationToken: cancellationToken, semanticModelOpt: semanticModel); }
private IEnumerable<SignatureHelpItem> GetDelegateTypeConstructors( ObjectCreationExpressionSyntax objectCreationExpression, SemanticModel semanticModel, ISymbolDisplayService symbolDisplayService, IAnonymousTypeDisplayService anonymousTypeDisplayService, INamedTypeSymbol delegateType, INamedTypeSymbol containingType, CancellationToken cancellationToken) { var invokeMethod = delegateType.DelegateInvokeMethod; if (invokeMethod == null) { return null; } var position = objectCreationExpression.SpanStart; var item = CreateItem( invokeMethod, semanticModel, position, symbolDisplayService, anonymousTypeDisplayService, isVariadic: false, documentationFactory: null, prefixParts: GetDelegateTypePreambleParts(invokeMethod, semanticModel, position), separatorParts: GetSeparatorParts(), suffixParts: GetDelegateTypePostambleParts(invokeMethod), parameters: GetDelegateTypeParameters(invokeMethod, semanticModel, position, cancellationToken)); return SpecializedCollections.SingletonEnumerable(item); }
public ICodeBlockEndedAnalyzer OnCodeBlockStarted(SyntaxNode codeBlock, ISymbol ownerSymbol, SemanticModel semanticModel, Action<Diagnostic> addDiagnostic, CancellationToken cancellationToken) { var methodSymbol = ownerSymbol as IMethodSymbol; if (methodSymbol == null || methodSymbol.ReturnsVoid || methodSymbol.ReturnType.Kind == SymbolKind.ArrayType || methodSymbol.Parameters.Length > 0 || !(methodSymbol.DeclaredAccessibility == Accessibility.Public || methodSymbol.DeclaredAccessibility == Accessibility.Protected) || methodSymbol.IsAccessorMethod() || !IsPropertyLikeName(methodSymbol.Name)) { return null; } // Fxcop has a few additional checks to reduce the noise for this diagnostic: // Ensure that the method is non-generic, non-virtual/override, has no overloads and doesn't have special names: 'GetHashCode' or 'GetEnumerator'. // Also avoid generating this diagnostic if the method body has any invocation expressions. if (methodSymbol.IsGenericMethod || methodSymbol.IsVirtual || methodSymbol.IsOverride || methodSymbol.ContainingType.GetMembers(methodSymbol.Name).Length > 1 || methodSymbol.Name == GetHashCodeName || methodSymbol.Name == GetEnumeratorName) { return null; } return GetCodeBlockEndedAnalyzer(); }
public static bool AreSemanticallyEquivalent( SemanticModel semanticModel1, SemanticModel semanticModel2, SyntaxNode node1, SyntaxNode node2, Func<SyntaxNode, bool> predicate = null) { // First check for syntactic equivalency. If two nodes aren't structurally equivalent, // then they're not semantically equivalent. if (node1 == null && node2 == null) { return true; } if (node1 == null || node2 == null) { return false; } if (!node1.IsEquivalentTo(node2, topLevel: false)) { return false; } // From this point on we can assume the tree structure is the same. So no need to check // kinds, child counts or token contents. return AreSemanticallyEquivalentWorker( semanticModel1, semanticModel2, node1, node2, predicate); }
/// <summary> /// Analyzes if type information is obvious to the reader by simply looking at the assignment expression. /// </summary> /// <remarks> /// <paramref name="typeInDeclaration"/> accepts null, to be able to cater to codegen features /// that are about to generate a local declaration and do not have this information to pass in. /// Things (like analyzers) that do have a local declaration already, should pass this in. /// </remarks> public static bool IsTypeApparentInAssignmentExpression( TypeStylePreference stylePreferences, ExpressionSyntax initializerExpression, SemanticModel semanticModel, CancellationToken cancellationToken, ITypeSymbol typeInDeclaration = null) { // default(type) if (initializerExpression.IsKind(SyntaxKind.DefaultExpression)) { return true; } // literals, use var if options allow usage here. if (initializerExpression.IsAnyLiteralExpression()) { return stylePreferences.HasFlag(TypeStylePreference.ImplicitTypeForIntrinsicTypes); } // constructor invocations cases: // = new type(); if (initializerExpression.IsKind(SyntaxKind.ObjectCreationExpression) && !initializerExpression.IsKind(SyntaxKind.AnonymousObjectCreationExpression)) { return true; } // explicit conversion cases: // (type)expr, expr is type, expr as type if (initializerExpression.IsKind(SyntaxKind.CastExpression) || initializerExpression.IsKind(SyntaxKind.IsExpression) || initializerExpression.IsKind(SyntaxKind.AsExpression)) { return true; } // other Conversion cases: // a. conversion with helpers like: int.Parse methods // b. types that implement IConvertible and then invoking .ToType() // c. System.Convert.Totype() var memberName = GetRightmostInvocationExpression(initializerExpression).GetRightmostName(); if (memberName == null) { return false; } var methodSymbol = semanticModel.GetSymbolInfo(memberName, cancellationToken).Symbol as IMethodSymbol; if (methodSymbol == null) { return false; } if (memberName.IsRightSideOfDot()) { var containingTypeName = memberName.GetLeftSideOfDot(); return IsPossibleCreationOrConversionMethod(methodSymbol, typeInDeclaration, semanticModel, containingTypeName, cancellationToken); } return false; }
/// <summary> /// Determines whether the specified TypeSyntax is actually 'var'. /// </summary> public static bool IsTypeInferred(this TypeSyntax typeSyntax, SemanticModel semanticModel) { if (!typeSyntax.IsVar) { return false; } if (semanticModel.GetAliasInfo(typeSyntax) != null) { return false; } var type = semanticModel.GetTypeInfo(typeSyntax).Type; if (type == null) { return false; } if (type.Name == "var") { return false; } return true; }
public static IAliasSymbol GetAliasInfo( ISemanticFactsService semanticFacts, SemanticModel model, SyntaxToken token, CancellationToken cancellationToken) { if (semanticFacts == null) { return model.GetAliasInfo(token.Parent, cancellationToken); } var entry = GetCachedEntry(model); if (entry == null) { return model.GetAliasInfo(token.Parent, cancellationToken); } if (entry.AliasNameSet == null) { var set = semanticFacts.GetAliasNameSet(model, cancellationToken); Interlocked.CompareExchange(ref entry.AliasNameSet, set, null); } if (entry.AliasNameSet.Contains(token.ValueText)) { return model.GetAliasInfo(token.Parent, cancellationToken); } return null; }
internal TypeInferrer( SemanticModel semanticModel, CancellationToken cancellationToken) { this.semanticModel = semanticModel; this.cancellationToken = cancellationToken; }
internal override Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, CancellationToken cancellationToken) { var actions = ImmutableArray.CreateBuilder<CodeAction>(); // Fix 1: Add a NonSerialized attribute to the field var fieldNode = GetFieldDeclarationNode(nodeToFix); if (fieldNode != null) { var generator = SyntaxGenerator.GetGenerator(document); var codeAction = new MyDocumentCodeAction(FxCopFixersResources.AddNonSerializedAttribute, async ct => await AddNonSerializedAttribute(document, model, root, fieldNode, generator).ConfigureAwait(false)); actions.Add(codeAction); // Fix 2: If the type of the field is defined in source, then add the serializable attribute to the type. var fieldSymbol = model.GetDeclaredSymbol(nodeToFix, cancellationToken) as IFieldSymbol; var type = fieldSymbol.Type; if (type.Locations.Any(l => l.IsInSource)) { var typeCodeAction = new MySolutionCodeAction(FxCopFixersResources.AddSerializableAttribute, async ct => await AddSerializableAttributeToType(document, model, generator, type, cancellationToken).ConfigureAwait(false)); actions.Add(typeCodeAction); } } return Task.FromResult<IEnumerable<CodeAction>>(actions.ToImmutable()); }
private Task<Document> AddNonSerializedAttribute(Document document, SemanticModel model, SyntaxNode root, SyntaxNode fieldNode, SyntaxGenerator generator) { var attr = generator.Attribute(generator.TypeExpression(WellKnownTypes.NonSerializedAttribute(model.Compilation))); var newNode = generator.AddAttributes(fieldNode, attr); var newDocument = document.WithSyntaxRoot(root.ReplaceNode(fieldNode, newNode)); return Task.FromResult(newDocument); }
private bool TypeHasWeakIdentity(ITypeSymbol type, SemanticModel model) { switch (type.TypeKind) { case TypeKind.ArrayType: var arrayType = type as IArrayTypeSymbol; return arrayType != null && arrayType.ElementType.IsPrimitiveType(); case TypeKind.Class: case TypeKind.TypeParameter: Compilation compilation = model.Compilation; INamedTypeSymbol marshalByRefObjectTypeSymbol = compilation.GetTypeByMetadataName("System.MarshalByRefObject"); INamedTypeSymbol executionEngineExceptionTypeSymbol = compilation.GetTypeByMetadataName("System.ExecutionEngineException"); INamedTypeSymbol outOfMemoryExceptionTypeSymbol = compilation.GetTypeByMetadataName("System.OutOfMemoryException"); INamedTypeSymbol stackOverflowExceptionTypeSymbol = compilation.GetTypeByMetadataName("System.StackOverflowException"); INamedTypeSymbol memberInfoTypeSymbol = compilation.GetTypeByMetadataName("System.Reflection.MemberInfo"); INamedTypeSymbol parameterInfoTypeSymbol = compilation.GetTypeByMetadataName("System.Reflection.ParameterInfo"); INamedTypeSymbol threadTypeSymbol = compilation.GetTypeByMetadataName("System.Threading.Thread"); return type.SpecialType == SpecialType.System_String || type.Equals(executionEngineExceptionTypeSymbol) || type.Equals(outOfMemoryExceptionTypeSymbol) || type.Equals(stackOverflowExceptionTypeSymbol) || type.Inherits(marshalByRefObjectTypeSymbol) || type.Inherits(memberInfoTypeSymbol) || type.Inherits(parameterInfoTypeSymbol) || type.Inherits(threadTypeSymbol); // What about struct types? default: return false; } }
private bool TryClassifySymbol( NameSyntax name, SymbolInfo symbolInfo, SemanticModel semanticModel, CancellationToken cancellationToken, out IEnumerable<ClassifiedSpan> result) { if (symbolInfo.CandidateReason == CandidateReason.Ambiguous) { return TryClassifyAmbiguousSymbol(name, symbolInfo, semanticModel, cancellationToken, out result); } // Only classify if we get one good symbol back, or if it bound to a constructor symbol with // overload resolution/accessibility errors, or bound to type/constructor and type wasn't creatable. var symbol = TryGetSymbol(name, symbolInfo, semanticModel); ClassifiedSpan classifiedSpan; if (TryClassifySymbol(name, symbol, semanticModel, cancellationToken, out classifiedSpan)) { result = SpecializedCollections.SingletonEnumerable(classifiedSpan); return true; } result = null; return false; }
/// <summary> /// Returns true if type information could be gleaned by simply looking at the given statement. /// This typically means that the type name occurs in right hand side of an assignment. /// </summary> private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDeclaration, SemanticModel semanticModel, TypeStylePreference stylePreferences, CancellationToken cancellationToken) { var initializer = variableDeclaration.Variables.Single().Initializer; var initializerExpression = GetInitializerExpression(initializer); var declaredTypeSymbol = semanticModel.GetTypeInfo(variableDeclaration.Type, cancellationToken).Type; return TypeStyleHelper.IsTypeApparentInAssignmentExpression(stylePreferences, initializerExpression, semanticModel,cancellationToken, declaredTypeSymbol); }
private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel) { position = CheckAndAdjustPosition(position); var methodSymbol = (MethodSymbol)this.MemberSymbol; // Strip off ExecutableCodeBinder (see ctor). Binder binder = this.RootBinder; do { if (binder is ExecutableCodeBinder) { binder = binder.Next; break; } binder = binder.Next; } while (binder != null); Debug.Assert(binder != null); var executablebinder = new ExecutableCodeBinder(body, methodSymbol, binder ?? this.RootBinder); var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags()); speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, position); return true; }
internal SyntaxNode CreateOrdinalMemberAccess(SyntaxGenerator syntaxFactoryService, SemanticModel model) { var stringComparisonType = WellKnownTypes.StringComparison(model.Compilation); return syntaxFactoryService.MemberAccessExpression( syntaxFactoryService.TypeExpression(stringComparisonType), syntaxFactoryService.IdentifierName(CA1309DiagnosticAnalyzer.OrdinalText)); }
public static void AddAliasSymbols(SemanticModel semanticModel, int namespaceId, IEnumerable<IAliasSymbol> aliasSymbols) { // given semantic model must be the original semantic model for now var treeMap = s_treeAliasMap.GetValue(semanticModel.Compilation, s_createTreeMap); // check again to see whether somebody has beaten us var key = (tree: semanticModel.SyntaxTree, namespaceId: namespaceId); if (treeMap.ContainsKey(key)) { return; } var builder = ImmutableDictionary.CreateBuilder<INamespaceOrTypeSymbol, IAliasSymbol>(); foreach (var alias in aliasSymbols) { if (builder.ContainsKey(alias.Target)) { continue; } // only put the first one. builder.Add(alias.Target, alias); } // Use namespace id rather than holding onto namespace node directly, that will keep the tree alive as long as // the compilation is alive. In the current design, a node can come and go even if compilation is alive through recoverable tree. treeMap.TryAdd(key, builder.ToImmutable()); }
internal static SemanticMap From(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken) { var map = new SemanticMap(); var walker = new Walker(semanticModel, map, cancellationToken); walker.Visit(node); return map; }
private bool CheckStatement(SemanticModel semanticModel, StatementSyntax statement, CancellationToken cancellationToken) { if (statement is CheckedStatementSyntax || statement is DoStatementSyntax || statement is EmptyStatementSyntax || statement is ExpressionStatementSyntax || statement is FixedStatementSyntax || statement is ForEachStatementSyntax || statement is ForStatementSyntax || statement is IfStatementSyntax || statement is LocalDeclarationStatementSyntax || statement is LockStatementSyntax || statement is ReturnStatementSyntax || statement is SwitchStatementSyntax || statement is ThrowStatementSyntax || statement is TryStatementSyntax || statement is UnsafeStatementSyntax || statement is UsingStatementSyntax || statement is WhileStatementSyntax) { return true; } return false; }
/// <summary> /// Checks if any property in the class given as parameter has a getter for the field we are moving. /// </summary> /// <param name="node">Syntax node of the class the field belongs to.</param> /// <param name="semanticModel">Semantic model for the code we are processing.</param> /// <returns></returns> private PropertyDeclarationSyntax getProperty(ClassDeclarationSyntax node, SemanticModel semanticModel) { foreach (var p in node.Members.Where(m => m.Kind == SyntaxKind.PropertyDeclaration)) { var property = p as PropertyDeclarationSyntax; var accessors = property.AccessorList.Accessors; var getter = accessors.FirstOrDefault(ad => ad.Kind == SyntaxKind.GetAccessorDeclaration); var statements = getter.BodyOpt.Statements; if (statements.Count != 0) { var returnStatement = statements.FirstOrDefault() as ReturnStatementSyntax; if (returnStatement != null && returnStatement.ExpressionOpt != null) { var semanticInfo = document.GetSemanticModel().GetSemanticInfo(returnStatement.ExpressionOpt); var fieldSymbol = semanticInfo.Symbol as FieldSymbol; if (fieldSymbol != null && fieldSymbol == semanticModel.GetDeclaredSymbol(field)) { return property; } } } } return null; }
public override IEnumerable<SymbolDisplayPart> GetAnonymousTypeParts( INamedTypeSymbol anonymousType, SemanticModel semanticModel, int position, ISymbolDisplayService displayService) { var members = new List<SymbolDisplayPart>(); members.Add(Keyword(SyntaxFacts.GetText(SyntaxKind.NewKeyword))); members.AddRange(Space()); members.Add(Punctuation(SyntaxFacts.GetText(SyntaxKind.OpenBraceToken))); members.AddRange(Space()); bool first = true; foreach (var property in anonymousType.GetValidAnonymousTypeProperties()) { if (!first) { members.Add(Punctuation(SyntaxFacts.GetText(SyntaxKind.CommaToken))); members.AddRange(Space()); } first = false; members.AddRange(displayService.ToMinimalDisplayParts(semanticModel, position, property.Type).Select(p => p.MassageErrorTypeNames("?"))); members.AddRange(Space()); members.Add(new SymbolDisplayPart(SymbolDisplayPartKind.PropertyName, property, property.Name)); } members.AddRange(Space()); members.Add(Punctuation(SyntaxFacts.GetText(SyntaxKind.CloseBraceToken))); return members; }
private static bool IsRequiredCastForReferenceEqualityComparison(ITypeSymbol outerType, CastExpressionSyntax castExpression, SemanticModel semanticModel, out ExpressionSyntax other) { if (outerType.SpecialType == SpecialType.System_Object) { var expression = castExpression.WalkUpParentheses(); var parentNode = expression.Parent; if (parentNode.IsKind(SyntaxKind.EqualsExpression) || parentNode.IsKind(SyntaxKind.NotEqualsExpression)) { // Reference comparison. var binaryExpression = (BinaryExpressionSyntax)parentNode; other = binaryExpression.Left == expression ? binaryExpression.Right : binaryExpression.Left; // Explicit cast not required if we are comparing with type parameter with a class constraint. var otherType = semanticModel.GetTypeInfo(other).Type; if (otherType != null && otherType.TypeKind != TypeKind.TypeParameter) { return !other.WalkDownParentheses().IsKind(SyntaxKind.CastExpression); } } } other = null; return false; }
internal override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, string diagnosticId, CancellationToken cancellationToken) { // if nothing can be fixed, return the unchanged node var newRoot = root; var kind = nodeToFix.CSharpKind(); var syntaxFactoryService = document.GetLanguageService<SyntaxGenerator>(); switch (kind) { case SyntaxKind.Argument: // StringComparison.CurrentCulture => StringComparison.Ordinal // StringComparison.CurrentCultureIgnoreCase => StringComparison.OrdinalIgnoreCase var argument = (ArgumentSyntax)nodeToFix; var memberAccess = argument.Expression as MemberAccessExpressionSyntax; if (memberAccess != null) { // preserve the "IgnoreCase" suffix if present bool isIgnoreCase = memberAccess.Name.GetText().ToString().EndsWith(CA1309DiagnosticAnalyzer.IgnoreCaseText); var newOrdinalText = isIgnoreCase ? CA1309DiagnosticAnalyzer.OrdinalIgnoreCaseText : CA1309DiagnosticAnalyzer.OrdinalText; var newIdentifier = syntaxFactoryService.IdentifierName(newOrdinalText); var newMemberAccess = memberAccess.WithName((SimpleNameSyntax)newIdentifier).WithAdditionalAnnotations(Formatter.Annotation); newRoot = root.ReplaceNode(memberAccess, newMemberAccess); } break; case SyntaxKind.IdentifierName: // string.Equals(a, b) => string.Equals(a, b, StringComparison.Ordinal) // string.Compare(a, b) => string.Compare(a, b, StringComparison.Ordinal) var identifier = (IdentifierNameSyntax)nodeToFix; var invokeParent = identifier.GetAncestor<InvocationExpressionSyntax>(); if (invokeParent != null) { var methodSymbol = model.GetSymbolInfo(identifier).Symbol as IMethodSymbol; if (methodSymbol != null && CanAddStringComparison(methodSymbol)) { // append a new StringComparison.Ordinal argument var newArg = syntaxFactoryService.Argument(CreateOrdinalMemberAccess(syntaxFactoryService, model)) .WithAdditionalAnnotations(Formatter.Annotation); var newInvoke = invokeParent.AddArgumentListArguments((ArgumentSyntax)newArg).WithAdditionalAnnotations(Formatter.Annotation); newRoot = root.ReplaceNode(invokeParent, newInvoke); } } break; case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: // "a == b" => "string.Equals(a, b, StringComparison.Ordinal)" // "a != b" => "!string.Equals(a, b, StringComparison.Ordinal)" var binaryExpression = (BinaryExpressionSyntax)nodeToFix; var invocation = CreateEqualsExpression(syntaxFactoryService, model, binaryExpression.Left, binaryExpression.Right, kind == SyntaxKind.EqualsExpression).WithAdditionalAnnotations(Formatter.Annotation); newRoot = root.ReplaceNode(nodeToFix, invocation); break; } if (newRoot == root) { return Task.FromResult(document); } return Task.FromResult(document.WithSyntaxRoot(newRoot)); }
protected static bool IsAcceptableOverload(IMethodSymbol methodSymbol, SemanticModel model) { var stringComparisonType = WellKnownTypes.StringComparison(model.Compilation); return methodSymbol.IsStatic ? IsAcceptableStaticOverload(methodSymbol, stringComparisonType) : IsAcceptableInstanceOverload(methodSymbol, stringComparisonType); }
private async Task<SyntaxNode> AddNamespaceImportsAsync( Document document, SemanticModel model, OptionSet options, IEnumerable<INamespaceSymbol> namespaces, CancellationToken cancellationToken) { var existingNamespaces = new HashSet<INamespaceSymbol>(); await this.GetExistingImportedNamespacesAsync(document, model, existingNamespaces, cancellationToken).ConfigureAwait(false); var namespacesToAdd = new HashSet<INamespaceSymbol>(namespaces); namespacesToAdd.RemoveAll(existingNamespaces); var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); if (namespacesToAdd.Count == 0) { return root; } var gen = SyntaxGenerator.GetGenerator(document); var newRoot = root; foreach (var import in namespacesToAdd.Select(ns => gen.NamespaceImportDeclaration(ns.ToDisplayString()).WithAdditionalAnnotations(Simplifier.Annotation))) { newRoot = this.InsertNamespaceImport(newRoot, gen, import, options); } return newRoot; }
public PostProcessor(SemanticModel semanticModel, int contextPosition) { Contract.ThrowIfNull(semanticModel); _semanticModel = semanticModel; _contextPosition = contextPosition; }
private static IEnumerable<ITypeSymbol> ExtractTypeSymbolsFromSyntaxNode(SyntaxNode node, SemanticModel model) { var parameter = node as ParameterSyntax; if (parameter?.Type != null) { yield return model.GetSymbolInfo(parameter.Type).Symbol as ITypeSymbol; } if (node is VariableDeclarationSyntax variableDeclaration) { yield return model.GetSymbolInfo(variableDeclaration.Type).Symbol as ITypeSymbol; } if (node is ObjectCreationExpressionSyntax objectCreation) { var objectCreationTypeInfo = model.GetTypeInfo(objectCreation); yield return objectCreationTypeInfo.Type; yield return objectCreationTypeInfo.ConvertedType; } if (node is IdentifierNameSyntax identifierName) { yield return model.GetSymbolInfo(identifierName).Symbol as ITypeSymbol; } }
private static async Task <Document> RemoveArgumentsAndAddNecessaryNamesAsync(Document document, ArgumentListSyntax argumentList, List <SyntaxNodeSymbolSemanticModelTuple <ArgumentSyntax, IParameterSymbol> > argumentMappings, List <ArgumentSyntax> argumentsToRemove, SemanticModel semanticModel, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newArgumentList = SyntaxFactory.ArgumentList(); var alreadyRemovedOne = false; foreach (var argumentMapping in argumentMappings .Where(argumentMapping => !argumentMapping.Symbol.IsParams)) { var argument = argumentMapping.SyntaxNode; if (argumentsToRemove.Contains(argument)) { alreadyRemovedOne = true; continue; } newArgumentList = AddArgument(newArgumentList, argumentMapping.Symbol.Name, argument, alreadyRemovedOne); } var paramsArguments = argumentMappings .Where(mapping => mapping.Symbol.IsParams) .ToList(); if (paramsArguments.Any()) { newArgumentList = AddParamsArguments(semanticModel, paramsArguments, newArgumentList); } var newRoot = root.ReplaceNode(argumentList, newArgumentList); return(document.WithSyntaxRoot(newRoot)); }
protected abstract void AnalyzeNode(SymbolAnalysisContext symbolContext, TSyntaxNodeOfInterest syntaxNode, SemanticModel semanticModel);
private static async Task <Document> Fix(CodeFixContext context, SyntaxNode root, SyntaxGenerator generator, SemanticModel semanticModel, CancellationToken cancellationToken) { SyntaxNode node = root.FindNode(context.Span); Diagnostic diagnostic = context.Diagnostics.First(); switch (diagnostic.Properties[OperatorOverloadsHaveNamedAlternatesAnalyzer.DiagnosticKindText]) { case OperatorOverloadsHaveNamedAlternatesAnalyzer.AddAlternateText: SyntaxNode methodDeclaration = generator.GetDeclaration(node, DeclarationKind.Operator) ?? generator.GetDeclaration(node, DeclarationKind.ConversionOperator); var operatorOverloadSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken); INamedTypeSymbol typeSymbol = operatorOverloadSymbol.ContainingType; // For C# the following `typeDeclarationSyntax` and `typeDeclaration` nodes are identical, but for VB they're different so in // an effort to keep this as language-agnostic as possible, the heavy-handed approach is used. SyntaxNode typeDeclarationSyntax = typeSymbol.DeclaringSyntaxReferences.First().GetSyntax(cancellationToken); SyntaxNode typeDeclaration = generator.GetDeclaration(typeDeclarationSyntax, typeSymbol.TypeKind == TypeKind.Struct ? DeclarationKind.Struct : DeclarationKind.Class); SyntaxNode addedMember; IEnumerable <SyntaxNode> bodyStatements = generator.DefaultMethodBody(semanticModel.Compilation); if (OperatorOverloadsHaveNamedAlternatesAnalyzer.IsPropertyExpected(operatorOverloadSymbol.Name)) { // add a property addedMember = generator.PropertyDeclaration( name: OperatorOverloadsHaveNamedAlternatesAnalyzer.IsTrueText, type: generator.TypeExpression(SpecialType.System_Boolean), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.ReadOnly, getAccessorStatements: bodyStatements); } else { // add a method ExpectedMethodSignature expectedSignature = GetExpectedMethodSignature(operatorOverloadSymbol, semanticModel.Compilation); if (expectedSignature.Name == "CompareTo" && operatorOverloadSymbol.ContainingType.TypeKind == TypeKind.Class) { var nullCheck = generator.IfStatement( generator.InvocationExpression( generator.IdentifierName("ReferenceEquals"), generator.IdentifierName(expectedSignature.Parameters.First().name), generator.NullLiteralExpression()), new[] { generator.ReturnStatement(generator.LiteralExpression(1)) }); bodyStatements = new[] { nullCheck }.Concat(bodyStatements); } addedMember = generator.MethodDeclaration( name: expectedSignature.Name, parameters: expectedSignature.Parameters.Select(p => generator.ParameterDeclaration(p.name, generator.TypeExpression(p.typeSymbol))), returnType: generator.TypeExpression(expectedSignature.ReturnType), accessibility: Accessibility.Public, modifiers: expectedSignature.IsStatic ? DeclarationModifiers.Static : DeclarationModifiers.None, statements: bodyStatements); } SyntaxNode newTypeDeclaration = generator.AddMembers(typeDeclaration, addedMember); return(context.Document.WithSyntaxRoot(root.ReplaceNode(typeDeclaration, newTypeDeclaration))); case OperatorOverloadsHaveNamedAlternatesAnalyzer.FixVisibilityText: SyntaxNode badVisibilityNode = generator.GetDeclaration(node, DeclarationKind.Method) ?? generator.GetDeclaration(node, DeclarationKind.Property); ISymbol badVisibilitySymbol = semanticModel.GetDeclaredSymbol(badVisibilityNode, cancellationToken); SymbolEditor symbolEditor = SymbolEditor.Create(context.Document); ISymbol newSymbol = await symbolEditor.EditOneDeclarationAsync(badVisibilitySymbol, (documentEditor, syntaxNode) => documentEditor.SetAccessibility(badVisibilityNode, Accessibility.Public), cancellationToken).ConfigureAwait(false); Document newDocument = symbolEditor.GetChangedDocuments().Single(); SyntaxNode newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); return(context.Document.WithSyntaxRoot(newRoot)); default: return(context.Document); } }
internal abstract CSharpSyntaxRewriter CreateSyntaxRewriter(Compilation compilation, SemanticModel semanticModel);
private static ITypeParameterSymbol GetGenericParameterSymbol(ISyntaxFactsService syntaxFacts, SemanticModel semanticModel, SyntaxNode node1, SyntaxNode node2, CancellationToken cancellationToken) { var valueNode = syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(node1)) ? node2 : node1; var argumentExpression = syntaxFacts.GetExpressionOfArgument(valueNode); if (argumentExpression != null) { var parameterType = semanticModel.GetTypeInfo(argumentExpression, cancellationToken).Type; return(parameterType as ITypeParameterSymbol); } return(default);
/// <summary> /// Initializes a new instance of the <see cref="DefaultExpression"/> class. /// </summary> /// <param name="syntaxNode"></param> /// <param name="semanticModel"></param> public DefaultExpression(CSharpSyntaxNode syntaxNode, SemanticModel semanticModel) : base(syntaxNode, semanticModel) { }
private static IEnumerable<ITypeSymbol> CollectCoupledClasses(FieldDeclarationSyntax field, SemanticModel model) { return field.Declaration.Variables .SelectMany(variable => ExtractTypesFromVariableDeclarator(variable, model)); }
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel) { throw ExceptionUtilities.Unreachable; }
private static IEnumerable<ITypeSymbol> CollectCoupledClasses(BaseMethodDeclarationSyntax method, SemanticModel model) { return method.DescendantNodes() .SelectMany(node => ExtractTypeSymbolsFromSyntaxNode(node, model)); }
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel) { throw ExceptionUtilities.Unreachable; }
internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel) { throw ExceptionUtilities.Unreachable; }
private static MethodArgumentDescriptor[] GetArgumentDescriptors(List <ParameterSyntax> argumentList, SemanticModel semanticModel, MockFramework mockFramework) { MethodArgumentDescriptor[] argumentDescriptors = new MethodArgumentDescriptor[argumentList.Count()]; for (int i = 0; i < argumentDescriptors.Count(); i++) { string argumentName = argumentList[i].Identifier.Text; ParameterModifier modifier = GetArgumentModifier(argumentList[i]); var namedTypeSymbol = InjectableType.TryCreateInjectableTypeFromParameterNode(argumentList[i], semanticModel, mockFramework); if (namedTypeSymbol != null) { argumentDescriptors[i] = new MethodArgumentDescriptor(namedTypeSymbol, argumentName, modifier); continue; } var argumentType = argumentList[i].Type; string typeName = argumentType.ToString(); argumentDescriptors[i] = new MethodArgumentDescriptor(new TypeDescriptor(typeName, null), argumentName, modifier); } return(argumentDescriptors); }
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel) { throw ExceptionUtilities.Unreachable; }
public RDomReturnStatement(SyntaxNode rawItem, IDom parent, SemanticModel model) : base(rawItem, parent, model) { }
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel) { throw ExceptionUtilities.Unreachable; }
public InvocationVisitor(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ProgramState programState) { this.invocation = invocation; this.semanticModel = semanticModel; this.programState = programState; }
private async Task <TestGenerationContext> CollectTestGenerationContextAsync( ProjectItemSummary selectedFile, string targetProjectNamespace, TestFramework testFramework, MockFramework mockFramework) { Microsoft.CodeAnalysis.Solution solution = CreateUnitTestBoilerplateCommandPackage.VisualStudioWorkspace.CurrentSolution; DocumentId documentId = solution.GetDocumentIdsWithFilePath(selectedFile.FilePath).FirstOrDefault(); if (documentId == null) { throw new InvalidOperationException("Could not find document in solution with file path " + selectedFile.FilePath); } var document = solution.GetDocument(documentId); SyntaxNode root = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); SyntaxNode firstClassDeclaration = root.DescendantNodes().FirstOrDefault(node => node.Kind() == SyntaxKind.ClassDeclaration); if (firstClassDeclaration == null) { throw new InvalidOperationException("Could not find class declaration."); } if (firstClassDeclaration.ChildTokens().Any(node => node.Kind() == SyntaxKind.AbstractKeyword)) { throw new InvalidOperationException("Cannot unit test an abstract class."); } SyntaxToken classIdentifierToken = firstClassDeclaration.ChildTokens().FirstOrDefault(n => n.Kind() == SyntaxKind.IdentifierToken); if (classIdentifierToken == default(SyntaxToken)) { throw new InvalidOperationException("Could not find class identifier."); } NamespaceDeclarationSyntax namespaceDeclarationSyntax = null; if (!TypeUtilities.TryGetParentSyntax(firstClassDeclaration, out namespaceDeclarationSyntax)) { throw new InvalidOperationException("Could not find class namespace."); } // Find property injection types var injectableProperties = new List <InjectableProperty>(); string classFullName = namespaceDeclarationSyntax.Name + "." + classIdentifierToken; INamedTypeSymbol classType = semanticModel.Compilation.GetTypeByMetadataName(classFullName); foreach (ISymbol member in classType.GetBaseTypesAndThis().SelectMany(n => n.GetMembers())) { if (member.Kind == SymbolKind.Property) { IPropertySymbol property = (IPropertySymbol)member; foreach (AttributeData attribute in property.GetAttributes()) { if (PropertyInjectionAttributeNames.Contains(attribute.AttributeClass.ToString())) { var injectableProperty = InjectableProperty.TryCreateInjectableProperty(property.Name, property.Type.ToString(), mockFramework); if (injectableProperty != null) { injectableProperties.Add(injectableProperty); } } } } } string className = classIdentifierToken.ToString(); // Find constructor injection types List <InjectableType> constructorInjectionTypes = new List <InjectableType>(); SyntaxNode constructorDeclaration = firstClassDeclaration.ChildNodes().FirstOrDefault(n => n.Kind() == SyntaxKind.ConstructorDeclaration); if (constructorDeclaration != null) { constructorInjectionTypes.AddRange( GetParameterListNodes(constructorDeclaration) .Select(node => InjectableType.TryCreateInjectableTypeFromParameterNode(node, semanticModel, mockFramework))); } // Find public method declarations IList <MethodDescriptor> methodDeclarations = new List <MethodDescriptor>(); foreach (MethodDeclarationSyntax methodDeclaration in firstClassDeclaration.ChildNodes().Where( n => n.Kind() == SyntaxKind.MethodDeclaration && ((MethodDeclarationSyntax)n).Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword)))) { var parameterList = GetParameterListNodes(methodDeclaration).ToList(); var parameterTypes = GetArgumentDescriptors(parameterList, semanticModel, mockFramework); var isAsync = methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword)) || DoesReturnTask(methodDeclaration); var hasReturnType = !DoesReturnNonGenericTask(methodDeclaration) && !DoesReturnVoid(methodDeclaration); methodDeclarations.Add(new MethodDescriptor(methodDeclaration.Identifier.Text, parameterTypes, isAsync, hasReturnType)); } string unitTestNamespace; string relativePath = this.GetRelativePath(selectedFile); if (string.IsNullOrEmpty(relativePath)) { unitTestNamespace = targetProjectNamespace; } else { List <string> defaultNamespaceParts = targetProjectNamespace.Split('.').ToList(); List <string> unitTestNamespaceParts = new List <string>(defaultNamespaceParts); unitTestNamespaceParts.AddRange(relativePath.Split('\\')); unitTestNamespace = string.Join(".", unitTestNamespaceParts); } List <InjectableType> injectedTypes = new List <InjectableType>(injectableProperties); injectedTypes.AddRange(constructorInjectionTypes.Where(t => t != null)); GenerateMockNames(injectedTypes); return(new TestGenerationContext( mockFramework, testFramework, unitTestNamespace, className, namespaceDeclarationSyntax.Name.ToString(), injectableProperties, constructorInjectionTypes, injectedTypes, methodDeclarations)); }
private static SyntaxNode GenerateDescriptionArgument(SyntaxGenerator generator, SemanticModel semanticModel) { SyntaxNode attributeArgument; if (semanticModel.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisHostMefMefConstruction, out var mefConstructionType) && mefConstructionType.GetMembers("ImportingConstructorMessage").OfType <IFieldSymbol>().Any()) { attributeArgument = generator.MemberAccessExpression( generator.TypeExpressionForStaticMemberAccess(mefConstructionType), generator.IdentifierName("ImportingConstructorMessage")); } else { attributeArgument = generator.LiteralExpression("This exported object must be obtained through the MEF export provider."); } return(generator.AttributeArgument(attributeArgument)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ExpressionSyntax expression, predicate: f => f.IsKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression))) { return; } if (IsPartOfLeftSideOfAssignment()) { return; } if (expression .WalkUp(f => f.IsKind(SyntaxKind.InvocationExpression, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression, SyntaxKind.ParenthesizedExpression)) .IsParentKind(SyntaxKind.AwaitExpression)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (expression.IsInExpressionTree(semanticModel, context.CancellationToken)) { return; } SyntaxKind kind = expression.Kind(); if (kind == SyntaxKind.SimpleMemberAccessExpression) { expression = ((MemberAccessExpressionSyntax)expression).Expression; } else if (kind == SyntaxKind.ElementAccessExpression) { expression = ((ElementAccessExpressionSyntax)expression).Expression; } CodeAction codeAction = CodeAction.Create( "Use conditional access", cancellationToken => RefactorAsync(context.Document, expression, cancellationToken), GetEquivalenceKey(DiagnosticIdentifiers.AvoidNullReferenceException)); context.RegisterCodeFix(codeAction, context.Diagnostics); bool IsPartOfLeftSideOfAssignment() { for (SyntaxNode node = expression; node != null; node = node.Parent) { var assignmentExpression = node.Parent as AssignmentExpressionSyntax; if (assignmentExpression?.Left == node) { return(true); } } return(false); } }
private ImmutableArray <IFieldSymbol> GetReferencedDescriptorFields(SyntaxNode syntax, SemanticModel semanticModel) { ImmutableArray <IFieldSymbol> .Builder builder = ImmutableArray.CreateBuilder <IFieldSymbol>(); foreach (TIdentifierNameSyntax identifier in syntax.DescendantNodes().OfType <TIdentifierNameSyntax>()) { ISymbol symbol = semanticModel.GetSymbolInfo(identifier).Symbol; if (symbol != null && symbol.Kind == SymbolKind.Field) { var field = (IFieldSymbol)symbol; if (field.Type is INamedTypeSymbol fieldType && fieldType.GetBaseTypesAndThis().Contains(_diagnosticDescriptorType)) { builder.Add((IFieldSymbol)symbol); } } } return(builder.ToImmutable()); }
protected abstract void AddAllParameterNameHintLocations( SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, SyntaxNode node, ArrayBuilder <(int position, string?identifierArgument, IParameterSymbol?parameter, HintKind kind)> buffer,
public CppImplWalker(CSharpCompilation compilation, SemanticModel model, ConversionSettings settings) : base(compilation, model, settings) { }
protected override void AnalyzeNode(SymbolAnalysisContext symbolContext, TInvocationExpressionSyntax invocation, SemanticModel semanticModel) { ISymbol symbol = semanticModel.GetSymbolInfo(invocation, symbolContext.CancellationToken).Symbol; if (symbol == null || symbol.Kind != SymbolKind.Method || !symbol.Name.Equals(ReportDiagnosticName, StringComparison.OrdinalIgnoreCase) || !_contextTypes.Contains(symbol.ContainingType)) { return; } IEnumerable <SyntaxNode> arguments = GetArgumentExpressions(invocation); if (arguments.HasExactly(1)) { SyntaxNode argument = arguments.First(); ITypeSymbol type = semanticModel.GetTypeInfo(argument, symbolContext.CancellationToken).ConvertedType; if (type != null && type.Equals(_diagnosticType)) { ISymbol argSymbol = semanticModel.GetSymbolInfo(argument, symbolContext.CancellationToken).Symbol; if (argSymbol != null) { SyntaxNode diagnosticInitializerOpt = null; if (argSymbol is ILocalSymbol local) { SyntaxReference syntaxRef = local.DeclaringSyntaxReferences.FirstOrDefault(); if (syntaxRef != null) { diagnosticInitializerOpt = syntaxRef.GetSyntax(symbolContext.CancellationToken).FirstAncestorOrSelf <TVariableDeclaratorSyntax>(); } } else { if (argSymbol is IMethodSymbol method && method.ContainingType.Equals(_diagnosticType) && method.Name.Equals(nameof(Diagnostic.Create), StringComparison.OrdinalIgnoreCase)) { diagnosticInitializerOpt = argument; } } if (diagnosticInitializerOpt != null) { ImmutableArray <IFieldSymbol> descriptorFields = GetReferencedDescriptorFields(diagnosticInitializerOpt, semanticModel); if (descriptorFields.Length == 1 && !_supportedDescriptorFieldsMap[(INamedTypeSymbol)symbolContext.Symbol].Contains(descriptorFields[0])) { Diagnostic diagnostic = Diagnostic.Create(InvalidReportDiagnosticRule, invocation.GetLocation(), descriptorFields[0].Name); symbolContext.ReportDiagnostic(diagnostic); } } } } } }
private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxNode node, BlockSyntax body) { if (body == null) { return; } if (body.ContainsDiagnostics) { return; } SyntaxList <StatementSyntax> statements = body.Statements; if (statements.Count != 2) { return; } if (!(statements[0] is IfStatementSyntax ifStatement)) { return; } if (!(statements[1] is ReturnStatementSyntax returnStatement)) { return; } ExpressionSyntax returnExpression = returnStatement.Expression; if (returnExpression?.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression) != true) { return; } if (ifStatement.SpanOrTrailingTriviaContainsDirectives()) { return; } if (returnStatement.SpanOrLeadingTriviaContainsDirectives()) { return; } SimpleIfStatementInfo simpleIf = SyntaxInfo.SimpleIfStatementInfo(ifStatement); if (!simpleIf.Success) { return; } StatementSyntax statement = simpleIf.IfStatement.SingleNonBlockStatementOrDefault(); if (statement == null) { return; } SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(statement); if (!assignmentInfo.Success) { return; } if (!assignmentInfo.Left.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression)) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(simpleIf.Condition, semanticModel: semanticModel, allowedStyles: NullCheckStyles.CheckingNull, cancellationToken: cancellationToken); if (!nullCheck.Success) { return; } ExpressionSyntax expression = nullCheck.Expression; if (!expression.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression)) { return; } if (!(semanticModel.GetSymbol(expression, cancellationToken) is IFieldSymbol fieldSymbol)) { return; } if (!ExpressionEquals(expression, assignmentInfo.Left)) { return; } if (fieldSymbol.Type.IsNullableType() && returnExpression.Kind() == SyntaxKind.SimpleMemberAccessExpression) { var memberAccessExpression = (MemberAccessExpressionSyntax)returnExpression; if (memberAccessExpression.Name is IdentifierNameSyntax identifierName && string.Equals(identifierName.Identifier.ValueText, "Value", StringComparison.Ordinal)) { returnExpression = memberAccessExpression.Expression; } } if (!ExpressionEquals(expression, returnExpression)) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.SimplifyLazyInitialization, Location.Create(node.SyntaxTree, TextSpan.FromBounds(ifStatement.SpanStart, returnStatement.Span.End))); }
public static async Task <ISymbol?> FindApplicableAlias(this ITypeSymbol type, int position, SemanticModel semanticModel, CancellationToken cancellationToken) { try { if (semanticModel.IsSpeculativeSemanticModel) { position = semanticModel.OriginalPositionForSpeculation; semanticModel = semanticModel.ParentModel; } var root = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var applicableUsings = GetApplicableUsings(position, (CompilationUnitSyntax)root); foreach (var applicableUsing in applicableUsings) { var alias = semanticModel.GetOriginalSemanticModel().GetDeclaredSymbol(applicableUsing, cancellationToken); if (alias != null && Equals(alias.Target, type)) { return(alias); } } return(null); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
private static bool HasFloatingType(ExpressionSyntax right, ExpressionSyntax left, SemanticModel semanticModel) { return(IsExpressionFloatingType(right, semanticModel) || IsExpressionFloatingType(left, semanticModel)); }
private static void CheckDelegateCreation(SyntaxNode node, TypeInfo typeInfo, SemanticModel semanticModel, bool isAssignmentToReadonly, Action <Diagnostic> reportDiagnostic, Location location, string filePath, CancellationToken cancellationToken) { // special case: method groups if (typeInfo.ConvertedType?.TypeKind == TypeKind.Delegate) { // new Action<Foo>(MethodGroup); should skip this one var insideObjectCreation = node?.Parent?.Parent?.Parent?.Kind() == SyntaxKind.ObjectCreationExpression; if (node is ParenthesizedLambdaExpressionSyntax || node is SimpleLambdaExpressionSyntax || node is AnonymousMethodExpressionSyntax || node is ObjectCreationExpressionSyntax || insideObjectCreation) { // skip this, because it's intended. } else { if (node.IsKind(SyntaxKind.IdentifierName)) { if (semanticModel.GetSymbolInfo(node, cancellationToken).Symbol is IMethodSymbol) { reportDiagnostic(Diagnostic.Create(MethodGroupAllocationRule, location, EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.MethodGroupAllocation(filePath); } } else if (node.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { var memberAccess = node as MemberAccessExpressionSyntax; if (semanticModel.GetSymbolInfo(memberAccess.Name, cancellationToken).Symbol is IMethodSymbol) { if (isAssignmentToReadonly) { reportDiagnostic(Diagnostic.Create(ReadonlyMethodGroupAllocationRule, location, EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.ReadonlyMethodGroupAllocation(filePath); } else { reportDiagnostic(Diagnostic.Create(MethodGroupAllocationRule, location, EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.MethodGroupAllocation(filePath); } } } else if (node is ArrowExpressionClauseSyntax) { var arrowClause = node as ArrowExpressionClauseSyntax; if (semanticModel.GetSymbolInfo(arrowClause.Expression, cancellationToken).Symbol is IMethodSymbol) { reportDiagnostic(Diagnostic.Create(MethodGroupAllocationRule, location, EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.MethodGroupAllocation(filePath); } } } var symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol; if (symbolInfo?.ContainingType?.IsValueType == true && !insideObjectCreation) { reportDiagnostic(Diagnostic.Create(DelegateOnStructInstanceRule, location, EmptyMessageArgs)); } } }
public static AttributeSyntax FindAttribute(this BaseTypeDeclarationSyntax typeDeclaration, SemanticModel model, string typeName) { return(typeDeclaration.AttributeLists .SelectMany(x => x.Attributes) .Where(x => model.GetTypeInfo(x).Type?.ToDisplayString() == typeName) .FirstOrDefault()); }
private static bool IsExpressionFloatingType(ExpressionSyntax expression, SemanticModel semanticModel) { return(semanticModel.GetTypeInfo(expression).Type.IsAny(KnownType.FloatingPointNumbers)); }