madskristensen / RainbowBraces

A Visual Studio extension
Apache License 2.0
133 stars 7 forks source link

not support angle brackets for c++.png #77

Open 1821746019 opened 1 year ago

1821746019 commented 1 year ago

Describe the bug not support colorizing angle brackets for c++,but xml is supported To Reproduce Steps to reproduce the behavior: 1.create a .h/.cpp/.ixx/.cppm file. 2.paste:

template <typename Ret, typename Func, typename... Args,
                      typename = enable_if_t<is_invocable_v<Func, Args...> &&
                          (/*is_convertible_v<invoke_result_t<Func, Args...>, Ret>*/1 || is_same_v<Ret, nullptr_t>)>>

template <typename... Args>
void LogDBG(Args&&... args)
{
    std::cout << "\033[0;95m[LogDBG]: \033[0m";
    ((std::cout << args << " "), ...);
    std::cout << std::endl;
}

Expected behavior colorizing any angle bracket normally. Screenshots not support angle brackets for c++ not support angle brackets for c++_2 the version of the vs

but the xml is supported+the version of the extension Additional context I am eager to see this bug repaired.It is uncomfortable to see the bracket with no color. Waiting for your good news

lordfanger commented 1 year ago

Hi, do you program a lot in C++? I've looked at it and for me it is simple 'Operator', possibly the same as '<' less then and '>' greater then operator or maybe something another. I can try to match 'Operator' but remove any 'cppOperator' (should be classical operators) but I'm not sure if it will not mark something unwanted to colorizable. Would you mind to make it opt-in and test it?

#include <iostrea> should be colorizable by default :)

1821746019 commented 1 year ago

Hi, do you program a lot in C++? I've looked at it and for me it is simple 'Operator', possibly the same as '<' less then and '>' greater then operator or maybe something another. I can try to match 'Operator' but remove any 'cppOperator' (should be classical operators) but I'm not sure if it will not mark something unwanted to colorizable. Would you mind to make it opt-in and test it?

#include <iostrea> should be colorizable by default :)

Hello, Yes, I use C++ a lot. However,

template <typename... Args>

the angle brackets are used to surround the type args of the template and not the simple 'Operator' as you might think, and implementing it might require much effort if you're not familiar with C++ .

Maybe you can create a 'develop' branch, and I would be happy to test it. Hopefully, the following code and its comments can provide assistance to your development:

#include <functional>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;

//template class or template func has 'template <...>'('...' are type Args of the template) above.
template <typename T> //args of the template arg surrounded with  angle brackets
class TClass
{
    T value_;

public:
    TClass(T value)
    {
        value_ = value;
    }

    friend ostream& operator<<(ostream& os, const TClass& t_class)
    {
        os << t_class.value_ << endl;
        return os;
    }
};

template <typename T> //args of the template arg surrounded with  angle brackets
void TFunc(T arg)
{
    //'<<','>>'is stream operator here;
    stringstream ss;
    ss << arg;
    string result;
    ss >> result;
    cout << "result is " << result << endl;
}

template <typename... Ts>
using a2t = tuple<Ts...>; //tuple is a template class of the STL

using namespace std;

class Async
{
    //shared_ptr is a template class
    shared_ptr<bool> p_is_finish_ = make_shared<bool>(false);

public:
    //here are 4 template func,there arg a constructor.

    //`enable_if_t`,`is_invocable_v`,`is_convertible_v`,`invoke_result_t` are template func
    template <typename Ret, typename Func, typename... Args,
              typename = enable_if_t<is_invocable_v<Func, Args...> &&
                  (is_convertible_v<invoke_result_t<Func, Args...>, Ret> || is_same_v<Ret, nullptr_t>)>>
    Async(Ret&& ret, Func&& func, tuple<Args...>&& args); //tuple is a template class of the STL

    template <typename Func, typename... Args>
    Async(Func&& func, tuple<Args...>&& args);

    template <typename Ret, typename Func, typename... Args,
              typename = enable_if_t<is_invocable_v<Func, Args...> &&
                  (is_convertible_v<invoke_result_t<Func, Args...>, Ret> || is_same_v<Ret, nullptr_t>)>>
    Async(Ret&& ret, Func&& func, tuple<Args...>&& args,
          const double max_exe_secs, const function<void()> post_process = nullptr);
    //function is a template class of the STL

