private static void AnalyzeCall(SyntaxNodeAnalysisContext context, ISymbol migratableAttributeType, ISymbol dataContractAttributeType, ISymbol dataMemberAttributeType) { var typeDecl = (TypeDeclarationSyntax)context.Node; var semanticModel = context.SemanticModel; var ct = context.CancellationToken; var isMigratable = MigrationHashHelper.HasAttribute(typeDecl, migratableAttributeType, semanticModel, ct); if (!isMigratable) { return; } if (dataContractAttributeType != null && dataMemberAttributeType != null) { var isDataContract = MigrationHashHelper.HasAttribute(typeDecl, dataContractAttributeType, semanticModel, ct); var hasDataMember = MigrationHashHelper.GetDataMembers(typeDecl, ct, semanticModel, dataMemberAttributeType).Any(); if (isDataContract && hasDataMember) { return; } } var diagnostic = Diagnostic.Create(Rule, typeDecl.GetLocation(), typeDecl.Identifier.ToString()); context.ReportDiagnostic(diagnostic); }
private static void AnalyzeCall(SyntaxNodeAnalysisContext context, ISymbol migratableAttributeType) { var ct = context.CancellationToken; var typeDeclaration = (TypeDeclarationSyntax)context.Node; var attribute = MigrationHashHelper.GetAttribute(typeDeclaration, migratableAttributeType, context.SemanticModel, ct); if (attribute == null) { return; } var typeSymbol = context.SemanticModel.GetDeclaredSymbol(typeDeclaration, ct); var verifier = new MigrationMethodVerifier(CanAssign(context)); var migrationMethods = MigrationHashHelper.GetMigrationMethods(typeSymbol); var invalidMethods = verifier.VerifyMigrationMethods(migrationMethods) .Where(x => x.Result != VerificationResultEnum.Ok); foreach (var x in invalidMethods) { var method = typeSymbol.GetMembers() .First(sy => sy.Name == x.Method.Name); Debug.Assert(method.Locations.Length == 1, "Method has multiple locations."); var diagnostic = Diagnostic.Create(Rule, method.Locations[0], method.Name, typeSymbol.Name, x.Result); context.ReportDiagnostic(diagnostic); } }
private static async Task <Document> FixMigrationHash(Document document, TypeDeclarationSyntax typeDecl, CancellationToken ct) { var semanticModel = await document.GetSemanticModelAsync(ct); var newTypeDecl = MigrationHashHelper.UpdateMigrationHash(typeDecl, ct, semanticModel); var root = await document.GetSyntaxRootAsync(ct); var newRoot = root.ReplaceNode(typeDecl, newTypeDecl); return(document.WithSyntaxRoot(newRoot)); }
private static async Task <Document> AddMigrationMethod(Document document, TypeDeclarationSyntax typeDecl, CancellationToken ct) { var semanticModel = await document.GetSemanticModelAsync(ct); var typeSymbol = semanticModel.GetDeclaredSymbol(typeDecl, ct); var latestMigrationMethod = MigrationHashHelper.GetMigrationMethods(typeSymbol).LastOrDefault(); var latestVersion = latestMigrationMethod?.ToVersion ?? 0; var dataArgumentTypeName = latestMigrationMethod?.ReturnType.Name ?? "JToken"; var method = GetMigrationMethod(latestVersion + 1, dataArgumentTypeName, ct); var typeDeclWithUpdatedMigrationHash = MigrationHashHelper.UpdateMigrationHash(typeDecl, ct, semanticModel); var typeDeclWithAddedMigrationMethod = AddMember(typeDeclWithUpdatedMigrationHash, method); var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(ct); var rootWithNewTypeDecl = root.ReplaceNode(typeDecl, typeDeclWithAddedMigrationMethod); return(document.WithSyntaxRoot(rootWithNewTypeDecl)); }
private static void AnalyzeCall(SyntaxNodeAnalysisContext context, ISymbol migratableAttributeType, ISymbol dataMemberAttributeType) { var ct = context.CancellationToken; var typeDeclaration = (TypeDeclarationSyntax)context.Node; var attribute = MigrationHashHelper.GetAttribute(typeDeclaration, migratableAttributeType, context.SemanticModel, ct); if (attribute == null) { return; } var attributeHash = GetAttributeHash(attribute, context.SemanticModel, ct); var computedHash = MigrationHashHelper.GetMigrationHashFromType(typeDeclaration, ct, context.SemanticModel, dataMemberAttributeType); if (attributeHash != computedHash) { var diagnostic = Diagnostic.Create(Rule, typeDeclaration.GetLocation(), typeDeclaration.Identifier.ToString(), computedHash, attributeHash); context.ReportDiagnostic(diagnostic); } }
public void ShouldGetAllDataMembers() { var tree = SyntaxFactory.ParseSyntaxTree(@"using System.Runtime.Serialization; public class A { public string PropertyA { get; } [DataMember] public string PropertyB { get; } public int FieldA { get; } [DataMember] public int FieldB { get; } }"); var compilation = CSharpCompilation.Create( "MyCompilation", syntaxTrees: new[] { tree }, references: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(DataMemberAttribute).Assembly.Location) }); var model = compilation.GetSemanticModel(tree); var typeDecl = tree .GetRoot() .ChildNodes() .OfType <TypeDeclarationSyntax>() .Single(); var dataMemberAttributeType = compilation.GetTypeByMetadataName(Constants.DataMemberAttributeMetadataName); var dataMembers = MigrationHashHelper.GetDataMembers(typeDecl, CancellationToken.None, model, dataMemberAttributeType); dataMembers.Count.Should().Be(2); dataMembers[0].Identifier.Should().Be("FieldB"); dataMembers[0].Type.Should().Be("int"); dataMembers[1].Identifier.Should().Be("PropertyB"); dataMembers[1].Type.Should().Be("string"); }