protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken, out TextSpan issueSpan) { // If it is already var, return. if (typeName.IsTypeInferred(semanticModel)) { issueSpan = default(TextSpan); return false; } var candidateReplacementNode = SyntaxFactory.IdentifierName("var"); var candidateIssueSpan = typeName.Span; // If there exists a type named var, return. var conflict = semanticModel.GetSpeculativeSymbolInfo(typeName.SpanStart, candidateReplacementNode, SpeculativeBindingOption.BindAsTypeOrNamespace).Symbol; if (conflict?.IsKind(SymbolKind.NamedType) == true) { issueSpan = default(TextSpan); return false; } if (typeName.Parent.IsKind(SyntaxKind.VariableDeclaration) && typeName.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.ForStatement, SyntaxKind.UsingStatement)) { var variableDeclaration = (VariableDeclarationSyntax)typeName.Parent; // implicitly typed variables cannot be constants. if ((variableDeclaration.Parent as LocalDeclarationStatementSyntax)?.IsConst == true) { issueSpan = default(TextSpan); return false; } var variable = variableDeclaration.Variables.Single(); if (AssignmentSupportsStylePreference( variable.Identifier, typeName, variable.Initializer.Value, semanticModel, optionSet, cancellationToken)) { issueSpan = candidateIssueSpan; return true; } } else if (typeName.IsParentKind(SyntaxKind.ForEachStatement)) { issueSpan = candidateIssueSpan; return true; } issueSpan = default(TextSpan); return false; }
private static DiagnosticDescriptor GetCorrespondingDiagnostic(SemanticModel semanticModel, InvocationExpressionSyntax invocation) { var methodName = (invocation?.Expression as MemberAccessExpressionSyntax)?.Name?.ToString(); var nameToCheck = methodName == "Any" ? allName : methodName == "All" ? anyName : null; if (nameToCheck == null) return null; var invocationSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; if (invocationSymbol?.Parameters.Length != 1) return null; if (!IsLambdaWithoutBody(invocation)) return null; var otherInvocation = invocation.WithExpression(((MemberAccessExpressionSyntax)invocation.Expression).WithName(nameToCheck)); var otherInvocationSymbol = semanticModel.GetSpeculativeSymbolInfo(invocation.SpanStart, otherInvocation, SpeculativeBindingOption.BindAsExpression); if (otherInvocationSymbol.Symbol == null) return null; if (methodName == "Any") return RuleAny; return RuleAll; }
/// <summary> /// Binds the node in the context of the specified location and get semantic information /// such as type, symbols and diagnostics. This method is used to get semantic information /// about an expression that did not actually appear in the source code. /// </summary> /// <param name="semanticModel"></param> /// <param name="position">A character position used to identify a declaration scope and /// accessibility. This character position must be within the FullSpan of the Root syntax /// node in this SemanticModel. /// </param> /// <param name="expression">A syntax node that represents a parsed expression. This syntax /// node need not and typically does not appear in the source code referred to SemanticModel /// instance.</param> /// <param name="bindingOption">Indicates whether to binding the expression as a full expressions, /// or as a type or namespace. If SpeculativeBindingOption.BindAsTypeOrNamespace is supplied, then /// expression should derive from TypeSyntax.</param> /// <returns>The semantic information for the topmost node of the expression.</returns> /// <remarks>The passed in expression is interpreted as a stand-alone expression, as if it /// appeared by itself somewhere within the scope that encloses "position".</remarks> public static SymbolInfo GetSpeculativeSymbolInfo(this SemanticModel semanticModel, int position, SyntaxNode expression, SpeculativeBindingOption bindingOption) { return(semanticModel.GetSpeculativeSymbolInfo(position, expression, bindingOption)); }
public static bool TryReduceOrSimplifyExplicitName( this CrefSyntax crefSyntax, SemanticModel semanticModel, out CrefSyntax replacementNode, out TextSpan issueSpan, OptionSet optionSet, CancellationToken cancellationToken) { replacementNode = null; issueSpan = default(TextSpan); // Currently Qualified Cref is the only CrefSyntax We are handling separately if (crefSyntax.Kind() != SyntaxKind.QualifiedCref) { return false; } var qualifiedCrefSyntax = (QualifiedCrefSyntax)crefSyntax; var memberCref = qualifiedCrefSyntax.Member; // Currently we are dealing with only the NameMemberCrefs if (optionSet.GetOption(SimplificationOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, LanguageNames.CSharp) && (memberCref.Kind() == SyntaxKind.NameMemberCref)) { var nameMemberCref = ((NameMemberCrefSyntax)memberCref).Name; var symbolInfo = semanticModel.GetSymbolInfo(nameMemberCref, cancellationToken); var symbol = symbolInfo.Symbol; if (symbol == null) { return false; } if (symbol is INamespaceOrTypeSymbol) { //var namespaceOrTypeSymbol = (INamespaceOrTypeSymbol)symbol; // 1. Check for Predefined Types if (symbol is INamedTypeSymbol) { var namedSymbol = (INamedTypeSymbol)symbol; var keywordKind = ExpressionSyntaxExtensions.GetPredefinedKeywordKind(namedSymbol.SpecialType); if (keywordKind != SyntaxKind.None) { replacementNode = SyntaxFactory.TypeCref( SyntaxFactory.PredefinedType( SyntaxFactory.Token(crefSyntax.GetLeadingTrivia(), keywordKind, crefSyntax.GetTrailingTrivia()))); replacementNode = crefSyntax.CopyAnnotationsTo(replacementNode); // we want to show the whole name expression as unnecessary issueSpan = crefSyntax.Span; return true; } } } } var oldSymbol = semanticModel.GetSymbolInfo(crefSyntax, cancellationToken).Symbol; if (oldSymbol != null) { var speculativeBindingOption = SpeculativeBindingOption.BindAsExpression; if (oldSymbol is INamespaceOrTypeSymbol) { speculativeBindingOption = SpeculativeBindingOption.BindAsTypeOrNamespace; } var newSymbol = semanticModel.GetSpeculativeSymbolInfo(crefSyntax.SpanStart, memberCref, speculativeBindingOption).Symbol; if (newSymbol == oldSymbol) { // Copy Trivia and Annotations memberCref = memberCref.WithLeadingTrivia(crefSyntax.GetLeadingTrivia()); memberCref = crefSyntax.CopyAnnotationsTo(memberCref); issueSpan = qualifiedCrefSyntax.Container.Span; replacementNode = memberCref; return true; } } return false; }
// private static bool IsThisOrTypeOrNamespace(MemberAccessExpressionSyntax memberAccess, SemanticModel semanticModel) // { // if (memberAccess.Expression.Kind() == SyntaxKind.ThisExpression) // { // var previousToken = memberAccess.Expression.GetFirstToken().GetPreviousToken(); // // var symbol = semanticModel.GetSymbolInfo(memberAccess.Name).Symbol; // // if (previousToken.Kind() == SyntaxKind.OpenParenToken && // previousToken.Parent.IsKind(SyntaxKind.ParenthesizedExpression) && // !previousToken.Parent.IsParentKind(SyntaxKind.ParenthesizedExpression) && // ((ParenthesizedExpressionSyntax)previousToken.Parent).Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression && // symbol != null && symbol.Kind == SymbolKind.Method) // { // return false; // } // // return true; // } // // var expressionInfo = semanticModel.GetSymbolInfo(memberAccess.Expression); // if (SimplificationHelpers.IsValidSymbolInfo(expressionInfo.Symbol)) // { // if (expressionInfo.Symbol is INamespaceOrTypeSymbol) // { // return true; // } // // if (expressionInfo.Symbol.IsThisParameter()) // { // return true; // } // } // // return false; // } private static bool IsReplacableByVar( this TypeSyntax simpleName, SemanticModel semanticModel, out TypeSyntax replacementNode, out TextSpan issueSpan, OptionSet optionSet, CancellationToken cancellationToken) { replacementNode = null; issueSpan = default(TextSpan); if (!optionSet.GetOption(SimplificationOptions.PreferImplicitTypeInLocalDeclaration)) { return false; } // If it is already var if (simpleName.IsVar) { return false; } var candidateReplacementNode = SyntaxFactory.IdentifierName("var") .WithLeadingTrivia(simpleName.GetLeadingTrivia()) .WithTrailingTrivia(simpleName.GetTrailingTrivia()); var candidateIssueSpan = simpleName.Span; // If there exists a Type called var , fail. var checkSymbol = semanticModel.GetSpeculativeSymbolInfo(simpleName.SpanStart, candidateReplacementNode, SpeculativeBindingOption.BindAsTypeOrNamespace).Symbol; if (checkSymbol != null && checkSymbol.IsKind(SymbolKind.NamedType) && ((INamedTypeSymbol)checkSymbol).TypeKind == TypeKind.Class && checkSymbol.Name == "var") { return false; } // If the simpleName is the type of the Variable Declaration Syntax belonging to LocalDeclaration, For Statement or Using statement if (simpleName.IsParentKind(SyntaxKind.VariableDeclaration) && ((VariableDeclarationSyntax)simpleName.Parent).Type == simpleName && simpleName.Parent.Parent.IsKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.ForStatement, SyntaxKind.UsingStatement)) { if (simpleName.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement) && ((LocalDeclarationStatementSyntax)simpleName.Parent.Parent).Modifiers.Any(n => n.Kind() == SyntaxKind.ConstKeyword)) { return false; } var variableDeclaration = (VariableDeclarationSyntax)simpleName.Parent; // Check the Initialized Value to see if it is allowed to be in the Var initialization if (variableDeclaration.Variables.Count != 1 || !variableDeclaration.Variables.Single().Initializer.IsKind(SyntaxKind.EqualsValueClause)) { return false; } var variable = variableDeclaration.Variables.Single(); var initializer = (EqualsValueClauseSyntax)variable.Initializer; var identifier = variable.Identifier; if (EqualsValueClauseNotSuitableForVar(identifier, simpleName, initializer, semanticModel, cancellationToken)) { return false; } replacementNode = candidateReplacementNode; issueSpan = candidateIssueSpan; return true; } if (simpleName.IsParentKind(SyntaxKind.ForEachStatement) && ((ForEachStatementSyntax)simpleName.Parent).Type == simpleName) { replacementNode = candidateReplacementNode; issueSpan = candidateIssueSpan; return true; } return false; }
static JToken GetTokenInfo(SemanticModel model, SyntaxToken token) { var symbol = model.GetDeclaredSymbol(token.Parent); if (symbol == null) { var symbolInfo = model.GetSymbolInfo(token.Parent); if (symbolInfo.Symbol == null) { symbolInfo = model.GetSpeculativeSymbolInfo(0, token.Parent, SpeculativeBindingOption.BindAsTypeOrNamespace); if (symbolInfo.Symbol == null) { symbolInfo = model.GetSpeculativeSymbolInfo(0, token.Parent, SpeculativeBindingOption.BindAsExpression); if (symbolInfo.Symbol == null) return null; } } symbol = symbolInfo.Symbol; } if (!symbol.IsDefinition) symbol = symbol.OriginalDefinition; string info = null; var displayPoarts = symbol.ToDisplayParts(format); var xml = symbol.GetDocumentationCommentXml(CultureInfo.InvariantCulture, true); if(!string.IsNullOrEmpty(xml)) { try { XDocument doc = XDocument.Parse(xml); var summary = doc.Root.Element("summary"); if (summary != null) info = summary.Value; } catch { } } return new JObject( new JProperty("summary", info == null ? null : new JValue(info)), new JProperty("name", new JArray( displayPoarts.Select(part => Categorize(part)) )) ); }
private static SyntaxNode CreatRootWithUsingFromMemberAccessedNode(SyntaxNode root, SemanticModel semanticModel, ref string newVariableName, ExpressionSyntax accessedNode) { SyntaxNode newRoot; var memberAccessStatement = accessedNode.Parent; var newVariableNameParts = newVariableName.Split('.'); newVariableName = newVariableNameParts[newVariableNameParts.Length - 1].ToLowerCaseFirstLetter(); var parentStatement = memberAccessStatement.FirstAncestorOrSelfThatIsAStatement(); var originalName = newVariableName; for (int nameIncrement = 1; ; nameIncrement++) { var speculativeSymbol = semanticModel.GetSpeculativeSymbolInfo(parentStatement.GetLocation().SourceSpan.Start, SyntaxFactory.IdentifierName(newVariableName), SpeculativeBindingOption.BindAsExpression); if (speculativeSymbol.Symbol == null) break; newVariableName = originalName + nameIncrement; } var newVariable = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(SyntaxFactory.ParseTypeName("var"), SyntaxFactory.SeparatedList(new[] { SyntaxFactory.VariableDeclarator(newVariableName).WithInitializer(SyntaxFactory.EqualsValueClause(accessedNode)) }))); newRoot = root.TrackNodes(parentStatement, accessedNode); newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(accessedNode), SyntaxFactory.IdentifierName(newVariableName)); var newTrackedParentStatement = newRoot.GetCurrentNode(parentStatement); newRoot = newRoot.InsertNodesBefore(newTrackedParentStatement, new[] { newVariable }); var statement = (LocalDeclarationStatementSyntax)newRoot.GetCurrentNode(parentStatement).GetPreviousStatement(); var variableDeclaration = statement.Declaration; var variableDeclarator = variableDeclaration.Variables.First(); newRoot = CreateRootWithUsing(newRoot, statement, u => u.WithDeclaration(variableDeclaration.WithoutLeadingTrivia())); return newRoot; }
public static SyntaxNode CreateUsing(SyntaxNode root, ObjectCreationExpressionSyntax objectCreation, SemanticModel semanticModel) { SyntaxNode newRoot; if (objectCreation.Parent.IsKind(SyntaxKind.SimpleAssignmentExpression)) { var assignmentExpression = (AssignmentExpressionSyntax)objectCreation.Parent; var statement = assignmentExpression.Parent as ExpressionStatementSyntax; var identitySymbol = (ILocalSymbol)semanticModel.GetSymbolInfo(assignmentExpression.Left).Symbol; newRoot = UsedOutsideParentBlock(semanticModel, statement, identitySymbol) ? CreateRootAddingDisposeToEndOfMethod(root, statement, identitySymbol) : CreateRootWithUsing(root, statement, u => u.WithExpression(assignmentExpression)); } else if (objectCreation.Parent.IsKind(SyntaxKind.EqualsValueClause) && objectCreation.Parent.Parent.IsKind(SyntaxKind.VariableDeclarator)) { var variableDeclarator = (VariableDeclaratorSyntax)objectCreation.Parent.Parent; var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; var statement = (LocalDeclarationStatementSyntax)variableDeclaration.Parent; newRoot = CreateRootWithUsing(root, statement, u => u.WithDeclaration(variableDeclaration.WithoutLeadingTrivia())); } else if (objectCreation.Parent.IsKind(SyntaxKind.Argument)) { var identifierName = GetIdentifierName(objectCreation, semanticModel); var variableDeclaration = SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName(@"var")) .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(identifierName)) .WithInitializer(SyntaxFactory.EqualsValueClause(SyntaxFactory.Token(SyntaxKind.EqualsToken), objectCreation)))); var arg = objectCreation.Parent as ArgumentSyntax; var args = objectCreation.Parent.Parent as ArgumentListSyntax; var newArgs = args.ReplaceNode(arg, arg.WithExpression(SyntaxFactory.IdentifierName(identifierName))); StatementSyntax statement = objectCreation.FirstAncestorOfType<ExpressionStatementSyntax>(); if (statement != null) { var exprStatement = statement.ReplaceNode(args, newArgs); var newUsingStatment = CreateUsingStatement(exprStatement, SyntaxFactory.Block(exprStatement)) .WithDeclaration(variableDeclaration); return root.ReplaceNode(statement, newUsingStatment); } statement = (StatementSyntax)objectCreation.Ancestors().First(node => node is StatementSyntax); var newStatement = statement.ReplaceNode(args, newArgs); var statementsForUsing = new[] { newStatement }.Concat(GetChildStatementsAfter(statement)); var usingBlock = SyntaxFactory.Block(statementsForUsing); var usingStatement = CreateUsingStatement(newStatement, usingBlock) .WithDeclaration(variableDeclaration); var statementsToReplace = new List<StatementSyntax> { statement }; statementsToReplace.AddRange(statementsForUsing.Skip(1)); newRoot = root.ReplaceNodes(statementsToReplace, (node, _) => node.Equals(statement) ? usingStatement : null); } else if (objectCreation.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { var newVariableName = objectCreation.Type.ToString(); var newVariableNameParts = newVariableName.Split('.'); newVariableName = newVariableNameParts[newVariableNameParts.Length - 1].ToLowerCaseFirstLetter(); var parentStatement = objectCreation.Parent.FirstAncestorOrSelfThatIsAStatement(); var originalName = newVariableName; for (int nameIncrement = 1; ; nameIncrement++) { var speculativeSymbol = semanticModel.GetSpeculativeSymbolInfo(parentStatement.GetLocation().SourceSpan.Start, SyntaxFactory.IdentifierName(newVariableName), SpeculativeBindingOption.BindAsExpression); if (speculativeSymbol.Symbol == null) break; newVariableName = originalName + nameIncrement; } var newVariable = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(SyntaxFactory.ParseTypeName("var"), SyntaxFactory.SeparatedList(new[] { SyntaxFactory.VariableDeclarator(newVariableName).WithInitializer(SyntaxFactory.EqualsValueClause(objectCreation)) }))); newRoot = root.TrackNodes(parentStatement, objectCreation); newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(objectCreation), SyntaxFactory.IdentifierName(newVariableName)); var newTrackedParentStatement = newRoot.GetCurrentNode(parentStatement); newRoot = newRoot.InsertNodesBefore(newTrackedParentStatement, new[] { newVariable }); var statement = (LocalDeclarationStatementSyntax)newRoot.GetCurrentNode(parentStatement).GetPreviousStatement(); var variableDeclaration = statement.Declaration; var variableDeclarator = variableDeclaration.Variables.First(); newRoot = CreateRootWithUsing(newRoot, statement, u => u.WithDeclaration(variableDeclaration.WithoutLeadingTrivia())); } else { newRoot = CreateRootWithUsing(root, (ExpressionStatementSyntax)objectCreation.Parent, u => u.WithExpression(objectCreation)); } return newRoot; }