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

CustomTool hangs in VS2019 #210

Closed
zpqrtbnk opened this issue Jul 16, 2019 · 24 comments

Comments

@zpqrtbnk
Copy link
Owner

commented Jul 16, 2019

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

This comment has been minimized.

Copy link

commented Jul 16, 2019

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

@zpqrtbnk

This comment has been minimized.

Copy link
Owner Author

commented Jul 16, 2019

@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

This comment has been minimized.

Copy link
Owner Author

commented Jul 16, 2019

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

This comment has been minimized.

Copy link

commented Jul 16, 2019

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

This comment has been minimized.

Copy link
Owner Author

commented Jul 16, 2019

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

@FransdeJong

This comment has been minimized.

Copy link

commented Jul 16, 2019

True.

@zpqrtbnk

This comment has been minimized.

Copy link
Owner Author

commented Jul 17, 2019

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

This comment has been minimized.

Copy link

commented Jul 17, 2019

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:

  • generate
  • regenerate
  • add property and regenerate
  • remove property and regenerate.
@hfloyd

This comment has been minimized.

Copy link

commented Jul 17, 2019

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

This comment has been minimized.

Copy link

commented Jul 17, 2019

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

This comment has been minimized.

Copy link
Owner Author

commented Jul 18, 2019

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

This comment has been minimized.

Copy link
Owner Author

commented Jul 18, 2019

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

This comment has been minimized.

Copy link

commented Jul 18, 2019

The generation still goes well but:

  • I get a notification that the project has been modified outside of VS
  • the modelsbuilder.generated.cs is not nested under the class with the custom tool

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

@zpqrtbnk

This comment has been minimized.

Copy link
Owner Author

commented Jul 18, 2019

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

@FransdeJong

This comment has been minimized.

Copy link

commented Jul 18, 2019

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

We have the same coding style I see :D

@zpqrtbnk

This comment has been minimized.

Copy link
Owner Author

commented Jul 18, 2019

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:

  • You don't set a "custom tool" on a CSharp file anymore
  • Instead, you Add | New Item... then pick Visual C# Items | Umbraco and add an Umbraco Models placeholder, with a .md extension (the name does not matter, but the extension is important) - for instance, Models.md - the content of the file is, for now, of no importance
  • That placeholder will automatically have a Build Models command in its context menu. So, right-click and Build Models ... and models are generated and nicely nested under the placeholder, both in "ToolsVersion" projects and in "NET.Sdk" projects.

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

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

@FransdeJong

This comment has been minimized.

Copy link

commented Jul 18, 2019

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

This comment has been minimized.

Copy link
Owner Author

commented Jul 19, 2019

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

This comment has been minimized.

Copy link
Owner Author

commented Jul 19, 2019

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

This comment has been minimized.

Copy link

commented Jul 19, 2019

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

@zpqrtbnk

This comment has been minimized.

Copy link
Owner Author

commented Jul 19, 2019

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

@FransdeJong

This comment has been minimized.

Copy link

commented Jul 19, 2019

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

And the question to this answer disappeared...

@hfloyd

This comment has been minimized.

Copy link

commented Jul 19, 2019

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

@hfloyd

This comment has been minimized.

Copy link

commented Jul 19, 2019

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! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.