-
Notifications
You must be signed in to change notification settings - Fork 244
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
Refine the client-namespace-conflict
diagnostic
#6161
base: main
Are you sure you want to change the base?
Refine the client-namespace-conflict
diagnostic
#6161
Conversation
694d17a
to
07c774f
Compare
API change check API changes are not detected in this pull request. |
…ype deserialization, which might be incorrect. Will change it later
private const string namespaceConflictCode = "client-namespace-conflict"; | ||
|
||
private string? _namespace; | ||
protected override string BuildNamespace() => _namespace ??= BuildNamespaceCore(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method is called multiple times - but we expect it should always return the same result, therefore I added the cache here.
If this is called multiple times, the diagnostic would be reported multiple times which is quite annoying
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this called multiple times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, twice:
first time here:
Line 113 in 134f7e7
CustomCodeView?.BuildNamespace() ?? BuildNamespace(), |
second time here:
Line 38 in 134f7e7
=> CodeModelPlugin.Instance.SourceInputModel.FindForType(BuildNamespace(), BuildName()); |
we cannot change the second invocation to Namespace
, because it would cause infinite invocation of this method.
Therefore I think we cannot actually resolve it
|
||
private Emitter() | ||
internal Emitter() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changing to internal because with the singleton pattern, the emitter would be disposed when one test case is done, and the stream would be disposed and we cannot get things out of it then.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/EmitterRpc/Emitter.cs
Outdated
Show resolved
Hide resolved
/// <param name="left">the first namespace</param> | ||
/// <param name="right">the second namespace</param> | ||
/// <returns></returns> | ||
public static bool IsLastNamespaceSegmentTheSame(string left, string right) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I introduce this method to verify if the namespace has been changed in one client
I added tests for this to verify it is working properly.
@@ -46,6 +47,7 @@ public CodeModelPlugin(GeneratorContext context) | |||
Configuration = context.Configuration; | |||
_inputLibrary = new InputLibrary(Configuration.OutputDirectory); | |||
TypeFactory = new TypeFactory(); | |||
Emitter = null!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we will inject a value for this property later after the plugin was loaded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should throw from the getter instead of doing this. Similar to what we do for other non-nullable properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure let me change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#6161 (comment)
I changed this so that the emitter could be initialized here.
} | ||
|
||
public static Emitter Instance => _emitter ??= new Emitter(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the singleton pattern was messing things up in our test cases because it might dispose the stream prematurely
therefore I decide to remove the singleton pattern here, and when we load the plugin, we inject the constructed instance in main into the CodeModelPlugin
.
We have using
statement in the Main method therefore this emitter instance would only be dispose when the program exits.
@@ -69,6 +70,8 @@ public static Mock<CodeModelPlugin> LoadMockPlugin( | |||
// initialize the singleton instance of the plugin | |||
var mockPlugin = new Mock<CodeModelPlugin>(new GeneratorContext(Configuration.Load(configFilePath, configuration))) { CallBase = true }; | |||
|
|||
mockPlugin.Setup(p => p.Emitter).Returns(new Emitter(Console.OpenStandardOutput())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not add a hook here so that we could mock it in our UT - but if in the future we need to check something, we could do it here.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/perf/PluginInitializer.cs
Outdated
Show resolved
Hide resolved
|
||
namespace Microsoft.TypeSpec.Generator | ||
{ | ||
internal class PluginHandler | ||
{ | ||
public void LoadPlugin(CommandLineOptions options) | ||
public void LoadPlugin(Emitter emitter, CommandLineOptions options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need the emitter param?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this comment and I have changed this back
@@ -30,6 +31,7 @@ internal void SelectPlugin(CommandLineOptions options) | |||
{ | |||
CodeModelPlugin.Instance = plugin.Value; | |||
CodeModelPlugin.Instance.IsNewProject = options.IsNewProject; | |||
CodeModelPlugin.Instance.Emitter = emitter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just construct the emitter here, and call Dispose on the instance from Program.cs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously Program
needs this emitter to write debug information when we attach the debugger.
I think it should be fine if we just simply write the information into stderr - normal users would not come across it.
Now the emitter has been changed to initialize inside the CodeModelPlugin
- and Program disposes it if it is still there.
Fixes Azure/autorest.csharp#5241
I removed the report diagnostic in our emitter - because not every generator would have this issue
and move the diagnostic reporting into our C# generator, when we build the namespace for a client type.
I also added a few test cases for the
Emitter
class in our C# generator, which leads to series of other changes about the disposing issue.