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

Use of EditorBrowsableState.Never leads language service to claim it's gone #720

Closed
AArnott opened this issue Dec 10, 2019 · 27 comments · Fixed by #37184 or #67466
Closed

Use of EditorBrowsableState.Never leads language service to claim it's gone #720

AArnott opened this issue Dec 10, 2019 · 27 comments · Fixed by #37184 or #67466
Labels
api-approved API was approved in API review, it can be implemented area-Meta
Milestone

Comments

@AArnott
Copy link
Contributor

AArnott commented Dec 10, 2019

Due to the Never flag used on a couple of these enum values:

public enum ComInterfaceType
{
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")]
InterfaceIsDual = 0,
InterfaceIsIUnknown = 1,
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")]
InterfaceIsIDispatch = 2,
InterfaceIsIInspectable = 3,
}

When coding against multiple frameworks, Roslyn claims the APIs are simply missing:

image

Can we get these Never settings to be changed to Advanced instead?

Desired API Changes

 public enum ComInterfaceType 
 { 
-    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] 
-    [System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")] 
     InterfaceIsDual = 0, 
     InterfaceIsIUnknown = 1, 
-    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] 
-    [System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")] 
     InterfaceIsIDispatch = 2, 
     InterfaceIsIInspectable = 3, 
 }
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Dec 10, 2019
@AArnott
Copy link
Contributor Author

AArnott commented Dec 10, 2019

CC: @AaronRobinsonMSFT

@danmoseley
Copy link
Member

@terrajobst

@terrajobst
Copy link
Member

terrajobst commented Dec 10, 2019

I have zero issues with changing the editor browsable state for these APIs. But before we're changing the APIs to accommodate tools I'd like to understand the IntelliSense behavior.

@jaredpar

Is this a side effect of how the combined language service works in multi-targeted projects? If so, can we fix this?

@jaredpar
Copy link
Member

@jasonmalinowski

@jasonmalinowski
Copy link
Member

The "this is only available on one side" logic is implemented by computing the list for both targets; it merges all the times together and if it didn't appear on one side or the other then the warning is given. You could imagine that we could instead merge and compute the warnings prior to throwing out the things for EditorBrowsableState.Never, although I'm not sure how much work that would take. I would have two things to think about:

  1. EditorBrowsableState.Never is the IDE's ultimate back compat nightmare: any time we change this, somebody else will complain instead. At this point, we don't touch it unless we have a really good reason to. This is something we'd have to consider carefully, and I could imagine somebody else might come up with a reason we simply can't change this.
  2. The IDE behavior looks like a feature here for other scenarios. I could totally imagine somebody having a multitargeted library they built that they're updating for .NET Core, and there's a corner of the library that they must deprecate -- say it's some corner that was something that isn't supported in .NET Core, and they don't really care to support it either. I could imagine them using [Obsolete] plus an EditorBrowsableState.Never as a way to say "in this target, this feature is no longer supported" so the consumer of a library could get a better error message that says "this is now dead, go use this other thing over here" rather than a generic "method doesn't exist" compiler error. Put another way, if in say .NET 42 you decided that .NET 43 was going to finally deprecate say InterfaceIsDual, would you wish for the current behavior?

@jasonmalinowski
Copy link
Member

@dpoeschl might also know more about the behavior here as well.

@terrajobst
Copy link
Member

The "this is only available on one side" logic is implemented by computing the list for both targets; it merges all the times together and if it didn't appear on one side or the other then the warning is given.

That's what I thought. I don't think the current behavior is desirable. You show a warning in IntelliSense that never materializes as a diagnostic when building. As this issue demonstrates, this is confusing because IntelliSense claims an API to be unavailable when in fact it is available but hidden. If the API is marked as EditorBrowsable.Never across all configured TFMs, then hiding the API entirely in the merged IntelliSense makes sense to me. But even in that case, the completion window wouldn't show a warning icon.

  1. EditorBrowsableState.Never is the IDE's ultimate back compat nightmare: any time we change this, somebody else will complain instead. At this point, we don't touch it unless we have a really good reason to. This is something we'd have to consider carefully, and I could imagine somebody else might come up with a reason we simply can't change this.

That's why I'd like to avoid having to change the API declarations.

  1. The IDE behavior looks like a feature here for other scenarios.

I don't buy the described scenario. If the person obsoletes the API for one TFM, then the consumer will get a warning when building for that TFM. Keep in mind that when people use multi-targeting they often do so because they need to support multiple versions of the same TFM. In that scenario you're often forced to call API that was obsoleted/hidden in a later TFM because the replacement isn't available in the earlier TFM. In that scenario, not showing me the API is the opposite of being helpful.

@AArnott
Copy link
Contributor Author

AArnott commented Dec 11, 2019

We have the ObsoleteAttribute API to mark things as deprecated. Making them "Never" visible is an extreme tool to use for obsoleting something. The irony of doing so on these particular enum values is that IDispatch is the default value. How can .NET Core deprecate the default setting? It's ironic that .NET Core hides the enum value that is default anyway, making it difficult to express the default explicitly. But not setting it at all (by omitting the InterfaceType attribute) doesn't get you closer to your goal because that too is the deprecated setting.

So what's the plan here? How can IDispatch even be deprecated to begin with?

@terrajobst
Copy link
Member

terrajobst commented Dec 11, 2019

I’m not sure why it’s marked as hidden. I’ll take a look tomorrow.

FWIW, I agree with you that In 99% of cases obsoletion and hiding shouldn’t be combined.

@jozefizso
Copy link

Fixing this will greatly improve the quality of IntelliSense we get when we develop Office Add-in and other COM interop code which we plan to target for .NET Framework and .NET Core.

@reflectronic
Copy link
Contributor

Are these even supposed to be deprecated? There is an issue about some COM features that mistakenly were marked obsolete.

@terrajobst
Copy link
Member

OK, I've created dotnet/roslyn#40370 to track the potential for changing how IntelliSense deals with hidden APIs. Now let's keep this thread focused on the why these particular APIs are hidden/obsoleted.

@AaronRobinsonMSFT
Copy link
Member

These APIs were marked hidden/obsolete when the original port to coreclr was made. At that time we had no COM support so it made sense. In 3.0, we have that support so they are technically still valid. Issue https://github.com/dotnet/corefx/issues/40376 was created based on my comments at https://github.com/dotnet/coreclr/issues/26207#issuecomment-522070936.

At a minimum these APIs shouldn't marked System.ComponentModel.EditorBrowsableState.Never and ideally, since it plays badly with code quality metrics, the ObsoleteAttribute should be removed.

@Dennis-Petrov
Copy link

Dennis-Petrov commented Jan 14, 2020

@AaronRobinsonMSFT , started to port our COM-object from NETfx to NETCore, got Support for IDispatch may be unavailable in future releases warning. Found this thread after a couple of hours of web search. Tons of posts which tells that NETCore 3+ has COM support, even the official docs tutorial, but nothing mentions IDispatch. So, if one wants to use late binding for NETCore 3+ COM-object from VBA, SAP ERP or something similar, it is valid to use ComInterfaceType.InterfaceIsDual, and it will work, isn't it?

@AaronRobinsonMSFT
Copy link
Member

@Dennis-Petrov IDispatch is supported and .NET Core does support scenarios involving VBA. There are some caveats however. Since there is no supported TlbExp tool for .NET Core, a Type Library will not be created by the runtime. This is simple to circumvent since the interface can be defined in IDL and a Type Library created using the MIDL compiler. The scenario is definitely not as direct as .NET Framework but all the IDispatch runtime support from .NET Framework is available in .NET Core.

See https://github.com/dotnet/core-setup/issues/7800 for an end-to-end with VBA and the current issues.

@Dennis-Petrov
Copy link

@AaronRobinsonMSFT , thanks a lot!

@AArnott
Copy link
Contributor Author

AArnott commented Jan 14, 2020

Since there is no supported TlbExp tool for .NET Core

@AaronRobinsonMSFT Why not just use tlbexp.exe from a .NET Framework targeted DLL? If you expect a DLL to have COM compatible types, wouldn't that assembly likely be readily targetable to net472 and then you can use the existing tools?

@Dennis-Petrov
Copy link

@AArnott, in my particular case COM object is just a thin legacy wrapper around large piece of functionality. It depends on number of NETStandard2.1/NETCore 3.1 libraries. Actually, absence of type library is a headache. I'm considering available options... Create IDL manually, compile it with MIDL compiler? How to register that TLB on target machine?

@AaronRobinsonMSFT
Copy link
Member

@AArnott That is a valid point. Since all that is needed is a TLB it is possible to simply take the .NET Framework DLL and generate the TLB to represent the contracts. The only caveat is the automatic generation of class interfaces, which is not supported in .NET Core and unlikely to be brought back. This reduces to the idea that if one defines all their interfaces in C# compiles for .NET Framework and then runs the assembly through TlbExp, the resulting TLB should have a contract that is projectable from both a .NET Framework and .NET Core COM server.

@terrajobst
Copy link
Member

@AaronRobinsonMSFT are you OK with these changes then?

 public enum ComInterfaceType 
 { 
-    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] 
-    [System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")] 
     InterfaceIsDual = 0, 
     InterfaceIsIUnknown = 1, 
-    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] 
-    [System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")] 
     InterfaceIsIDispatch = 2, 
     InterfaceIsIInspectable = 3, 
 }

@terrajobst terrajobst added api-needs-work API needs work before it is approved, it is NOT ready for implementation and removed api-ready-for-review labels Feb 14, 2020
@AaronRobinsonMSFT
Copy link
Member

@terrajobst Yep, that makes sense to me.

@stephentoub stephentoub added api-ready-for-review and removed api-needs-work API needs work before it is approved, it is NOT ready for implementation untriaged New issue has not been triaged by the area owner labels Feb 26, 2020
@clairernovotny
Copy link
Member

Ping? I just hit this with 5.0p4. ComEventInterface is also marked as obsolete when I don't believe it should be?

@stephentoub stephentoub added the blocking Marks issues that we want to fast track in order to unblock other important work label May 24, 2020
@terrajobst terrajobst added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review blocking Marks issues that we want to fast track in order to unblock other important work labels May 29, 2020
@terrajobst
Copy link
Member

terrajobst commented May 29, 2020

Video

Looks good as proposed

 public enum ComInterfaceType 
 { 
-    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] 
-    [System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")] 
     InterfaceIsDual = 0, 
     InterfaceIsIUnknown = 1, 
-    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] 
-    [System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")] 
     InterfaceIsIDispatch = 2, 
     InterfaceIsIInspectable = 3, 
 }

@AArnott
Copy link
Contributor Author

AArnott commented Apr 1, 2022

Reactivating because the proposed and accepted API change was made, then lost. See? The attributes are still there:

public enum ClassInterfaceType
{
None = 0,
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")]
AutoDispatch = 1,
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.ObsoleteAttribute("Support for IDispatch may be unavailable in future releases.")]
AutoDual = 2,
}

@AArnott AArnott reopened this Apr 1, 2022
@dotnet dotnet unlocked this conversation Apr 1, 2022
@AArnott
Copy link
Contributor Author

AArnott commented Apr 1, 2022

@AaronRobinsonMSFT Can you re-apply your change?

@AArnott
Copy link
Contributor Author

AArnott commented Apr 1, 2022

It's not just the language service discoverability issues. These attributes are leading to CS0618 warnings on legitimate code.

@AaronRobinsonMSFT
Copy link
Member

@AArnott That is a different API. This issue was for ComInterfaceType. It seems we missed updating ClassInterfaceType. I'll send out a new PR.

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Apr 1, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Apr 2, 2022
@dotnet dotnet locked as resolved and limited conversation to collaborators May 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-Meta
Projects
None yet