Skip to content

Conversation

@wjk
Copy link

@wjk wjk commented Oct 2, 2018

Title says it all, really. Have tested with the project attached below. The STR code-behind is generated containing both a string and non-string resource (a Bitmap, to be precise) and compiles successfully. Code is very messy, however; I would appreciate some advice on how it should be cleaned up. Thanks!

Relates to: #2221, dotnet/sdk#1782

msbuild_test.zip

radical and others added 7 commits December 19, 2016 10:18
Methods that used WinForms-specific resx BCL types have been #if'ed
out to throw NotImplementedException on .NET Core. They will be more
fully implemented in the next series of commits.
This helps work with non-string types in resx files.
@wjk
Copy link
Author

wjk commented Oct 2, 2018

Note that ResXFileRef resource entries won't be handled properly with the code in this PR. The generated property will reference the type ResXFileRef, not Stream, Bitmap, or whatever other type is correct in this case. A pointer on how to fix this will also be appreciated.

@wjk
Copy link
Author

wjk commented Oct 3, 2018

I think I've fixed ResXFileRef support, but I'm not certain.

@rainersigwald
Copy link
Member

@nguerrera and @Tanya-Solyanik, do you have thoughts about this approach of reimplementing some of the resx reading instead of (I assume until) we can wait to get System.Windows.Forms and a full ResXResourceReader? It seems like a fine approach to me.

