Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getCanonicalTypeName() for Field and Variable types. #15

Open
wants to merge 12 commits into
base: dev
Choose a base branch
from

Conversation

Flone-dnb
Copy link

@Flone-dnb Flone-dnb commented Aug 28, 2022

Hello. As I described in one of my issues I needed something like this, so I've spend some time to dig into the source code and I think I'm close to implementing this feature.

This PR adds getCanonicalTypeName() for VariableBase class which means that both Field and Variable will have this function. Canonical type name is taken from kodgen::TypeInfo class and added to generated files. Since non reflected types can be considered equal (while in reality it may be incorrect) I've put canonical type name to VariableBase instead of Type.

Here is an example:

#pragma once

#include <string>
#include <vector>

#include "Foo.generated.h"

using namespace std;

class CLASS() Foo{
public:
    Foo() = default;
    virtual ~Foo() = default;

    FIELD()
    const vector<string> myValue;

    FIELD()
    string myString;

    Foo_GENERATED
};
File_Foo_GENERATED

For myValue this function will return std::vector<std::basic_string<char>> and for myString it will be std::basic_string<char>.

Due to the lack of knowledge of this project I was unable to compile RefurekuTests target, got lots of errors like:

TestClass.rfks.h(23, 232): [C2259] 'UniqueInheritedProperty': cannot instantiate abstract class (compiling source file D:\Downloads\Refureku\Refureku\Library\Tests\Src\TestClass.cpp)

I've regenerated reflection for test files but was still getting these errors. Maybe you need to regenerate reflection in some special way?

Also, I've noticed that if you don't include <vector> type name for myValue will not be std::vector<std::basic_string<char>> but int and the same for string field if you don't include <string>. So when shouldLogDiagnostic is true we can see:

...
[Warning] ...h:16:18: error: use of undeclared identifier 'string'
[Warning] ...h:19:5: error: unknown type name 'string'
[Warning] ...h:21:5: error: unknown type name 'Node_GENERATED'
...

I think we should detect actual errors (like use of undeclared identifier 'string') and stop code generation and ignore errors like unknown type name 'Node_GENERATED'. For this I'm proposing this PR.

@jsoysouvanh
Copy link
Owner

Hello.

Thank you for your contribution, I'm a bit busy right now but will look into it ASAP.

@Flone-dnb
Copy link
Author

I've fixed tests target compilation, I had to remove Generated directory so that it will be regenerated using the new generator.

Copy link
Owner

@jsoysouvanh jsoysouvanh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution.
I have addressed a few comments for the nomenclature consistency.

I still have mixed feelings about having the canonical type name at the variable level to be honest though.
From a purely logical point of view, the data should be at the Type level, but in that case the canonical name may or may not be filled: if the type is used for a reflected field/variable or method/function parameter/returned type within the same translation unit, the type canonical name will be valid, otherwise it will stay empty (and let's be honest, this is a huge problem).

I do not have any better idea for now to have this information consistently at the Type level, but I will think about it.

By the way, is it possible for you to modify this pull request to target the dev branch instead of master? I usually have everything on dev and merge to master only for new releases, plus it allows to have the CI run before moving to master.

@Flone-dnb
Copy link
Author

The whole point of this PR is do get type information for non-reflected types, but because Type can incorrect for non-reflected types (for example matching std::string and std::vector will be true) I'm adding this functionality to variables instead of types. Although we can 100% work on improving this and eventually move this to the Type but right now this will solve my issue and allow me to continue development on my project that uses Refureku.

I will work on requested changes and will change the target branch to dev.

Also, because I see lots of code-style mistakes that I made, have you though about using clang-format and/or clang-tidy for code-style? With them developers don't need to care about code-style because clang tools will do all of the formatting automatically (for example, on Ctrl+S press and/or in CI).

@Flone-dnb Flone-dnb changed the base branch from master to dev September 2, 2022 14:19
@Flone-dnb
Copy link
Author

I consider this PR done. Although I also want you to merge my other PR.

@jsoysouvanh
Copy link
Owner

The whole point of this PR is do get type information for non-reflected types

I get your point here, but it sounds off in the first place wanting to get reflection data from an unreflected class.
If you want to get reflection data, you should reflect your class in the first place, and it's a design decision on your side not wanting to do so.

I will merge this to dev and think about an optimal solution before merging to master. Having these changes pushed to master and then modified afterwards will break the library API/ABI which I want to avoid.
I should be able to work with your forked version until then.

have you though about using clang-format and/or clang-tidy for code-style?

I know it exists but have never taken the time to look into it yet, will definitely have to do so if it can handle all code-style for us. I wonder how far it can go.

Here is why I've decided to do this:
i've tried creating a custom type T that inherits from `rfk::Object` and
storing it in as a field of some other type. This caused a parsing
error saying that T is abstract. I've noticed that `rfk::Object`'s
`getArchetype()` function is pure virtual and it's implemented
in the generated files, but since on parsing step we don't have
anything generated this causes the parser to show this error. To avoid
this issue I've added a default implementation for `getArchetype()`
that just returns a class with the name `NULL` and size of `int`. Since
all generated files implement `getArchetype()` I don't think this
commit will make any difference to other code.
Running the new parsing that fails on parsing errors, some test
files don't include stuff that they use.
Running the new parsing that fails on parsing errors, some test
files don't include stuff that they use.
I've added the `shouldFailCodeGenerationOnClangErrors` parameter
to the `RefurekuTestsSettings.toml` with the value `false`.
I've added the `shouldFailCodeGenerationOnClangErrors` parameter to
the `RefurekuSettings.toml` file with the value `false`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants