modelsbuilder / ModelsBuilder.Original

The Community Models Builder for Umbraco
MIT License
114 stars 49 forks source link

CustomTool hangs in VS2019 #210

Closed zpqrtbnk closed 5 years ago

zpqrtbnk commented 5 years ago

See #199 - in some cases, the custom tool can hang.

Reproduced with a simple solution that @FransdeJong shared - contains two projects, on 1 project (created by UaaS.cmd) the tool hangs, on 1 project (created in VS) the tool works.

Now to figure what is causing this, and whether the problems comes from MB or UaaS...

FransdeJong commented 5 years ago

@hfloyd did you start the project with a beta UaaS tool?

zpqrtbnk commented 5 years ago

@FransdeJong in our tests... the YourProject.Core project, created by UaaS.cmd, is a <Project Sdk="Microsoft.NET.Sdk"> project type, whereas the YourProject.Test project, which we created manually in Visual Studio, is a <Project ToolsVersion="15.0"> project type.

There seem to be some problems with single file generators (ie IVsSingleFileGenerator, the interface we implement to provide the custom tool) and VS2019 and NET.Sdk projects. Almost looks like they wanted to dig custom tools entirely at one point. Digging into it now.

zpqrtbnk commented 5 years ago

Ah. So, the APIs that Visual Studio provides to add/remove files to/from a project, just don't work with NET.Sdk projects. Need to modify the raw Xml of the project file, it seems. Working on it..

FransdeJong commented 5 years ago

Is it worth it? Or can we convert the project to ToolsVersion="15.0"? If a easy conversion is possible than it seems unnecessary since it affects only a few people?

zpqrtbnk commented 5 years ago

Well, the problem will happen one day anyways, so I'd rather fix it + have the fix in MB not in UaaS.

FransdeJong commented 5 years ago

True.

zpqrtbnk commented 5 years ago

Hey. Want to try this VSIX: Umbraco.ModelsBuilder.CustomTool-8.1.1.vsix.zip ? By my tests, it works both on traditional (ToolsVersion...) projects and Net.Sdk projects. If it works for you too, I'll upload to the market place.

FransdeJong commented 5 years ago

I tried it and it works in both projects here as well. It looks like the Net.Sdk project is twice as fast to.

By the way I tested:

hfloyd commented 5 years ago

Awesome work, @zpqrtbnk ! I was able to install the updated VSIX with no issues. I moved my Models files back into my original ".Core" project and ran it - no errors, no hanging! :-) #H5YR

hfloyd commented 5 years ago

Well, I might have written too soon in regards to "no errors".

Though the "Output" window shows:

UmbracoModelsBuilder: Starting v8.1.1 7/17/2019 3:18:47 PM.
UmbracoModelsBuilder: Done.

The "Error List" window includes this one:

Error Custom tool UmbracoModelsBuilder failed to produce an output for input file 'Models\ContentTypes\_ModelBuilder.cs' but did not log a specific error.

referencing my MB "config" file (\Models\ContentTypes_ModelBuilder.cs)

The good news is that it actually DID work - my new Doctypes and properties are reflected in the .generated.cs files. So, I'm not sure why the error is getting displayed.

(This is in Visual Studio 2017)

zpqrtbnk commented 5 years ago

Ah well. There is no need to produce an output, ie to generate anything, corresponding to the "config" file _ModelBuilder.cs, so I have simplified things by returning nothing. And, everything works, but I had not paid attention to the fact that it would log an error in the list.

Going to revert that change to generate something, again. Stay tuned.

zpqrtbnk commented 5 years ago

Want to try Umbraco.ModelsBuilder.CustomTool-8.1.2.vsix.zip ? Same thing, but generates the dummy file again, so there should not be errors anymore. Let me know.

FransdeJong commented 5 years ago

The generation still goes well but:

The previous version with the error was more user friendly in a way.

zpqrtbnk commented 5 years ago

right - i hoped it would "just" work - working on it

FransdeJong commented 5 years ago

right - i hoped it would "just" work - working on it

We have the same coding style I see :D

zpqrtbnk commented 5 years ago

OK, this was interesting. Traditional custom tools implement a "Visual Studio Single File Generator" and then hack the generator to, in fact, generate more than one file. Turns out this leads to all sorts of problems when supporting both old-style "ToolsVersion" projects, and new-style "Net.Sdk" projects.

So... I want to move from using a "File Generator" to a proper "Visual Studio Command". What this means is:

And it should be way more robust, and easier to maintain.

Want to test? Umbraco.ModelsBuilder.CustomTool-8.1.3.vsix.zip

FransdeJong commented 5 years ago

In the old project it works great.

In the Net.Sdk project it fails with following error:

UmbracoModelsBuilder: UmbracoModelsBuilder failed to generate code: Exception: Response status code does not indicate success (InternalServerError)
{"Message":"An error has occurred.","ExceptionMessage":"{ expected","ExceptionType":"Umbraco.ModelsBuilder.Building.CompilerException","StackTrace":"   at Umbraco.ModelsBuilder.Building.Compiler.ThrowExceptionFromDiagnostic(String path, String code, Diagnostic diagnostic)\r\n   at Umbraco.ModelsBuilder.Building.Compiler.<>c__DisplayClass14_0.<GetCompilation>b__0(KeyValuePair`2 x)\r\n   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()\r\n   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)\r\n   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)\r\n   at Umbraco.ModelsBuilder.Building.Compiler.GetCompilation(String assemblyName, IDictionary`2 files, SyntaxTree[]& trees)\r\n   at Umbraco.ModelsBuilder.Building.Builder.PrepareAmbiguousSymbols()\r\n   at Umbraco.ModelsBuilder.Building.Builder.IsAmbiguousSymbol(String symbol, String match)\r\n   at Umbraco.ModelsBuilder.Building.TextBuilder.WriteNonGenericClrType(StringBuilder sb, String s)\r\n   at Umbraco.ModelsBuilder.Building.TextBuilder.WriteClrType(StringBuilder sb, String type)\r\n   at Umbraco.ModelsBuilder.Building.TextBuilder.WriteInterfaceProperty(StringBuilder sb, PropertyModel property)\r\n   at Umbraco.ModelsBuilder.Building.TextBuilder.WriteContentType(StringBuilder sb, TypeModel type)\r\n   at Umbraco.ModelsBuilder.Building.TextBuilder.Generate(StringBuilder sb, TypeModel typeModel)\r\n   at Umbraco.ModelsBuilder.Api.ApiHelper.GetModels(UmbracoServices umbracoServices, String modelsNamespace, IDictionary`2 files)\r\n   at Umbraco.ModelsBuilder.Api.ModelsBuilderApiController.GetModels(GetModelsData data)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()"}
UmbracoModelsBuilder:    at Umbraco.ModelsBuilder.Api.ApiClient.EnsureSuccess(HttpResponseMessage result)
   at Umbraco.ModelsBuilder.Api.ApiClient.GetModels(Dictionary`2 ourFiles, String modelsNamespace)
   at Umbraco.ModelsBuilder.CustomTool.Generator.TryGenerate(ProjectItem sourceItem)
   at Umbraco.ModelsBuilder.CustomTool.Generator.Generate(AsyncPackage package, ProjectItem sourceItem)

I had this error before in V7 projects when using IPublishedContent as model somewhere but I cant find something like that in this project. Also the previous versions worked so let me know if you want me to test something specific.

zpqrtbnk commented 5 years ago

Cause: the models.mb file was in a directory named "New Models" which we turned into a namespace "New Models" which is not a valid C# namespace. Need to use the same (or similar) logic Visual Studio uses to derive namespaces from folder names.

Want to test? Umbraco.ModelsBuilder.CustomTool-8.1.4.vsix.zip

zpqrtbnk commented 5 years ago

And then... with NET.Sdk projects, there's some race conditions in the Solution Explorer where files appear un-nested and then nested, or even remain un-nested. Trying to fix.

Want to test? Umbraco.ModelsBuilder.CustomTool-8.1.5.vsix.zip

FransdeJong commented 5 years ago

I tested this version and it works great in the standard and the old project. No more unnested models. Great work Stephan!!

zpqrtbnk commented 5 years ago

Fixed in the new Visual Studio Extension which replaces the old Visual Studio Custom Tool, read this blog post for details. Closing.

FransdeJong commented 5 years ago

It should be possible to put them in a cs file like before.

And the question to this answer disappeared...

hfloyd commented 5 years ago

Awesome work, @zpqrtbnk ! Thanks for your ongoing dedication to this tool. :-)

hfloyd commented 5 years ago

It should be possible to put them in a cs file like before.

And the question to this answer disappeared...

Haha! Yes, sorry about that - I had left this page open from yesterday and hadn't refreshed for Stephan's comment about the blog post - until I posted my question. I realized that all questions were answered in the Blog and thought to hide my mistake - but you, sir are way too quick for me! :-)