    template <typename Func, typename... Args>
    Async(Func&& func, tuple<Args...>&& args, const double max_exe_secs,
          const function<void()> post_process = nullptr);
};

int main()
{

    //briefly,when "template",class, func are follow with '<>' and with many type split with ',' in '<>',it can be inferred that '<>' are used to surround the type Args.
    //When variables or literal are follow with '<' or '>',if can be inferred that '<' or '>' are simple operator.
    TClass<double> t_class(0);
    TFunc(1); //T as the type of the arg of the TFunc can be automatically deduced to int here,
    TFunc<double>(1); //manually specify T is double
    //equally
    TFunc   <double> (1); //manually specify T is double

    Async async<void, void(*)(int), tuple<int>>(async, a2t(1));
    //vector is a template class need template arg which surrounded with angle brackets like TClass
    std::vector<std::vector<int>> matrix{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};
    std::vector<std::vector<std::vector<int>>> cubic{
        {{0, 1}, {1}, {2}},
        {{0, 1}, {1}, {2}},
        {{0, 1}, {1}, {2}}
    };

    //'<'and'>' as operator
    if (1 < 2 && 2 > 3);

    return 0;
}
lordfanger commented 1 year ago

Install new version 1.0.111+ and set this flag to True and you can test it. image

Thank you for source code. I know what C++ templates are but I don't actively work in C++ for about 6 years so I can't test it myself. The RainbowBraces extension use ITaggers which tags part of source code to be later colorized by Visual Studio. (keywords are blue, methods are light blue etc) And it looks like C++ tagger is tagging template '<' and classic '<' with the same classification tag. It is impossible for this extension to parse the the .cpp file on its own. The C++ language is sooo complex. But maybe there will be some other ways we can rely on.

1821746019 commented 1 year ago

OK. I install version 1.0.112 and test it. Here are the results and I mark some bugs in the second picture. result bugs

Suddenly I have a good idea. Is it possible to for the extension to use the feature finding corresponding bracket of the visual studio?

find corresponding bracket

lordfanger commented 1 year ago

I see, I did some rework based on classifications of next and previous tags. The supplied file looks good to me, but I see some errors, maybe some library is missing or what. :D When Mad merges it, you can try.

That feature maybe help. But I don't know how to invoke it, whether I can invoke it safely (without interference to GUI) and I'm not sure it will don't incur some performace hit (can be implemented to full scan whole file for every single pair). But I'll keep it in mind if my previous solution will fail unrecoverably.

1821746019 commented 1 year ago

ok. I cannot wait to try it.

1821746019 commented 1 year ago

@lordfanger

Good job, you kill a bug.

good_job,you kill a bug  png

But you make another bug, and there is still a bug waiting to be killed.

But you make another bug, and there is still a bug waiting to be killed

lordfanger commented 1 year ago

@1821746019 Is it better now?

1821746019 commented 1 year ago

Oh, yes! I try the new version just now. It becomes more reliable!

more reliable

There is one small flaw.

small flaw In the majority of cases, << represents the stream insertion operator in C++. This is because in C++ templates, < is always followed by at least a type name, so the occurrence of << is not possible. However, >> is different. For example,

    std::vector<std::vector<int>> matrix{{0, 1, 2, 3}, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }};
    std::vector<std::vector<std::vector<int>>> cubic{
        {{0, 1}, { 1 }, { 2 }},
        { {0, 1}, {1}, {2} },
        { {0, 1}, {1}, {2} }
    };

Hope that this can help you.

lordfanger commented 1 year ago

I know. It was one of my fixes to exclude any "<<" or more from possible colorizable tags.

These cyanish color is not from this extension. At least not in my test suite. They are from C++ Operator Functions. image

1821746019 commented 1 year ago

I got it. It must be the bug of vs.

bug of vs

In addition, I see that you test the code I provided above by yourself. Please ignore the Async async<void, void(*)(int), tuple<int>>(async, a2t(1)); in main, which was my mistake.

