Browse Source
* fix: Avalonia.Generators not found if you put SourceGenerators.props in a project with path are like this:"C:\GitHub\Avalonia\sample\mobile\android\ANoteSample\ANoteSample.csproj", the Compiler is not able to found `Avalonia.Generators` * test: Add test #10046 Xaml Compiler error when code-behind class contains a DllImport method * fix: Xaml Compiler error when code-behind class contains a DllImport method * fix: Address Review * fix: ValidateApiDiff has thrown an exceptionpull/12861/head
committed by
GitHub
13 changed files with 330 additions and 3 deletions
@ -0,0 +1,39 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net472</TargetFramework> |
|||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> |
|||
<OutputType>Library</OutputType> |
|||
<IsPackable>false</IsPackable> |
|||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
|||
<Configuration Condition="'$(Configuration)'==''">Debug</Configuration> |
|||
</PropertyGroup> |
|||
|
|||
<Import Project="..\..\build\Moq.props" /> |
|||
<Import Project="..\..\build\Rx.props" /> |
|||
<Import Project="..\..\build\HarfBuzzSharp.props" /> |
|||
<Import Project="..\..\build\XUnit.props" /> |
|||
<Import Project="..\..\build\SharedVersion.props" /> |
|||
<ItemGroup> |
|||
<Content Include="..\TestFiles\BuildTasks\PInvoke\bin\$(Configuration)\netstandard2.0\PInvoke.dll" Link="Assets\PInvoke.dll"> |
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
|||
</Content> |
|||
<Content Include="..\TestFiles\BuildTasks\PInvoke\bin\$(Configuration)\netstandard2.0\PInvoke.dll.refs" Link="Assets\PInvoke.dll.refs"> |
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
|||
</Content> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" PrivateAssets="All" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj" /> |
|||
<!-- Ensure PInvoke.csproj is build before Avalonia.Build.Tasks.UnitTest --> |
|||
<ProjectReference Include="..\TestFiles\BuildTasks\PInvoke\PInvoke.csproj" |
|||
SetConfiguration="Configuration=$(Configuration)" |
|||
SetTargetFramework="TargetFramework=netstandard2.0" |
|||
ReferenceOutputAssembly="false" |
|||
PrivateAssets="all" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,38 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Reflection; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Build.Tasks.UnitTest; |
|||
|
|||
public class CompileAvaloniaXamlTaskTest |
|||
{ |
|||
|
|||
[Fact] |
|||
public void Does_Not_Fail_When_Codebehind_Contains_DllImport() |
|||
{ |
|||
using var engine = UnitTestBuildEngine.Start(); |
|||
var basePath = Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), "Assets"); |
|||
var originalAssemblyPath = Path.Combine(basePath, |
|||
"PInvoke.dll"); |
|||
var referencesPath = Path.Combine(basePath, |
|||
"PInvoke.dll.refs"); |
|||
var compiledAssemblyPath = "PInvoke.dll"; |
|||
|
|||
Assert.True(File.Exists(originalAssemblyPath), $"The original {originalAssemblyPath} don't exists."); |
|||
|
|||
new CompileAvaloniaXamlTask() |
|||
{ |
|||
AssemblyFile = originalAssemblyPath, |
|||
ReferencesFilePath = referencesPath, |
|||
OutputPath = compiledAssemblyPath, |
|||
RefAssemblyFile = null, |
|||
BuildEngine = engine, |
|||
ProjectDirectory = Directory.GetCurrentDirectory(), |
|||
VerifyIl = true |
|||
}.Execute(); |
|||
Assert.Equal(0, engine.Errors.Count); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,96 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using Microsoft.Build.Framework; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Build.Tasks.UnitTest; |
|||
|
|||
/// <summary>
|
|||
/// This is fake BuildEngine using for testing build task
|
|||
/// at moment it manage only <see cref="BuildErrorEventArgs"/> and <see cref="BuildWarningEventArgs"/>
|
|||
/// other messages are ignored/>
|
|||
/// </summary>
|
|||
internal class UnitTestBuildEngine : IBuildEngine, IDisposable |
|||
{ |
|||
private readonly bool _treatWarningAsError; |
|||
private readonly bool _assertOnDispose; |
|||
private readonly List<UnitTestBuildEngineMessage> _errors = new(); |
|||
|
|||
/// <summary>
|
|||
/// Start new instance of <see cref="UnitTestBuildEngine"/>
|
|||
/// </summary>
|
|||
/// <param name="continueOnError">if it is <c>false</c> immediately assert error</param>
|
|||
/// <param name="treatWarningAsError">if it is <c>true</c> treat warning as error</param>
|
|||
/// <param name="assertOnDispose">if it is <c>true</c> assert on dispose if there are any errors.</param>
|
|||
/// <returns></returns>
|
|||
public static UnitTestBuildEngine Start(bool continueOnError = false, |
|||
bool treatWarningAsError = false, |
|||
bool assertOnDispose = false) => |
|||
new UnitTestBuildEngine(continueOnError, treatWarningAsError, assertOnDispose); |
|||
|
|||
private UnitTestBuildEngine(bool continueOnError, |
|||
bool treatWarningAsError, |
|||
bool assertOnDispose) |
|||
{ |
|||
ContinueOnError = continueOnError; |
|||
_treatWarningAsError = treatWarningAsError; |
|||
_assertOnDispose = assertOnDispose; |
|||
} |
|||
|
|||
public bool ContinueOnError { get; } |
|||
|
|||
public int LineNumberOfTaskNode { get; } |
|||
|
|||
public int ColumnNumberOfTaskNode { get; } |
|||
|
|||
public string ProjectFileOfTaskNode { get; } |
|||
|
|||
public IReadOnlyList<UnitTestBuildEngineMessage> Errors => _errors; |
|||
|
|||
public bool BuildProjectFile(string projectFileName, |
|||
string[] targetNames, |
|||
IDictionary globalProperties, |
|||
IDictionary targetOutputs) |
|||
=> throw new NotImplementedException(); |
|||
|
|||
public void Dispose() |
|||
{ |
|||
if (_assertOnDispose && _errors.Count > 0) |
|||
{ |
|||
Assert.Fail("There is one o more errors."); |
|||
} |
|||
} |
|||
|
|||
|
|||
public void LogCustomEvent(CustomBuildEventArgs e) |
|||
{ |
|||
} |
|||
|
|||
public void LogMessageEvent(BuildMessageEventArgs e) |
|||
{ |
|||
} |
|||
|
|||
public void LogErrorEvent(BuildErrorEventArgs e) |
|||
{ |
|||
var message = UnitTestBuildEngineMessage.From(e); |
|||
_errors.Add(message); |
|||
if (!ContinueOnError) |
|||
{ |
|||
Assert.Fail(message.Message); |
|||
} |
|||
} |
|||
|
|||
public void LogWarningEvent(BuildWarningEventArgs e) |
|||
{ |
|||
if (_treatWarningAsError) |
|||
{ |
|||
var message = UnitTestBuildEngineMessage.From(e); |
|||
_errors.Add(message); |
|||
if (!ContinueOnError) |
|||
{ |
|||
Assert.Fail(message.Message); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
using Microsoft.Build.Framework; |
|||
|
|||
namespace Avalonia.Build.Tasks.UnitTest; |
|||
|
|||
enum MessageSource |
|||
{ |
|||
Unknown, |
|||
ErrorEvent, |
|||
MessageEvent, |
|||
CustomEvent, |
|||
WarningEvent |
|||
} |
|||
|
|||
record class UnitTestBuildEngineMessage |
|||
{ |
|||
private UnitTestBuildEngineMessage(MessageSource Type, LazyFormattedBuildEventArgs Source) |
|||
{ |
|||
this.Type = Type; |
|||
this.Source = Source; |
|||
Message = Source.Message; |
|||
} |
|||
|
|||
public MessageSource Type { get; } |
|||
public LazyFormattedBuildEventArgs Source { get; } |
|||
public string Message { get; } |
|||
|
|||
public static UnitTestBuildEngineMessage From(BuildWarningEventArgs buildWarning) => |
|||
new UnitTestBuildEngineMessage(MessageSource.WarningEvent, buildWarning); |
|||
|
|||
public static UnitTestBuildEngineMessage From(BuildMessageEventArgs buildMessage) => |
|||
new UnitTestBuildEngineMessage(MessageSource.MessageEvent, buildMessage); |
|||
|
|||
public static UnitTestBuildEngineMessage From(BuildErrorEventArgs buildError) => |
|||
new UnitTestBuildEngineMessage(MessageSource.ErrorEvent, buildError); |
|||
|
|||
public static UnitTestBuildEngineMessage From(CustomBuildEventArgs customBuild) => |
|||
new UnitTestBuildEngineMessage(MessageSource.CustomEvent, customBuild); |
|||
|
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
<Application |
|||
xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="PInvoke.App"> |
|||
<Application.Styles> |
|||
<FluentTheme /> |
|||
</Application.Styles> |
|||
</Application> |
|||
@ -0,0 +1,21 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls.ApplicationLifetimes; |
|||
using Avalonia.Markup.Xaml; |
|||
|
|||
namespace PInvoke; |
|||
|
|||
public class App : Application |
|||
{ |
|||
public override void Initialize() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
|
|||
public override void OnFrameworkInitializationCompleted() |
|||
{ |
|||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) |
|||
{ |
|||
desktopLifetime.MainWindow = new MainWindow(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
<Window xmlns="https://github.com/avaloniaui" |
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' |
|||
x:Class="PInvoke.MainWindow"> |
|||
</Window> |
|||
@ -0,0 +1,22 @@ |
|||
using System.Runtime.InteropServices; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace PInvoke; |
|||
|
|||
public partial class MainWindow : Window |
|||
{ |
|||
[DllImport(@"libhello")] |
|||
extern static int add(int a, int b); |
|||
|
|||
public MainWindow() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
protected override void OnLoaded(RoutedEventArgs e) |
|||
{ |
|||
base.OnLoaded(e); |
|||
var x = add(1, 2); |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks> |
|||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> |
|||
<IncludeAvaloniaGenerators>true</IncludeAvaloniaGenerators> |
|||
<!--<AvaloniaXamlIlDebuggerLaunch>true</AvaloniaXamlIlDebuggerLaunch>--> |
|||
<EnableAvaloniaXamlCompilation>false</EnableAvaloniaXamlCompilation> |
|||
<IncludeAvaloniaGenerators>true</IncludeAvaloniaGenerators> |
|||
<IsPackable>false</IsPackable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\src\Avalonia.Base\Avalonia.Base.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\src\Avalonia.Controls\Avalonia.Controls.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<Import Project="..\..\..\..\build\SampleApp.props" /> |
|||
<Import Project="..\..\..\..\build\ReferenceCoreLibraries.props" /> |
|||
<Import Project="..\..\..\..\build\BuildTargets.targets" /> |
|||
<Import Project="..\..\..\..\build\SourceGenerators.props" /> |
|||
</Project> |
|||
@ -0,0 +1,14 @@ |
|||
using Avalonia; |
|||
|
|||
namespace PInvoke; |
|||
|
|||
public class Program |
|||
{ |
|||
static void Main(string[] args) => BuildAvaloniaApp() |
|||
.StartWithClassicDesktopLifetime(args); |
|||
|
|||
public static AppBuilder BuildAvaloniaApp() => |
|||
AppBuilder.Configure<App>() |
|||
.UsePlatformDetect() |
|||
.LogToTrace(); |
|||
} |
|||
Loading…
Reference in new issue