while (!type.IsPublic)
{
type = type.BaseType;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me why this can be deleted. Won't it break existing uses?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It had to be deleted because I'm no longer operating on types. I am dealing with the full names of types as strings, because MSBuild might not have access to the types (such as Bitmap) that the user is placing in their resx file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that. I think we would have to leave the prior behavior on full-framework msbuild with more conditional compilation. :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I'm afraid so :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just my 2 cents, but I feel it would be really useful to have implementations of System.Resources.IResourceReader and System.Resources.IResourceWriter available to MSBuild and cross-platform (hopefully wrapped as a .netstandard package so it can fall through to the full framework or use a custom implementation etc.)
I believe that EF6 will need this as part of its porting.

@nguerrera
Copy link
Contributor

@rainersigwald I don't have a strong opinion. If the amount of code required is small (seems so here), I think it's reasonable to duplicate. Otherwise, I think we'd want to push the resx stuff down from System.Windows.Forms to base shared framework somewhere.

@wjk
Copy link
Author

wjk commented Oct 4, 2018

@nguerrera @rainersigwald In all honesty, this is still a very, very rough first draft. Any and all advice on how to improve this PR will be appreciated.

wjk added 2 commits October 5, 2018 17:00
Per PR review. I have tested this locally, and it works, but I
don't know it if meets compatibility requirements or not.
I had to add a reference to the ConfigurationManager package so that
the ConfigurationException thrown by the CodeDomProvider can be
properly handled. This in turn required that I bump the version of
the System.Security.Principal.Windows package.
Copy link

@iSazonov iSazonov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to see the PR. In PowerShell repo we use a workaround some years. I hope the PR will successfully finished.
I don't see xUnit tests so I'd consider shared code with WinForm too.

iSazonov and others added 5 commits November 13, 2018 09:59
Co-Authored-By: wjk <wjk011@gmail.com>
Co-Authored-By: wjk <wjk011@gmail.com>
Sometimes (such as in the test resx file I'm using), the strings used in the
resx file can be very long.

Note that I don't know how much this fix changes the doc comment generation behavior
from what it was before (if, indeed, it changed at all).
@wjk
Copy link
Author

wjk commented Nov 13, 2018

I think I've figured out the failing unit test. The problem is that the value returned by the IResourceReader here is null. If the value is null, then there is by definition no way to get its type. Unfortunately, as I understand it this resource should not be null in the first place. I don't know what's going on here.

@rainersigwald @nguerrera Could you (or whomever else has an idea) please chime in with some thoughts? I don't see a way to fix this test, but I may be missing something obvious. Thanks!

@wjk
Copy link
Author

wjk commented Nov 15, 2018

Could someone please help me out with the failing CI? I keep getting ~70 unit test failures, even after reverting the change I made in e45c285. All of these tests pass when I run them locally on my dev box. I am at my wits' end here, and I want to get this PR merged sooner rather than later so it can be ready for the Core 3.0 official preview.

@rainersigwald
Copy link
Member

I can reproduce some of the failures with build.cmd -test on my machine:

On full framework,

 Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.References.ReferencedAssemblySpecifiedUsingRelativePath
System.NullReferenceException : Object reference not set to an instance of an object.
   at Microsoft.Build.Tasks.ProcessResourceFiles.AddResource(ReaderInfo reader, String name, Object value, String inputFileName, Int32 lineNumber, Int32 linePosition, String customTypeName) in /_/src/Tasks/GenerateResource.cs:line 3774
   at Microsoft.Build.Tasks.ProcessResourceFiles.AddResource(ReaderInfo reader, String name, Object value, String inputFileName, String customTypeName) in /_/src/Tasks/GenerateResource.cs:line 3786
   at Microsoft.Build.Tasks.ProcessResourceFiles.ReadResources(ReaderInfo readerInfo, IResourceReader reader, String fileName) in /_/src/Tasks/GenerateResource.cs:line 3493
   at Microsoft.Build.Tasks.ProcessResourceFiles.ReadResources(String filename, Boolean shouldUseSourcePath, String outFileOrDir) in /_/src/Tasks/GenerateResource.cs:line 3044
   at Microsoft.Build.Tasks.ProcessResourceFiles.ProcessFile(String inFile, String outFileOrDir) in /_/src/Tasks/GenerateResource.cs:line 2625
   at Microsoft.Build.Tasks.ProcessResourceFiles.Run(TaskLoggingHelper log, ITaskItem[] assemblyFilesList, List`1 inputs, List`1 satelliteInputs, List`1 outputs, Boolean sourcePath, String language, String namespacename, String resourcesNamespace, String filename, String classname, Boolean publicClass, Boolean extractingResWFiles, String resWOutputDirectory) in /_/src/Tasks/GenerateResource.cs:line 2481
   at Microsoft.Build.Tasks.ProcessResourceFiles.Run(TaskLoggingHelper log, ITaskItem[] assemblyFilesList, List`1 inputs, List`1 satelliteInputs, List`1 outputs, Boolean sourcePath, String language, String namespacename, String resourcesNamespace, String filename, String classname, Boolean publicClass, Boolean extractingResWFiles, String resWOutputDirectory)
   at Microsoft.Build.Tasks.GenerateResource.Execute() in /_/src/Tasks/GenerateResource.cs:line 816
   at Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.References.ReferencedAssemblySpecifiedUsingRelativePath() in S:\msbuild\src\Tasks.UnitTests\GenerateResource_Tests.cs:line 2837
Output:
resgen.exe /r:bin\debug\ClassLibrary20.dll /compile C:\Users\raines\AppData\Local\Temp\nci4bpf2.qsd\1ee678c1eead440488532fd43f334547\MyStrings.resx,C:\Users\raines\AppData\Local\Temp\nci4bpf2.qsd\1ee678c1eead440488532fd43f334547\MyStrings.resources
Creating a separate AppDomain because of resource "Image1" of type "ClassLibrary20.Class1, ClassLibrary20, version=1.0.0.0, Culture=neutral, PublicKeyToken=null" in "C:\Users\raines\AppData\Local\Temp\nci4bpf2.qsd\1ee678c1eead440488532fd43f334547\MyStrings.resx" on line 43.
Processing resource file "C:\Users\raines\AppData\Local\Temp\nci4bpf2.qsd\1ee678c1eead440488532fd43f334547\MyStrings.resx" into "C:\Users\raines\AppData\Local\Temp\nci4bpf2.qsd\1ee678c1eead440488532fd43f334547\MyStrings.resources".

On core:

      <test name="Microsoft.Build.UnitTests.WriteCodeFragment_Tests.InvalidLanguage" type="Microsoft.Build.UnitTests.WriteCodeFragment_Tests" method="InvalidLanguage" time="0.0014599" result="Fail">
        <traits>
          <trait name="Category" value="mono-osx-failing" />
        </traits>
        <failure exception-type="System.CodeDom.Compiler.CodeDomProvider+ConfigurationErrorsException">
          <message><![CDATA[System.CodeDom.Compiler.CodeDomProvider+ConfigurationErrorsException : There is no CodeDom provider defined for the language.]]></message>
          <stack-trace><![CDATA[   at System.CodeDom.Compiler.CodeDomProvider.GetCompilerInfo(String language)
   at System.CodeDom.Compiler.CodeDomProvider.CreateProvider(String language)
   at Microsoft.Build.Tasks.WriteCodeFragment.GenerateCode(String& extension) in /_/src/Tasks/WriteCodeFragment.cs:line 140
   at Microsoft.Build.Tasks.WriteCodeFragment.Execute() in /_/src/Tasks/WriteCodeFragment.cs:line 84
   at Microsoft.Build.UnitTests.WriteCodeFragment_Tests.InvalidLanguage() in S:\msbuild\src\Tasks.UnitTests\WriteCodeFragment_Tests.cs:line 34]]></stack-trace>
        </failure>
      </test>

      <test name="Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.RequiredTransformations.STRWithResourcesNamespaceVB" type="Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.RequiredTransformations" method="STRWithResourcesNamespaceVB" time="0.0882194" result="Fail">
        <output><![CDATA[resgen.exe C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmpbedb2c14b77e4be3b605675e84a9533a.txt C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmpbedb2c14b77e4be3b605675e84a9533a.resources /str:VB,,,
Processing resource file "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmpbedb2c14b77e4be3b605675e84a9533a.txt" into "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmpbedb2c14b77e4be3b605675e84a9533a.resources".
Processing 4 resources from file "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmpbedb2c14b77e4be3b605675e84a9533a.txt".
Creating strongly typed resources class "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmpbedb2c14b77e4be3b605675e84a9533a.vb".
]]></output>
        <traits>
          <trait name="Category" value="mono-osx-failing" />
          <trait name="Category" value="mono-windows-failing" />
        </traits>
        <failure exception-type="Xunit.Sdk.TrueException">
          <message><![CDATA[Assert.True() Failure\r\nExpected: True\r\nActual:   False]]></message>
          <stack-trace><![CDATA[   at Microsoft.Build.UnitTests.GenerateResource_Tests.Utilities.AssertStateFileWasWritten(GenerateResource t) in S:\msbuild\src\Tasks.UnitTests\GenerateResource_Tests.cs:line 3245
   at Microsoft.Build.UnitTests.GenerateResource_Tests.Utilities.STRNamespaceTestHelper(String strLanguage, String resourcesNamespace, String classNamespace, ITestOutputHelper output) in S:\msbuild\src\Tasks.UnitTests\GenerateResource_Tests.cs:line 3631
   at Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.RequiredTransformations.STRWithResourcesNamespaceVB() in S:\msbuild\src\Tasks.UnitTests\GenerateResource_Tests.cs:line 1258]]></stack-trace>
        </failure>
      </test>

      <test name="Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.RequiredTransformations.STRWithResourcesNamespaceAndSTRNamespaceCS" type="Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.RequiredTransformations" method="STRWithResourcesNamespaceAndSTRNamespaceCS" time="0.0226973" result="Fail">
        <output><![CDATA[resgen.exe C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmp0dc3042b713248e1b7681137c6c57fa7.txt C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmp0dc3042b713248e1b7681137c6c57fa7.resources /str:CSharp,MySTClassNamespace,,
Processing resource file "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmp0dc3042b713248e1b7681137c6c57fa7.txt" into "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmp0dc3042b713248e1b7681137c6c57fa7.resources".
Processing 4 resources from file "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmp0dc3042b713248e1b7681137c6c57fa7.txt".
Creating strongly typed resources class "C:\Users\raines\AppData\Local\Temp\ogfuf5ii.wzw\tmp0dc3042b713248e1b7681137c6c57fa7.cs".
]]></output>
        <traits>
          <trait name="Category" value="mono-osx-failing" />
          <trait name="Category" value="mono-windows-failing" />
        </traits>
        <failure exception-type="Xunit.Sdk.TrueException">
          <message><![CDATA[Assert.True() Failure\r\nExpected: True\r\nActual:   False]]></message>
          <stack-trace><![CDATA[   at Microsoft.Build.UnitTests.GenerateResource_Tests.Utilities.AssertStateFileWasWritten(GenerateResource t) in S:\msbuild\src\Tasks.UnitTests\GenerateResource_Tests.cs:line 3245
   at Microsoft.Build.UnitTests.GenerateResource_Tests.Utilities.STRNamespaceTestHelper(String strLanguage, String resourcesNamespace, String classNamespace, ITestOutputHelper output) in S:\msbuild\src\Tasks.UnitTests\GenerateResource_Tests.cs:line 3631
   at Microsoft.Build.UnitTests.GenerateResource_Tests.InProc.RequiredTransformations.STRWithResourcesNamespaceAndSTRNamespaceCS() in S:\msbuild\src\Tasks.UnitTests\GenerateResource_Tests.cs:line 1271]]></stack-trace>
        </failure>
      </test>

And others. How are you running the tests?

@wjk
Copy link
Author

wjk commented Nov 15, 2018

@rainersigwald I just run them using the VS Test Explorer. I did this so I could use the debugger to investigate the cause of the failures. Is this an incorrect methodology?

Apparently, this was not the cause of the excessive
test failures being seen in CI.

This reverts commit e45c285.
@wjk
Copy link
Author

wjk commented Nov 15, 2018

As it turns out, using the VS Test Explorer was incorrect methodology. It runs the tests under the full-framework runtime, while the tests were failing only when run under the .NET Core runtime. Will have some fixes pushed up momentarily.

@wjk
Copy link
Author

wjk commented Dec 2, 2018

@rainersigwald @nguerrera It's been over two weeks since I got the tests passing; I would appreciate PR review so we can get this merged soon. Thanks! 😄

{
provider = CodeDomProvider.CreateProvider(stronglyTypedLanguage);
}
#if FEATURE_SYSTEM_CONFIGURATION
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elsewhere you still have configuration #if'ed out. Does CodeDomProvider actually throw configuration exception on .NET Core? I think we should avoid adding a dependency on it if it's not needed.

{
provider = CodeDomProvider.CreateProvider(Language);
}
#if FEATURE_WINFORMS_RESX
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This is where it's still #if'ed out that I referenced in earlier comment)


return InternalCreate(resourceList, baseName, generatedCodeNamespace, resourcesNamespace, codeProvider, internalClass, out unmatchable);
#else
throw new NotImplementedException();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably have a better error message describing what isn't supported.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about MSBuild usage, but in CoreFX NotImplementedException is used when something is not implemented by design (such as, it needs to be overridden) and PlatformNotSupportedException when it's not relevant to the platform or not yet implemented there.

@nguerrera
Copy link
Contributor

In general, I still find it hard to follow the impact this will have on the full-framework case. Some work was done to retain the System.Type usage, but then in some places, there are still string comparison replacing type comparisons unconditionally in other places. I think I'd have an easier time reviewing if it were more obvious that this enables core without changing behavior on framework.

@wjk
Copy link
Author

wjk commented Dec 7, 2018

@nguerrera In all honesty, the string comparison was only implemented because, at the time, ResXResourceReader and friends were not available on Core. If there was any other way, I would have used it.

However, with WinForms open-sourced and ported to Core, I was planning on adding a copy of them into the Tasks project (to break the dependency on the Forms DLL; we can always remove them again later), getting rid of the string-related code, and enabling FEATURE_RESX_RESOURCE_READER globally. Sound good? Thanks!

@nguerrera
Copy link
Contributor

nguerrera commented Dec 7, 2018

I'm not sure because there are open questions about actively instantiating objects while reading resx. I have two things in mind: get away from that, but also don't changebreak the .net framework case. I'd have to look more closely at what ResxResourceReader does.

@rainersigwald
Copy link
Member

I'd have to look more closely at what ResxResourceReader does.

This is high on my agenda for next week, for reasons closely related to this PR.

@nguerrera
Copy link
Contributor

nguerrera commented Dec 7, 2018

This is high on my agenda for next week, for reasons closely related to this PR.

👍

@wjk, I would hold off on doing any big changes to this PR while @rainersigwald is looking into this.

@wjk
Copy link
Author

wjk commented Feb 3, 2019

@nguerrera @rainersigwald Any updates?

@bergmeister
Copy link

This feature would really be useful, thanks to the PR creator, I hope this gets merged downstream to the 2.2 SDK as well.

@bergmeister
Copy link

Any updates @nguerrera @rainersigwald ?

@rainersigwald rainersigwald added this to the .NET Core 3.0 milestone Mar 21, 2019
@wjk
Copy link
Author

wjk commented Jun 26, 2019

This PR has since been superseded by #4420. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants