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

Unable to discover new string resource (or other xml defined resources) in Intellisense after building #1287

Closed
pjcollins opened this Issue Feb 8, 2018 · 12 comments

Comments

Projects
None yet
3 participants
@pjcollins
Member

pjcollins commented Feb 8, 2018

This issue appears to be a regression in d15-6, so I will be adding it to the 15.6 milestone. However, I am not sure if it is related to the managed resource parser changes that have been re-enabled there.

Steps to Reproduce

  1. Create a new Single-View Android App.
  2. Add a new string entry in Resources -> values -> Strings.xml, such as:
<string name="test">test</string>
  1. Open MainActivity.cs and confirm that you are unable to see Intellisense for Resource.String.test.
  2. Select Build -> Build solution
  3. Open MainActivity.cs and confirm that you are still unable to see Intellisense for Resource.String.test.

Expected Behavior

Newly added string and other xml resources can be discovered via Intellisense immediately after completing a build.

Actual Behavior

Intellisense does not work for a new string resource after building.

Version Information

VS 15.6 Preview 4:
https://gist.github.com/pjcollins/b8be35efd9b9eb0fb7e1355e74396fd2

Log File

Diagnostic build output:
https://gist.github.com/pjcollins/292e2acf118eaced6de4124aedf15254

@dellis1972

This comment has been minimized.

Contributor

dellis1972 commented Feb 8, 2018

@pjcollins that log output looks like a normal build , not a design time build.

@pjcollins

This comment has been minimized.

Member

pjcollins commented Feb 8, 2018

Sorry about that, here's the binlog for the DesignTimeBuild which occurred immediately after an explicit build:

App21_Debug_AnyCPU_DesignTimeBuild_2018-02-08T14_45_39.4140376-05_00.zip

@dellis1972

This comment has been minimized.

Contributor

dellis1972 commented Feb 9, 2018

@pjcollins looking at that log file there is no compile call and the DesignTimeBuild = false so I have no idea what is going on... I'll try and repo this issue locally on the latest 15.6 release

@pjcollins

This comment has been minimized.

Member

pjcollins commented Feb 16, 2018

This also affects newly added elements in Layout files as well. For example, if you open a layout file in the designer and either add a new layout element via code or by dragging a widget on to the designer, intellisense seemingly never kicks in until the entire solution is reloaded. This seems somewhat nasty.

Additionally, new compilation issues will surface if you attempt to reference a resource that does not exist. Not only will you receive an error for the element that does not exist, but new errors will be reported for the previously added and referenced resources which do exist.

Here's a slightly modified version of the steps in the description which demonstrate this last point:

  1. Create a new Single-View Android App.
  2. Add a two new string entry in Resources -> values -> Strings.xml, such as:
<string name="test">test</string>
<string name="test2">test2</string>
  1. Open MainActivity.cs and add the following lines to your OnCreate method:
var res = Resource.String.test;
var res2 = Resource.String.test2;
  1. Build your solution. This build should be successful, even though intellisense is reporting issues with the two lines shown above.
  2. Modify the OnCreate method, to include the following
var res3 = Resource.String.doesnotexist;
  1. Attempt to build the solution again. Now three errors should be reported for doesnotexist, test2, and test. This is strange, as test and test2 do exist, and did not cause build errors earlier (even if intellisense seemed to indicate otherwise).

Finally if I apply the following diff to my Xamarin.Android.Common.targets file, these issues go away in 15.6. This indicates to me that all of these negative behaviors are managed resource parser related.

+ <AndroidUseManagedDesignTimeResourceGenerator Condition=" '$(AndroidUseManagedDesignTimeResourceGenerator)' == '' " >False</AndroidUseManagedDesignTimeResourceGenerator>

jonpryor added a commit that referenced this issue Feb 16, 2018

[Xamarin.Android.Build.Tasks] Disable Managed DesignTimeBuild
Context: #1287

The managed DesignTimeBuild infrastructure is still not as bug-free as
we would like.

Disable for the final d15-6 release.

@pjcollins pjcollins modified the milestones: d15-6, d15-7 Feb 16, 2018

@pjcollins

This comment has been minimized.

Member

pjcollins commented Feb 16, 2018

Updating the milestone to 15.7, as this has now been disabled for 15.6.

@xamarin xamarin deleted a comment Feb 20, 2018

@dellis1972

This comment has been minimized.

Contributor

dellis1972 commented Feb 21, 2018

Looks like we need to run a target ourselves to update the design time resource designer file before intellisense will pick it up.

@jonpryor

This comment has been minimized.

Contributor

jonpryor commented Feb 21, 2018

@dellis1972 wrote:

Looks like we need to run a target ourselves to update the design time resource designer file before intellisense will pick it up.

How are we going to do that?! Create a FileSystemWatcher on everything in the project dir and execute the target on file changes? (Please don't do this.)

Or is this a sign that we should once again take a stab at fixing Bug #5870, have the IDE emit %(AndroidResource.Generator) metadata, and use the target specified in %(AndroidResource.Generator) also trigger a DesignTimeBuild update?

Related: https://mhut.ch/journal/2015/06/30/build_time_code_generation_msbuild
Related: https://trello.com/c/W5Mgou72/4-resourcedesignercs
Related: https://trello.com/c/ypQrdAQb/179-migration-to-automatic-resourcedesignercs-generation

@dellis1972

This comment has been minimized.

Contributor

dellis1972 commented Feb 21, 2018

@dellis1972

This comment has been minimized.

Contributor

dellis1972 commented Feb 21, 2018

now that I think about it. Generator won't help us here because we need to run it for both a normal build and a design time build since we don't use the same file anymore... It will help us know when a file changed in the targets though.. I'll need to figure out what to do then

@dellis1972

This comment has been minimized.

Contributor

dellis1972 commented Feb 22, 2018

ok.. I change the following code

<AndroidResource Include="Resources\values\styles.xml" />
to

<AndroidResource Include="Resources\values\styles.xml"> <SubType>Designer</SubType> <Generator>MSBuild:UpdateAndroidResources</Generator> </AndroidResource>

And that fixes the design time build issue. What happens is we run UpdateAndroidResources when the file is modified. Because its not a Build and $(DesignTimeBuild) == '' we do a design time build since we end updating _SetupDesignTimeBuildForCompile. This then updates the designer in the designtime folder and we get correct intelligence.

Now the problem is I don't think the the Generatormetadata is something we can add on the fly. I think in order for VS to use it, it has to be on the Item at project load. I am going to test this and see if I can just add it on the fly. If not then we are going to need to update ALL AndroidResource items to have this metadata. Related PR [1]

[1] #1327

@dellis1972

This comment has been minimized.

Contributor

dellis1972 commented Feb 22, 2018

@jonpryor wrote

@dellis1972 wrote:

Looks like we need to run a target ourselves to update the design time resource designer file before intellisense will pick it up.

How are we going to do that?! Create a FileSystemWatcher on everything in the project dir and execute the target on file changes? (Please don't do this.)

If we did the "running the target ourselves" thing. The IDE addin would need to deal with that, not sure if they have code to handle that already (@joj might know). It would need to monitor AndroidResources and call UpdateAndroidResources on update. I believe the IDE used to do that a while back.

At the moment its looking like any fix is either going to be pain because we need IDE support to either add the Generator metadata or add a file monitor. What ever I do I can't get the DTB to run. After chats with the roslyn project system team they recommend using Generator metadata as its they way UWP/xaml based apps work. But then again they don't have to worry about VSForMac support while we do.

Note I also tried adding the AndroidResource items to CustomAdditionalCompileInputs which is an input to the <CoreCompile/> target [1]. The hope was it would detect the updated android resource and trigger a Design Time Build. But that didn't work either.

[1] https://referencesource.microsoft.com/#MSBuildFiles/C/ProgramFiles(x86)/MSBuild/14.0/bin_/amd64/Microsoft.CSharp.Core.targets,15

dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Feb 27, 2018

[Xamarin.Android.Build.Tasks] Add Default Metadata for `@(AndroidReso…
…urce)` Items.

Fixes xamarin#1287

One of the problems we have encountered is that the logic behind
how and when the design time build (DTB) is run is unclear. Specifically
what events/changes trigger a DTB. After lenghty conversations with
the Visual Studio team it seems that their prefered solution is to
use the `Generator` metadata.

The idea behind this is that an Item can include

	<Generator>MSBuild:Target</Generator>

metadata which specify the MSBuild `Target` to run if that file
is modified. If these data is present Visual Studio will run the
target, which then modifies the required files which then triggers
an DTB update. Other ideas included adding a FileSystemWatcher to
the Visual Studio Addin to detect these changes and run targets.
That said the Generator metadata is built in and should work for
this purpose.

So now the problem. Normally you define this metadata on the Item
in the csproj. We have 1000's of developers with existing projects
which DO NOT include this data. So how do we fix up existing projects
without a) requiring manual changes or b) having to write a tool to
upgrade the projects.

This is where `<ItemDefinitionGroup/>` [1] comes in :). It allows
us to define the `default` metadata we want to include on Items.
So if we define

	<ItemDefinitionGroup>
		<Foo>
           		<A>bar</A>
        	</Foo>
	</ItemDefinitionGroup>

	<Foo Include="1">
		<A>some</A>
	</Foo>
	<Foo Include="2" />

When will happen is `<A>bar</A>` will be automatically added to
the `<Foo Include="2" />`. It will be skipped on the other one
because it already has a `<A/>` element defined. This is a really
nice feature since it allows us to add the required metadata in
the background without having to get users to upgrade projects.
Also because these are default values the csproj files will NOT
be changed when a user alters the project for some other reason.
i.e they WONT end up will ALL the `<AndroidResource />` items
having this new data on them.

The other thing to note is that these changes will only apply to
the DTB. The target we are calling in this case is `UpdateGeneratedFiles`.
This target is not part of the `Build` chain. As a result
`_SetupDesingTimeBuildForCompile` will be called. This sets `$(DesignTimeBuild)`
to true. So calling this target will ONLY update the DTB related files.

[1] https://docs.microsoft.com/en-us/visualstudio/msbuild/itemdefinitiongroup-element-msbuild

jonpryor added a commit that referenced this issue Feb 27, 2018

[Xamarin.Android.Build.Tasks] Add Default Metadata for `@(AndroidReso…
…urce)` Items. (#1345)

Fixes: #1287

One of the problems we have encountered is that the logic behind how
and when the Design-Time Build (DTB) is run is unclear. Specifically
what events/changes trigger a DTB. After lengthy conversations with
the Visual Studio team it seems that their preferred solution is to
use [`%(Generator)` metadata][0].

The idea behind this is that an Item can include

	<AndroidResource Include="Resources\layout\Main.axml">
	  <Generator>MSBuild:Target</Generator>
	</AndroidResource>

metadata which states that the MSBuild `Target` should be run when
the `%(Identity)` file is modified. When the `%(Identity)` file is
modified within the IDE, the specified MSBuild target will be
executed as part of a new Design-Time Build.

Normally you define the `%(Generator)` metadata on the Item in the
`.csproj`. However, We have *lots* of developers with existing
projects which DO NOT include this metadata. How do we fix up
existing projects without a) requiring manual changes or b) having to
write a tool to upgrade the projects?

This is where [`<ItemDefinitionGroup/>`][1] comes in :). It allows
us to define the `default` metadata we want to include on Items.
If we have:

	<ItemDefinitionGroup>
	  <Foo>
           <A>bar</A>
         </Foo>
	</ItemDefinitionGroup>

	<Foo Include="1">
	  <A>some</A>
	</Foo>
	<Foo Include="2" />

