using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Linq; namespace Semmle.Extraction.CSharp.Populators { public static class LocationExtensions { /// /// Manually extend a location. /// /// The location to extend. /// The node to extend the location to. /// Extended location. public static Location ExtendLocation(this Location l1, SyntaxNode n2) { if (n2 == null) { return l1; } var l2 = n2.FixedLocation(); var start = System.Math.Min(l1.SourceSpan.Start, l2.SourceSpan.Start); var end = System.Math.Max(l1.SourceSpan.End, l2.SourceSpan.End); return Location.Create(n2.SyntaxTree, new Microsoft.CodeAnalysis.Text.TextSpan(start, end - start)); } /// /// Adjust the location of some syntax nodes /// to make them more suitable for displaying results. /// Sometimes we do not wish to highlight the whole node, /// so select a sub-node such as the name. /// !! Refactor this into each entity. /// /// The syntax node. /// The fixed location. public static Location FixedLocation(this SyntaxNode node) { Location result; switch (node.Kind()) { case SyntaxKind.EqualsValueClause: result = ((EqualsValueClauseSyntax)node).Value.FixedLocation(); break; case SyntaxKind.OperatorDeclaration: { var decl = (OperatorDeclarationSyntax)node; result = decl.OperatorKeyword.GetLocation().ExtendLocation(decl.ParameterList); break; } case SyntaxKind.ConversionOperatorDeclaration: { var decl = (ConversionOperatorDeclarationSyntax)node; result = decl.OperatorKeyword.GetLocation(); break; } case SyntaxKind.DelegateDeclaration: { var decl = (DelegateDeclarationSyntax)node; return decl.Identifier.GetLocation().ExtendLocation(decl.TypeParameterList); } case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: { var decl = (TypeDeclarationSyntax)node; return decl.Identifier.GetLocation().ExtendLocation(decl.TypeParameterList); } case SyntaxKind.EnumDeclaration: return ((EnumDeclarationSyntax)node).Identifier.GetLocation(); case SyntaxKind.MethodDeclaration: { var decl = (MethodDeclarationSyntax)node; return decl.Identifier.GetLocation().ExtendLocation(decl.TypeParameterList); } case SyntaxKind.ConstructorDeclaration: { var decl = (ConstructorDeclarationSyntax)node; return decl.Identifier.GetLocation(); } case SyntaxKind.ParenthesizedExpression: return ((ParenthesizedExpressionSyntax)node).Expression.FixedLocation(); case SyntaxKind.CatchDeclaration: return ((CatchDeclarationSyntax)node).Identifier.GetLocation(); case SyntaxKind.LabeledStatement: return ((LabeledStatementSyntax)node).Identifier.GetLocation(); default: result = node.GetLocation(); break; } return result; } public static Location GetSymbolLocation(this ISymbol symbol) { return symbol.DeclaringSyntaxReferences.Any() ? symbol.DeclaringSyntaxReferences.First().GetSyntax().FixedLocation() : symbol.Locations.First(); } } }