Because <> is not allowed after variables . If I want to specify template parameters when invoking constructor, I should use another way.

not allow after the variable succeed to compile

1821746019 commented 1 year ago

Now the extension behaves fine. If I find any other bugs, I'll report them. Thank you.

1821746019 commented 1 year ago

@lordfanger I found one another bug. colorize_bug colorize_bug (2)

lordfanger commented 1 year ago

Is '!' only allowed operator there? Or there can be another?

1821746019 commented 1 year ago

In <> of the c++ template, value is also allowed. Here, std::is_same_v will return a bool, so we can use ! before it.

1821746019 commented 1 year ago

In addition, I found other bugs when use the concept of c++ 20. colorize bug

lordfanger commented 1 year ago

Thank you for reports. Possible fix PR is on the way.

1821746019 commented 1 year ago

@lordfanger uTools_1691797708286 uTools_1691797749912

                    for (int i = 0; i < ui->listWidget_dll_paths->count(); ++i)
                    {
                        if (i < ui->listWidget_dll_paths->count())
                        {
                        }
                        auto item = ui->listWidget_dll_paths->item(i);
                        if (item->data(Qt::UserRole).toString() == file_path)
                        {
                            result = true;
                            break;
                        }
                    }
#include <windows.h>
#include <detours.h>
#include <unordered_map>
#include <fstream>
#include <string>
using namespace std;
export
{
    class Hooker
    {
        unordered_map<PVOID*, PVOID> hook_map_;

        Hooker(const unordered_map<PVOID*, PVOID>& hook_map = {}): hook_map_((hook_map))
        {
        }

    public:
        static Hooker& instance()
        {
            static Hooker hooker;
            return hooker;
        }

        void setHook()
        {
            consolePrint("setting hook\n");
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            for (auto& e : hook_map_)
            {
                DetourAttach(e.first, e.second);
            }
            DetourTransactionCommit();
            consolePrint("finished setting hook\n");
        }

        void unHook()
        {
            consolePrint("start to RemoveHook\n");
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            for (auto& e : hook_map_)
            {
                DetourDetach((LPVOID*)&e.first, e.second);
            }
            DetourTransactionCommit();
            consolePrint("RemoveHook finish.\n");
        }
    };
}

template <typename T>
concept StringOrWString = std::is_same_v<T, std::string> || std::is_same_v<T, std::wstring>;

template <StringOrWString T>
T NewPath(const T& raw)
{
    T ret;
    vector<int> tmp;
    // TO DO:

    return ret;
}
lordfanger commented 1 year ago

Thank you, on first try I saw only a few uncolored. Then after I typed a whitespace on first line all were colorized. Can you try it too? I'll fix it anyway, but I want to know it the problem is with cache or colorization logic.

1821746019 commented 1 year ago

I am suspecting if the bugs of the experimental C++20 module feature in Visual Studio are causing the angle bracket to be uncolorized.

no use of c++20 module

no use of module

import essential module.

import essential module

I also add whitespace to avoid the influences of cache. I am not using modules in this file, so it might be the bugs of the extension.

uTools_1692064848940

lordfanger commented 1 year ago

I tried to set experimental C++20 module feature too and still see it colorized.

image

But I don't have <detours.h> so there are some errors. Not sure if it can be the problem. I'm trying to find some more data available from Visual Studio internals. But it takes some time to crunch VS codebase.

1821746019 commented 1 year ago

But you will not see the bugs if you do not import modules. The IntelliSense for C++20 module of VS is immature and often makes my variables colorized abnormally, so I tend to think it is the fault of VS.

1821746019 commented 1 year ago

Just see the color of the variables num; uTools_1692197896708 uTools_1692198024074

1821746019 commented 1 year ago

bugs uTools_1693482323241 @lordfanger help

1821746019 commented 1 year ago

bugs break out! uTools_1693482764887

lordfanger commented 1 year ago

I know about that. Sometimes it happens, I'm not sure why, but I'll have to rewrite a lot of the code. Refresh the colors should work or close/reopen file should work. Or it happens very frequently?

1821746019 commented 1 year ago

This is a rare occurrence. After I reloaded the project, it returned to normal. uTools_1693531419334