What will happen is `<A>bar</A>` will be automatically added to
the `<Foo Include="2" />`. It will be skipped on the other one
because it already has a `<A/>` element defined. This is a really
nice feature since it allows us to add the required metadata in
the background without having to get users to upgrade projects.
Also because these are default values the `.csproj` files will NOT
be changed when a user alters the project for some other reason.
i.e they WONT end up will ALL the `<AndroidResource />` items
having this new data on them.

The other thing to note is that these changes will only apply to the
Design-Time Builds. The target we are calling in this case is
`UpdateGeneratedFiles`. This target is not part of the `Build` chain.
As a result `_SetupDesingTimeBuildForCompile` will be called. This
sets `$(DesignTimeBuild)` to True. Calling this target will ONLY
update the DTB related files.

[0]: https://mhut.ch/journal/2015/06/30/build_time_code_generation_msbuild
[1]: https://docs.microsoft.com/en-us/visualstudio/msbuild/itemdefinitiongroup-element-msbuild

jonpryor added a commit that referenced this issue Feb 27, 2018

[Xamarin.Android.Build.Tasks] Add Default Metadata for `@(AndroidReso…
…urce)` Items. (#1345)

Fixes: #1287

One of the problems we have encountered is that the logic behind how
and when the Design-Time Build (DTB) is run is unclear. Specifically
what events/changes trigger a DTB. After lengthy conversations with
the Visual Studio team it seems that their preferred solution is to
use [`%(Generator)` metadata][0].

The idea behind this is that an Item can include

	<AndroidResource Include="Resources\layout\Main.axml">
	  <Generator>MSBuild:Target</Generator>
	</AndroidResource>

metadata which states that the MSBuild `Target` should be run when
the `%(Identity)` file is modified. When the `%(Identity)` file is
modified within the IDE, the specified MSBuild target will be
executed as part of a new Design-Time Build.

Normally you define the `%(Generator)` metadata on the Item in the
`.csproj`. However, We have *lots* of developers with existing
projects which DO NOT include this metadata. How do we fix up
existing projects without a) requiring manual changes or b) having to
write a tool to upgrade the projects?

This is where [`<ItemDefinitionGroup/>`][1] comes in :). It allows
us to define the `default` metadata we want to include on Items.
If we have:

	<ItemDefinitionGroup>
	  <Foo>
           <A>bar</A>
         </Foo>
	</ItemDefinitionGroup>

	<Foo Include="1">
	  <A>some</A>
	</Foo>
	<Foo Include="2" />

What will happen is `<A>bar</A>` will be automatically added to
the `<Foo Include="2" />`. It will be skipped on the other one
because it already has a `<A/>` element defined. This is a really
nice feature since it allows us to add the required metadata in
the background without having to get users to upgrade projects.
Also because these are default values the `.csproj` files will NOT
be changed when a user alters the project for some other reason.
i.e they WONT end up will ALL the `<AndroidResource />` items
having this new data on them.

The other thing to note is that these changes will only apply to the
Design-Time Builds. The target we are calling in this case is
`UpdateGeneratedFiles`. This target is not part of the `Build` chain.
As a result `_SetupDesingTimeBuildForCompile` will be called. This
sets `$(DesignTimeBuild)` to True. Calling this target will ONLY
update the DTB related files.

[0]: https://mhut.ch/journal/2015/06/30/build_time_code_generation_msbuild
[1]: https://docs.microsoft.com/en-us/visualstudio/msbuild/itemdefinitiongroup-element-msbuild
@pjcollins

This comment has been minimized.

Member

pjcollins commented Apr 3, 2018

I'm no longer able to reproduce any of the negative behavior described in the initial report or in the fourth comment. Adding the verified tag against d15-7 (XA 8.3.0.11)

@pjcollins pjcollins added the verified label Apr 3, 2018

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