c# - Check if IPropertySymbol has a backing field -
i started playing roslyn few days ago , trying write extension method tells if ipropertysymbol
has backing field, thought property has backing field if , if following not apply(as far concerned):
- if abstract
- if extern
- if readonlyproperty
- if getter or setter has no body or empty body
so came with
public static bool hasbackingfield(this ipropertysymbol property) { return !(property.isabstract || property.isextern || property.isreadonly); }
my questions are
- did miss condition?
- how check last condition? found
getmethod
,setmethod
properties inipropertysymbol
don't know check if have body
example start with
var code = @"class xyz { public int x => 4; //hasbacking field : false isreadonly public int m { { return 0;}} //hasbacking field : false isreadonly public int y { get; set; } //hasbacking field : false null body setter or getter public int z { { return 0; } set { } } //hasbacking field : false empty body setter or getter private int _g; public int g //hasbacking field : true getter , setter has no empty bodies { { return _g; } set { _g = value; } } }"; var syntaxtree = csharpsyntaxtree.parsetext(code); var compilation = csharpcompilation.create("xxx").addsyntaxtrees(syntaxtree); var classsymbol = compilation.gettypebymetadataname("xyz"); var propsymbols = classsymbol.getmembers().oftype<ipropertysymbol>(); var results = propsymbols.select(ps => ps.hasbackingfield()); //should [false false false false true]
i decided @ syntax representation rather actual symbol -- syntax @ lower level symbol , contains raw information we're interested in: looking @ individual statements.
this seems you're interested in:
internal static bool hasbackingfield(this propertydeclarationsyntax property) { var getter = property.accessorlist?.accessors.firstordefault(x => x.iskind(syntaxkind.getaccessordeclaration)); var setter = property.accessorlist?.accessors.firstordefault(x => x.iskind(syntaxkind.setaccessordeclaration)); if (setter?.body == null || getter?.body == null) { return false; } bool setterhasbodystatements = setter.body.statements.any(); bool getterhasbodystatements = getter.body.statements.any(); return setterhasbodystatements && getterhasbodystatements; }
note i'm not convinced reliable enough conclude there backing field available, follows idea had checking if there body or not.
i haven't added other checks had in mind these can trivially added (either use symbol or through propertydeclarationsyntax
modifiers/attributes).
---
full code test out yourself:
public static void execute() { var code = @"class xyz { public int x => 4; //hasbacking field : false isreadonly public int m { { return 0;}} //hasbacking field : false isreadonly public int y { get; set; } //hasbacking field : false null body setter or getter public int z { { return 0; } set { } } //hasbacking field : false empty body setter or getter private int _g; public int g //hasbacking field : true getter , setter has no empty bodies { { return _g; } set { _g = value; } } }"; var tree = csharpsyntaxtree.parsetext(code); var root = tree.getroot(); foreach (var prop in root.descendantnodes().oftype<propertydeclarationsyntax>()) { console.writeline(prop.hasbackingfield()); } } } internal static class extensions { internal static bool hasbackingfield(this propertydeclarationsyntax property) { var getter = property.accessorlist?.accessors.firstordefault(x => x.iskind(syntaxkind.getaccessordeclaration)); var setter = property.accessorlist?.accessors.firstordefault(x => x.iskind(syntaxkind.setaccessordeclaration)); if (setter?.body == null || getter?.body == null) { return false; } bool setterhasbodystatements = setter.body.statements.any(); bool getterhasbodystatements = getter.body.statements.any(); return setterhasbodystatements && getterhasbodystatements; } }
Comments
Post a Comment