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 ProgressToken constructor #688

Closed
wants to merge 1 commit into from
Closed

add ProgressToken constructor #688

wants to merge 1 commit into from

Conversation

ZacLN
Copy link
Contributor

@ZacLN ZacLN commented May 9, 2020

fixes #651 ?

@ZacLN ZacLN added the bug label May 9, 2020
@ZacLN ZacLN added this to the Current milestone May 9, 2020
@ZacLN ZacLN requested a review from davidanthoff May 9, 2020 08:52
@ZacLN ZacLN self-assigned this May 9, 2020
@ZacLN ZacLN added this to In progress in Current via automation May 9, 2020
@jipolanco
Copy link

It seems to work. But now that I think about it, isn't this type piracy? Since ProgressToken is just an alias for Union{Int, String}...

@ZacLN
Copy link
Contributor Author

ZacLN commented May 9, 2020

Yeah possibly, but who really owns a Union?

@jipolanco
Copy link

I'd say that, since we don't own any of the types in the Union, then we don't own the Union.

If we have the right to define a constructor for the Union, then any other module has the right to do the same, which is (as I understand it) what the concept of type piracy tries to avoid.

More concretely, this implementation could break if someone else decides to define their own constructor for the same Union.

@davidanthoff
Copy link
Member

Yeah, this seems kind of risky....

@ZacLN
Copy link
Contributor Author

ZacLN commented May 10, 2020

Probably right - I'll fix and add a check in StaticLint

@gdkrmr
Copy link

gdkrmr commented May 11, 2020

why not simply do progresstoken(x) = x instead of ProgressToken(x) = x, not super pretty, but avoids Type piracy. You could also make a struct:

struct ProgressToken
    token::Union{String, Int}
end

@matsievskiysv
Copy link

matsievskiysv commented May 12, 2020

Sorry for jumping in, but ProgressToken is used as a constructor only once in src/protocol/initialize.jl and it's not needed there. This will work just fine:

-    haskey(dict, "workDoneToken") ? ProgressToken(dict["workDoneToken"]) : missing)
+    haskey(dict, "workDoneToken") ? dict["workDoneToken"] : missing)

Also, there's a struct ProgressParams which was probably designed to hold this value but isn't used anywhere.

@ZacLN
Copy link
Contributor Author

ZacLN commented May 12, 2020

Sorry, I've not had time to have a proper look at this yet.

I'm pretty sure ProgressToken could be used during the construction of any struct defined with the @dict_readable macro (these represent possible incoming messages as part of the protocol).

@matsievskiysv
Copy link

I'm pretty sure ProgressToken could be used during the construction of any struct defined with the @dict_readable macro (these represent possible incoming messages as part of the protocol).

I've grepped project and found only this instance.
I also compiled LanguageServer with the patch above and it worked like a charm.

@ZacLN
Copy link
Contributor Author

ZacLN commented May 12, 2020

The macro mentioned above creates, for each struct it is used on, functions that convert a Dict to that struct where keys of the Dict match the fields of the struct. The datatype specified for each field is called is called on the matching Dict value, e.g.:

macroexpand(LanguageServer, :(
@dict_readable struct T 
    d::ProgressToken 
end))
-->
struct T
    d::ProgressToken
end
function T(dict::Dict)
    T(ProgressToken(dict["d"]))
end

So it's not only explicit calls to ProgressTokens constructor that need to be adjusted, but the whole body of auto-genned code.

Your fix above will work for now, but as soon as we start getting sent ProgressTokens in other contexts it will break. It's better to fix it broadly.

@gdkrmr
Copy link

gdkrmr commented May 13, 2020

The macro mentioned above creates, for each struct it is used on, functions that convert a Dict to that struct where keys of the Dict match the fields of the struct. The datatype specified for each field is called is called on the matching Dict value, e.g.:

Then you really should use

struct ProgressToken
    token::Union{String, Int}
end

@davidanthoff
Copy link
Member

What is the status with this? Should we first merge #701 and then revisit this?

@ghost
Copy link

ghost commented Jul 11, 2020

I just thought I'd mention I managed to get lsp-julia working without a hiccup by dropping in the progtoken branch and then editing InitializeParams as suggested. The progtoken branch did not work by itself. I'm on mac running 1.4.2. Thanks to the guys that solved this, it was driving me crazy.

@ordicker
Copy link

Could you share your init.el?

@ghost
Copy link

ghost commented Jul 11, 2020

My lsp-mode is installed manually because I was trying different versions when I was trying to get lsp-julia to work but I don't see why an elpa installed lsp-mode wouldn't work. Also, I had to edit lsp-julia.el to use the new LanguageServerInstance() syntax. That was throwing errors for me too.

my init.el

@aviatesk
Copy link
Member

aviatesk commented Aug 5, 2020

@julia-vscode/core bump ? (I got a report on this today in other place) I guess it's okay if we pirate the Union{Int,String} constructor since LanguageServer.jl isn't supposed to interact with user code ?

@non-Jedi
Copy link
Member

non-Jedi commented Aug 5, 2020

I think piracy is fine in an application, but I'd really prefer we continue thinking of LanguageServer.jl as a library/package so that people could use parts of it to build their own code analysis tools if desired. That said, it's unlikely to happen, so if the right fix for this is onerously difficult (involves special-casing a macro? I haven't dug in to see what the best fix would be), creating a method for a Union{Int,String} probably won't break things.

@aviatesk
Copy link
Member

aviatesk commented Aug 5, 2020

creating a method for a Union{Int,String} probably won't break things.

na, (::Type{Union{Int,String}})(x) = x is essentially same as Union{Int,String}(x) = x and so it pirates things.

@pfitzseb
Copy link
Member

pfitzseb commented Aug 5, 2020

So what's the reason for not making ProgressToken a struct again?

@aviatesk
Copy link
Member

aviatesk commented Aug 5, 2020

Guess we want to treat it as a value ?

pps = ProgressParams(...)
pps.token # want to get the actual value here ?

And overloading getproperty for every parent structs who own ProgressToken will be verbose.

@pfitzseb
Copy link
Member

pfitzseb commented Aug 5, 2020

Yeah, not sure how/in what contexts ProgressToken is used and whether defining a bunch of convert methods wouldn't be enough. I can take a more thorough at some point though.

@ZacLN
Copy link
Contributor Author

ZacLN commented Aug 24, 2020

If this instance of pirating is deemed unacceptable can we simply replace all fields that are typed by ::ProgressToken with ::Union{String,Int} # ProgressToken? I think the handwritten constructor for InitializeParams is the only instance where the Type is called

@pfitzseb
Copy link
Member

Sounds good to me.

@aviatesk
Copy link
Member

yeah good to me too

@pfitzseb pfitzseb closed this Aug 25, 2020
@davidanthoff davidanthoff deleted the progtoken branch August 28, 2020 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MethodError: no method matching Union{Int64, String}(::String)
9 participants