Compiled converters are invoked, by reflection, at compile time. Any
exception thrown there will be wrapped in a TargetInvocationException.
When that happens, we still want to expose the inner XamlParseException
to the user.
- fixes#4099
As part of #2556, the namescoping tree was assumed to be equiv to the
object tree, which is obviously wrong. This fixes it, while keeping the
old behavior as a fallback.
We might go further, but I can't come up with a reasonable scenario
failing.
- fixes#3821
Throws a XamlParseException on duplicate x:Key on RDs. This will find
duplicate in xaml, but duplicates can still happen if the RD is modified
in code. Those dupes are already detectd at runtime.
- helps, but doesn't fixes, #3512
* [XamlG] builds incrementally, add MSBuild integration tests
Context: https://github.com/xamarin/Xamarin.Forms/pull/2230
The main performance problem with the collection of MSBuild targets in
`Xamarin.Forms.targets` is they don't build incrementally. I addressed
this with `XamlC` using a "stamp" file; however, it is not quite so
easy to setup the same thing with `XamlG`.
They way "incremental" builds are setup in MSBuild, is by specifying
the `Inputs` and `Outputs` of a `<Target />`. MSBuild will partially
build a target when some outputs are not up to date, and skip it
entirely if they are all up to date.
The best docs I can find on MSBuild incremental builds:
https://msdn.microsoft.com/en-us/library/ms171483.aspx
Unfortunately a few things had to happen to make this work for
`XamlG`:
- Define a new target `_FindXamlGFiles` that is invoked before `XamlG`
- `_FindXamlGFiles` defines the `_XamlGInputs` and `_XamlGOutputs`
`<ItemGroup />`'s
- `_FindXamlGFiles` must also define `<Compile />` and `<FileWrites />`,
in case the `XamlG` target is skipped
- `XamlGTask` now needs to get passed in a list of `OutputFiles`,
since we have computed these paths ahead of time
- `XamlGTask` should validate the lengths of `XamlFiles` and
`OutputFiles` match, used error message from MSBuild proper:
a691a44f0e/src/Tasks/Copy.cs (L505)
`XamlG` now builds incrementally!
To give some context on how much improvement we can see with build
times, consider the following command:
msbuild Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj
If you run it once, it will take a while--this change will not improve
the first build. On the second build with the exact same command, it
*should* be much faster.
Before this commit, the second build on my machine takes:
40.563s
After the change:
23.692s
`XamlG` has cascading impact on build times when it isn't built
incrementally:
- The C# assembly always changes
- Hence, `XamlC` will always run
- Hence, `GenerateJavaStubs` will always run
- Hence, `javac.exe` and `dx.jar` will always run
I am making other improvements like this in Xamarin.Android itself,
that will further improve these times, such as:
https://github.com/xamarin/xamarin-android/pull/1693
~~ New MSBuild Integration Tests ~~
Added some basic MSBuild testing infrastructure:
- Tests write project files to `bin/Debug/temp/TestName`
- Each test has an `sdkStyle` flag for testing the new project system
versus the old one
- `[TearDown]` deletes the entire directory, with a retry for
`IOException` on Windows
- Used the `Microsoft.Build.Locator` NuGet package for locating
`MSBuild.exe` on Windows
- These tests take 2-5 seconds each
So for example, the simplest test, `BuildAProject` writes to
`Xamarin.Forms.Xaml.UnitTests\bin\Debug\temp\BuildAProject(False)\test.csproj`:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
<OutputType>Library</OutputType>
<OutputPath>bin\Debug</OutputPath>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="Xamarin.Forms.Core.dll">
<HintPath>..\..\Xamarin.Forms.Core.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Forms.Xaml.dll">
<HintPath>..\..\Xamarin.Forms.Xaml.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\..\..\.nuspec\Xamarin.Forms.targets" />
<ItemGroup>
<EmbeddedResource Include="MainPage.xaml" />
</ItemGroup>
</Project>
Invokes `msbuild`, and checks the intermediate output for files being
generated.
Tested scenarios:
- Build a simple project
- Build, then build again, and make sure targets were skipped
- Build, then clean, make sure files are gone
- Build, with linked files
- Design-time build
- Call `UpdateDesignTimeXaml` directly
- Build, add a new file, build again
- Build, update timestamp on a file, build again
- XAML file with random XML content
- XAML file with invalid XML content
- A general `EmbeddedResource` that shouldn't go through XamlG
Adding these tests found a bug! `IncrementalClean` was deleting
`XamlC.stamp`. I fixed this by using `<ItemGroup />`, which will be
propery evaluated even if the target is skipped.
~~ Other Changes ~~
- `FilesWrite` is actually supposed to be `FileWrites`, see canonical
source of how `Clean` works and what `FileWrites` is here:
https://github.com/Microsoft/msbuild/issues/2408#issuecomment-321082997
- Moved `DummyBuildEngine` into `MSBuild` directory--makes sense?
maybe don't need to?
- Added a `XamlGDifferentInputOutputLengths` test to check the error
message
- Expanded `DummyBuildEngine` so you can assert against log messages
- Changed a setting in `.Xamarin.Forms.Android.sln` so the unit test
project is built
- My VS IDE monkeyed with a few files, and I kept any *good* (or
relevant) changes: `Xamarin.Forms.UnitTests.csproj`,
`Xamarin.Forms.Xaml.UnitTests\app.config`, etc.
There were some checks for `%(TargetPath)` being blank in the C# code
of `XamlGTask`. In that case it was using `Path.GetRandomFileName`,
but we can't do this if we are setting up inputs and outputs for
`XamlG`. I presume this is from the designer and/or design-time builds
before `DependsOnTargets="PrepareResourceNames"` was added. I tested
design-time builds in VS on Windows, and `$(TargetPath)` was set. To
be sure we don't break anything here, I exclude inputs to `XamlG` if
`%(TargetPath)` is somehow blank.
See relevant MSBuild code for `%(TargetPath)` here:
0515178090/src/Tasks/Microsoft.Common.CurrentVersion.targets (L2822)
~~ Future changes ~~
CssG needs the exact same setup, as it was patterned after `XamlG`.
This should probably be done in a future PR.
* [msbuild] improved lookup of Xamarin.Forms.targets in integration tests
Context: https://devdiv.visualstudio.com/DevDiv/_build?buildId=1717939
Context: https://devdiv.visualstudio.com/DevDiv/_build?buildId=1718306
It looks like the VSTS builds for release branches are running tests
in a staging directory. This means we can't reliably import
`Xamarin.Forms.targets` as what was working locally in the
Xamarin.Forms source tree.
So to fix this:
- Look for `.nuspec/Xamarin.Forms.targets`, at the default location
and then using the `BUILD_SOURCESDIRECTORY` environment variable as
a fallback
- Copy all `*.targets` files to the test directory
- Our `*.csproj` files under test can import the file from there.
We have to copy the targets files here to be sure that MSBuild can
load `Xamarin.Forms.Build.Tasks.dll`, which is also referenced by the
unit tests.
I also made the tests abort earlier if they can't find
`Xamarin.Forms.targets`.
* [Xaml] open non-generic FindByName()
* [Xaml[C]] Only set the namescope when it's different
avoid setting the NamesCope if it's the same as the parent.
Also provide an IReferenceProvider for markup extension that need to
replicate the x:Reference behavior.
* [XamlC] x:DataType in default xmlns
* [XamlC] meaningful error on missing property
throw a readable exception when part of a compiled binding path is
missing.
- fixes#2517
* [XamlC] no longer use any reflection-base ImportReference
reflection-base ImportReference -- we were using MethodBase and Type --
are importing the types present in the reflection context, at the time
of compilation. As the compilation happens on netstandard2.0, and our
assembly can now be netstandard1.0 again, those imported types are
failing to be resolved.
this changes always import references based on the assembly, or the
assembly references.
it might, or might not, give us another speed bump.
* [XamlC] accomodate all kinds of netstandard versions
* reuse caching code
ImportReference with System.Reflection based argument is notoriously
slow on .NET. So we cache the results for those.
We do not cache the results for TypeReference, MethodReference or
FieldReference calls, as those are already fast (passthrough if the
reference was already imported), and they aren't valid as dictionary
keys (no concept of equatability).
While we're at it, we shave another few ms from Resolve(TypeReference)
calls as well.
As, on good days, it shaves up to 40% of XamlC time, we can say that it
- fixes#1848
* [C/XamlC] BindingMode.OneTime
Bindings with mode == OneTime:
- are only applied when the BindingContext changes
- do not subscribe to INPC
if the Binding is compiled and the mode explicitely set in the
`{Binding}` Markup extension, the setters and handlers aren't even
created.
- fixes#1686
* update docs
* [Xaml] let the previewer know the asm
in addition to the resourcePath, tell the previewer the assembly in
which we're looking for the resource.
* fix docs
* Port from old VSM branch
* Add PS and notes
* Checkpoint: entry text UWP mostly working, need to check on background colors
* Remove irrelevant samples from the EntryDisabledStatesGallery
Make Background color work on UWP Entry with VSM
* Add platform specific for disabling legacy colors on Android
* Add OnPlatform example to visual state manager gallery
* Add example OnIdiom in Visual State Manager
* Add platform specific for disabling legacy color mode on iOS Entry
* Add gallery for Button disabled states
Handling legacy colors for Buttons on Android
* Split out disabled states galleries; disabled legacy handling for Picker
* TimePicker disabled states
* DatePicker color management on Android
* Color management for pre-AppCompat button
* Button legacy color handling on iOS
* Consolidate Platform Specifics;
legacy colors working for iOS Picker and DatePicker
* Fix broken search bar color management
SearchBar color management working with VSM
Add test page for SearchBar disabled color management
Consolidate legacy color management check code into extension method on Android
* Legacy color management for Editor on Android
* Fix legacy color stuff for SearchBar Cancel button on iOS
* C# 7 cleanup
* Add colors for Cancel Button
* Make sure VisualStateGroup collections set by styles are distinct objects
* Validation example
* Make common state names consts
* Make the Windows VSM and Forms VSM work together
* Update galleries for Windows
* Make new methods internal
* Split gallery classes and add more explanation to validation example
* Remove debugging statements
* Add a quick code-only example
* Make legacy color management work for fast button renderer
* Remove old TODO
* Update docs
* Move RunTimeNamePropertyAttribute to Xamarin.Forms.Xaml namespace
* Verify XF namespace when looking for VisualState
* Use nameof
* Make common states constants public
* Cast VisualElement directly so it crashes if the property is set on the wrong type
* Collection -> IList for VisualStateManager
* Setting fromStyle to true
* Remove extraneous `private set`
* Seal VSM classes
* Use constraints instead of ==
* Add teardown method; use constraints rather than ==
* Remove null checking with GetVisualStateGroups
* Don't explicitly initialize collections on elements
* Actually, turns out that fromStyle:false *was* correct
* Direct casts
* Use GetIsDefault check in GoToState
* Validate parents in FindTypeForVisualState
* Validate group and state names on Add
* Fixed check for setter collection
* Fix issues with "duplicate" names when VisualStateGroups declared directly on VisualElements
* Add gallery example for VSGs directly on VisualElements
* Update docs
* Fix bug where initial TextColor isn't set for FastRenderer Button
* Move to explicit VisualStateGroupList in Setter
* Fix return types for unit tests
* Using string.CompareOrdinal in GetState
* Update docs
* Add check for null/empty VisualState Name properties