I'd like to have an analyzer detect all calls to setter properties not inside an object initializer of an object implementing a specific interfaces. I'm a bit lost of how to detect that, the docs are a bit thin. I can get an invocation expression, but how to check if it's inside an object initializer?
Any ideas?
To know if any particular code is inside an object initializer, you can simply look up the ancestors for any node that is of type InitializerExpressionSyntax.
var initializer = node.Ancestors().OfType<InitializerExpressionSyntax>.FirstOrDefault();
To know if any particular code is an assignment to a property setter, you'll have to do a bit more work. You'll need to ask the SemanticModel for the symbol being assigned for an AssignmentExpressionSyntax. Your analyzer should have access to the correct SemanticModel and SyntaxTree from its arguments/context.
SemanticModel model = ...;
AssignmentExpressionSyntax assignment = ...; // find the assignment
var symbol = model.GetSymbolInfo(assignment).Symbol as IMethodSymbol;
if (symbol?.MethodKind == MethodKind.PropertySet) { ... }
To know if the object implements a particular interface you will need to find the symbol for the object. You might be able to find it by looking up the containing symbol chain of the property setter symbol. You can also find the symbol for the object by finding the ObjectCreationExpressionSyntax that should be the parent or ancestor of the InitializerExpressionSyntax you already have.
Once you have that creation node you can ask the SemanticModel again. Use the GetTypeInfo method to get the type of the expression (the type/symbol being constructed) and not the symbol for the constructor.
var creation = initializer.Ancestors().OfType<ObjectCreationSyntax>().FirstOrDefault();
var createdType = model.GetTypeInfo(creation).Type as INamedTypeSymbol;
Now, you just need to know if the type implements the interface.
First you will need a symbol for the interface type. One quick way to get that is to look it up using its CLR metadata name.
var interfaceType = model.Compilation.GetTypeByMetadataName("MyNamspace.MyInterfaceType");
This part is usually done once at the initialization of the analyzer, so you don't have to keep looking it up, over and over again.
Now you have everything you need to discover if the type being constructed implements the interface.
if (createdType.AllInterfaces.Contains(interfaceType)) { ... }
Related
My solution builds ok in roslyn and so all types should be resolved
I'm able to get the type defined in a metadata assembly like so:
string typeName = "MyCompany.MyLibrary.MyType`1";
var theType = compilation.GetTypeByMetadataName(typeName);
and when I query the member names I see the method on the type, and I want to find all references to that method, but I can't figure out how I'm supposed to get the symbol for the method. When I try
var symbols = compilation.GetSymbolsWithName("MethodName");
it always returns 0.
And I can't see anyway to navigate from my type to the symbols underneath it in the tree.
I can't get the semantic model and find the symbol that way because I don't have a syntax tree for the metadata assembly.
I can find the symbol if I find an implementation in the current solution when overrides this method, but I don't want to have to go through that, I'd like to just go directly to the symbol.
ITypeSymbol has GetMembers which returns all members from type as ISymbol by a specified name (second overload). So you just need to check, that the set of returned members contains at least an one IMethodSymbol (or you may add a more specific check if you want):
string typeName = "MyCompany.MyLibrary.MyType`1";
var theType = compilation.GetTypeByMetadataName(typeName);
if (!(theType is null))
{
foreach (var member in theType.GetMembers("MethodName"))
{
if (member is IMethodSymbol method) //may check that method has a special parameters, for example
{
// you found the first "MethodName" method
}
}
}
I am getting a referenced type from a Roslyn compilation by using Compilation.GetTypeByMetadataName(...) method. Then I use INamedTypeSymbol.GetMembers() method to get all its member symbols. I am getting all public and protected symbols but neither private nor internal. I do not care much about private member symbols, but internals are a must for me. Is there any way to get them from a Roslyn compilation?
It seems like I resolved the problem but not without a hack.
one has to set a hidden property MetadataImportOptions of the compilation to MetadataImportOptions.All (which is 2). Both the CSharpCompilationOptions.MetadataImportOptions member and MetadataImportOptions enumeration are internal to Microsort.CodeAnalysis assembly. I had to use reflection to be able to set it. In particular I
did something like:
MethodInfo withMetadataImportOptionsMethodInfo =
typeof(CSharpCompilationOptions).GetMethod("WithMetadataImportOptions, BindingFlags.NonPublic | BindingFlags.Instance);
MyCompilationOptions =
(CSharpCompilationOptions) withMetadataImportOptionsMethodInfo.Invoke(MyCompilationOptions, (byte) 2);
(byte) 2 is the MetadataImportOptions.All option.
My goal here is to create a unique ID (starting a 0) for each child of a specific class. I'm not sure if it is possible in the way i want, but i figured i'd ask here as a last resort.
Some context:
I'm creating my own 2D game engine and i want it to have an ECS as it's back bone (Before anyone says anything, i'm doing this as a learning experience, i know i could just use an already existing game engine). My idea is that each class that implements the 'EntityComponent' class should have a unique ID applied to it. This needs to be per child, not per object. I want to use this ID as the index for an array to find the component of an entity. The actual ID that each Component gets is unimportant and each component does not need to be assigned the ID every run time.
My hope is there is some way to create something similar to a static variable per class (That implements the Entity Component class). It needs to be quick to get this value so doing an unordered_map lookup is slower than i would like. One thing i do not want to do is setting the ID for every component myself. This could cause problems once many components are made and could cause problems if i forget to set it or set two components to the same ID.
One idea i had was to make a variable in EntityComponent called ID (And a getter to get it). When the entity is constructed it looks up an unordered map (which was made at run time, assigning an ID to each class) for what ID it should have. The price of looking up once at construction is fine. The only problem i see with this is there is a lot of redundant data (Though overall it seems it would account to a pretty small amount). With this, every single transform component would have to store that it its ID is x. This means potentially thousands upon thousands of transform components are storing this ID value, when only 1 really needs to.
Basically i am after an extremely quick way to find an ID for a class TYPE. This can be through a lookup, but it needs to be a quick lookup. I would like something faster than unordered_map if possible. If this can be done through compile time tricks (Maybe enums?) or maybe even templates i would love to hear your ideas. I know premature optimisation is the bad, but being able to get a component fast is a pretty big thing.
What i'm asking might very well be impossible. Just thought i'd ask here to make sure first. I should also note i'm trying to avoid implementation of this in the children classes. I'd like to not have to set up the same code for each child class to create an id.
Thank you.
In order to get something corresponding to the actual type of an object, it either needs to be in the object itself or accessed via a virtual function. Otherwise the type will be determined by the type of the variable it is associated with.
A common option when speed and size are both important is to have an integer identifier associated with each type (when the full type list is known at compile time) and use that integer value in a specific way when you want to do something based on the type.
The integer mechanism usually uses an enum for generating the corresponding value for each type and has that field in every object.
The virtual method variety, I've used boost::uuid and a static data member in each class and a virtual method get'er for it.
Declare a virtual function newId() in EntityComponent.
Implement this function to get and increment a static variable in each class, which children you want to have a unique Id.
Assign Id in the constructor:
mId = newId();
don't know this if this is what you meant and i know this is an old post however this is how im currently dealing with a similar issue, maybe it will help someone else.
(Im also doing this as a learning experience for uni :) )
in the controlling class or its own utility class:
enum class EntityType{ TYPE_ONE = 0, TYPE_TWO =1};
in class header:
#include "EntityType.h"
class Whatever{
public:
inline void getType(){return _type;}
OR
inline void getType(){return EntityType::TYPE_ONE;}
private:
EntityType _type = EntityType::TYPE_ONE;
};
Hope this is helpful to anyone :)
when I go to the definition of List<> I can see it has a public struct Enumerator that implements the interfaces IEnumerator<T>, IDisposable and IEnumerator.
IEnumerator should force the implementation of Reset - besides Current and MoveNext. Yet only Current and MoveNext are implemented.
How can that be?
Where do I find the Reset() of List<>?
var list = new List<int>();
list.Add(23);
list.Add(44);
var Enumerator = list.GetEnumerator();
while (Enumerator.MoveNext())
{
Console.WriteLine(Enumerator.Current);
}
Enumerator.
And when I try it in code there is no Reset():
Ok - I tried to show a screenshot, but they don't let me.
But copying above code shows no Reset-Method after the Dot-operator (.) of Enumerator.
Would someone know and throw some light on this?
I see it calls the Reset of IEnumerator which is part of mscorlib.
var list = new List<int>();
list.Add(23);
list.Add(44);
var Enumerator = list.GetEnumerator();
Enumerator.MoveNext();
Enumerator.MoveNext();
Console.WriteLine(Enumerator.Current);
((IEnumerator<int>)Enumerator).Reset();
Enumerator.MoveNext();
And yet as IEnumerator is an interface how can code be called by it?
Reset() in IEnumerator should just be a definition and the implementation left to whoever uses the interface.
But somehow here actual functionality is provided by just defining the interface to be implemented. Nowhere do I see the actual implementation - and that part I do not understand.
It's explicitly implemented, as shown in the documentation, as is IEnumerator.Current. In other words, you can only call the method on a value with a compile-time type of IEnumerator.
So you could use:
// Casing changed to be more conventional
var enumerator = list.GetEnumerator();
((IEnumerator)enumerator).Reset();
However, that would then box the value anyway (as List<T>.Enumerator is a struct) which would make it pointless. It's not clear whether you're just interested in the apparent lack of a Reset method, but in general I would strongly advise you not to rely on IEnumerator.Reset - it's very often not implemented, and IMO it shouldn't have been part of the interface to start with...
You think you are using the IEnumerator<> interface, but you are not. Type inference is getting the better of you, the type of your Enumerator variable is actually List.Enumerator<>, a structure type. Use the interface and you'll have no trouble:
IEnumerator<int> Enumerator = list.GetEnumerator();
while (Enumerator.MoveNext()) {
Console.WriteLine(Enumerator.Current);
}
Enumerator.Reset(); // Fine
It doesn't work on List.Enumerator<> because Microsoft intentionally hid the Reset() method implementation by making it private. Note how iterators for other collection classes like Dictionary and HashSet behave this way as well.
That could use an explanation. IEnumerator encapsulates a forward-only iterator and is the foundation upon which the house of Linq was built. The Reset() method is a problem, that's no longer strictly forward-only. You move the iterator back. In practice, you'll find out that in many cases trying to call Reset() produces a NotImplementedException. Not a problem for List, easy to go back. Big problem for Linq.
IEnumerator should have been designed without a Reset() method. But it wasn't the .NET designers' choice, this was nailed down before 1996, long before anybody started working on .NET. Iterators were an existing concept in COM Automation. Which was the extension model for Visual Basic version 4, it replaced the 16-bit VBX model.
Wildly popular, almost any language runtime on Windows implements it. And still very heavily used in .NET programs. Skillfully hidden in most cases, no way to tell that you are using it when you put a WebBrowser on your UI for example. The .NET designers were forced to implement it as well to have a shot at getting programmers to move to .NET. Also the source of the very troublesome ICloneable interface.
This has been driving me nuts for over a week. Below are two snippets of Lua code from a robot player in the game Bitfighter (written in C++, using a variant of LuaWrapper for binding).
When I first start the Lua script, both work exactly as expected. But after some minutes of intense object creation and destruction, variant 2 stops working, and gives me the following error:
robot.lua:253: attempt to call missing or unknown method 'getEnergy' (a nil value)
To my eyes these should function identically. Who can explain the difference?
Notes: target is a (heavy) userdata representing a C++ object. getEnergy and getHealth are properly registered C++ functions. I can reproduce this differing behavior easily. This is Lua 5.1, using the luavec mod.
Variant 1 - always works
local mt = getmetatable(target)
local pow = mt.getEnergy(target) + mt.getHealth(target)
Variant 2 - starts failing after script has been running for an arbitrary amount of time
local pow = target:getEnergy() + target:getHealth()
To track what happens when it stops working you can wrap the call in pcall and explore what happened with the target value:
local ok, res = pcall(function() return target:getEnergy() + target:getHealth() end)
if not ok then
local s = "Invalid target value: "..tostring(target).." "..type(target).."\n"
for k, v in pairs(target) do s = s.."target "..tostring(k).." "..tostring(v).."\n" end
for k, v in pairs(getmetatable(target)) do s = s.."meta "..tostring(k).." "..tostring(v).."\n" end
-- add anything else that helps you figure out what happened to target
error(res..s)
end
local pow = res
I strongly suspect the issue is that you have a class or struct similar to this:
struct Foo
{
Bar bar;
// Other fields follow
}
And that you've exposed both Foo and Bar to Lua via LuaWrapper. The important bit here is that bar is the first field on your Foo struct. Alternatively, you may have some class that inherits from some other base class and both the derived and base class are exposed to LuaWrapper.
LuaWrapper uses an function called an Identifier to uniquely track each object (like whether or not the given object has already been added to the Lua state). By default it uses the object address as a key. In cases like the one posed above it is possible that both Foo and Bar have the same address in memory, and thus LuaWrapper can get confused.
This may result in grabbing the wrong object's metatable when attempting to look up a method. Clearly, since it's looking at the wrong metatable it won't find the method you want, and so it will appear as if your metatable has mysteriously lost entries.
I've checked in a change that tracks each object's data per-type rather than in one giant pile. If you update your copy LuaWrapper to latest one from the repository I'm fairly certain your problem will be fixed.
When you say it stops working at some stage, but works fine before... Could it be that you overwrite the .getEnergy function anywhere at runtime?
Maybe you're running a foo.getEnergy = nil instead of a foo.getEnergy == nil somewhere? Sounds like it might be a late initialization gone awry :)