xamarin-macios/tests/xtro-sharpie/DeprecatedCheck.cs

175 строки
6.6 KiB
C#
Исходник Обычный вид История

using System;
using System.Collections.Generic;
using System.Linq;
using Clang;
using Clang.Ast;
using Mono.Cecil;
namespace Extrospection
{
public class DeprecatedCheck : BaseVisitor
{
Dictionary<string, VersionTuple> ObjCDeprecatedItems = new Dictionary<string, VersionTuple> ();
Dictionary<string, VersionTuple> ObjCDeprecatedSelectors = new Dictionary<string, VersionTuple> ();
Dictionary<string, VersionTuple> PlainCDeprecatedFunctions = new Dictionary<string, VersionTuple> ();
List<TypeDefinition> ManagedTypes = new List<TypeDefinition> ();
Dictionary<string, MethodDefinition> dllimports = new Dictionary<string, MethodDefinition> ();
public override void VisitManagedMethod (MethodDefinition method)
{
if (!method.IsPInvokeImpl || !method.HasPInvokeInfo)
return;
// we don't decorate OpenTK types with availability
var dt = method.DeclaringType;
var ns = dt.IsNested ? dt.DeclaringType.Namespace : dt.Namespace;
if (ns.StartsWith ("OpenTK.", StringComparison.Ordinal))
return;
var info = method.PInvokeInfo;
if (info.Module.Name == "__Internal")
return;
// there are duplicated declarations, only the last will be reported
dllimports [info.EntryPoint] = method;
}
public override void End ()
{
foreach (var objcEntry in ObjCDeprecatedItems)
ProcessObjcEntry (objcEntry.Key, objcEntry.Value);
foreach (var objcEntry in ObjCDeprecatedSelectors)
ProcessObjcSelector (objcEntry.Key, objcEntry.Value);
foreach (var cEntry in PlainCDeprecatedFunctions)
ProcessCFunction (cEntry.Key, cEntry.Value);
}
void ProcessObjcEntry (string objcClassName, VersionTuple objcVersion)
{
TypeDefinition managedType = ManagedTypes.FirstOrDefault (x => Helpers.GetName (x) == objcClassName && x.IsPublic);
if (managedType != null) {
var framework = Helpers.GetFramework (managedType);
if (framework != null)
ProcessItem (managedType, Helpers.GetName (managedType), objcVersion, framework);
}
}
void ProcessObjcSelector (string fullname, VersionTuple objcVersion)
{
var class_method = fullname [0] == '+';
var n = fullname.IndexOf ("::");
string objcClassName = fullname.Substring (class_method ? 1: 0, n);
string selector = fullname.Substring (n + 2);
TypeDefinition managedType = ManagedTypes.FirstOrDefault (x => Helpers.GetName (x) == objcClassName);
if (managedType != null) {
var framework = Helpers.GetFramework (managedType);
if (framework == null)
return;
// If the entire type is deprecated, call it good enough
if (AttributeHelpers.HasAnyDeprecationForCurrentPlatform (managedType))
return;
var matchingMethod = managedType.Methods.FirstOrDefault (x => x.GetSelector () == selector && x.IsPublic && x.IsStatic == class_method);
if (matchingMethod != null)
ProcessItem (matchingMethod, fullname, objcVersion, framework);
}
}
void ProcessCFunction (string fullname, VersionTuple objcVersion)
{
if (dllimports.TryGetValue (fullname, out var method)) {
var dt = method.DeclaringType;
var framework = Helpers.GetFramework (dt);
if (framework == null)
return;
// If the entire type is deprecated, call it good enough
if (AttributeHelpers.HasAnyDeprecationForCurrentPlatform (dt))
return;
ProcessItem (method, fullname, objcVersion, framework);
}
}
public void ProcessItem (ICustomAttributeProvider item, string itemName, VersionTuple objcVersion, string framework)
{
// Our bindings do not need have [Deprecated] for ancicent versions we don't support anymore
if (VersionHelpers.VersionTooOldToCare (objcVersion))
return;
// In some cases we've used [Advice] when entire types are deprecated
// TODO - This is a hack, we shouldn't be doing ^
if (AttributeHelpers.HasAnyAdvice (item))
return;
if (!AttributeHelpers.HasAnyDeprecationForCurrentPlatform (item)) {
Log.On (framework).Add ($"!deprecated-attribute-missing! {itemName} missing a [Deprecated] attribute");
return;
}
// Don't version check us when Apple does __attribute__((availability(macos, introduced=10.0, deprecated=100000)));
// #define __API_TO_BE_DEPRECATED 100000
if (objcVersion.Major == 100000)
return;
// Some APIs have both a [Deprecated] and [Obsoleted]. Bias towards [Obsoleted].
Version managedVersion;
bool foundObsoleted = AttributeHelpers.FindObsolete (item, out managedVersion);
if (foundObsoleted) {
if (managedVersion != null && !ManagedBeforeOrEqualToObjcVersion (objcVersion, managedVersion))
Log.On (framework).Add ($"!deprecated-attribute-wrong! {itemName} has {managedVersion} not {objcVersion} on [Obsoleted] attribute");
return;
}
bool foundDeprecated = AttributeHelpers.FindDeprecated (item, out managedVersion);
if (foundDeprecated && managedVersion != null && !ManagedBeforeOrEqualToObjcVersion (objcVersion, managedVersion))
Log.On (framework).Add ($"!deprecated-attribute-wrong! {itemName} has {managedVersion} not {objcVersion} on [Deprecated] attribute");
}
public static bool ManagedBeforeOrEqualToObjcVersion (VersionTuple objcVersionTuple, Version managedVersion)
{
// Often header files will soft deprecate APIs versions before a formal deprecation (10.7 soft vs 10.10 formal). Accept older deprecation values
return managedVersion <= VersionHelpers.Convert (objcVersionTuple);
}
public override void VisitManagedType (TypeDefinition type)
{
ManagedTypes.Add (type);
}
public override void VisitObjCCategoryDecl (ObjCCategoryDecl decl, VisitKind visitKind) => VisitItem (decl, visitKind);
public override void VisitObjCInterfaceDecl (ObjCInterfaceDecl decl, VisitKind visitKind) => VisitItem (decl, visitKind);
void VisitItem (NamedDecl decl, VisitKind visitKind)
{
Bump to Xcode 13 beta 1. (#11861) * Bump maccore. New commits in xamarin/maccore: * xamarin/maccore@9acbbed1f6 [mlaunch] Add support for Xcode 13 beta 1. (#2452) * xamarin/maccore@e48f75c0b6 [Xamarin.Hosting] Fix the --stdout arg not being forwarded to DeviceLaunchConfig (#2435) * xamarin/maccore@109c695b1b [Xamarin.Hosting] Fix help string for launchdev argument (#2429) Diff: https://github.com/xamarin/maccore/compare/cddbd1915dcb27d8bf2d9b3b9cc4aeb22785698e..9acbbed1f60788349c60437dba11531a866777a8 * [xtro] Fix generation of .pch files * [xtro] Fix deprecated check to handle (anonymous) declarations and enable latest C# syntax in project * [xtro] Fix _sanity_ checks * [xtro] Update todo for beta 1 * [Siminstaller] Force siminstaller to use the xcode 12.5 url Related issue: https://github.com/xamarin/xamarin-macios/issues/11881 * Fix introspection failures (due to [breaking] changes) * [tests][intro] Fix hang for tvOS Creating an instance of `NSMetadataQuery` hangs the simulator. Even after (xharness) timeout the simulator is not in a good state to run further tests and every new (tvOS) test will also hang... * [tests][intro] Same hang for watchOS except that further test execution does not seem affected (like tvOS) ``` CoreSimulator 772.1 - Device: Apple Watch Series 3 - 38mm (watchOS 8.0) - created by XHarness (42262867-E060-40C0-803E-6DA676AF50CC) - Runtime: watchOS 8.0 (19R5266p) - DeviceType: Apple Watch Series 3 - 38mm Thread 0 Crashed:: tid_103 Dispatch queue: com.apple.main-thread 0 com.apple.Foundation 0x00007fff21470bd0 -[NSMetadataQuery dealloc] + 432 1 libobjc.A.dylib 0x00007fff200d11f7 objc_object::sidetable_release(bool, bool) + 177 2 com.apple.Foundation 0x00007fff21470a03 -[NSMetadataQuery init] + 64 3 com.xamarin.introspection_watch.watchkitapp.watchkitextension 0x0000000107efc139 xamarin_dyn_objc_msgSend + 217 (trampolines-x86_64-objc_msgSend.s:15) 4 ??? 0x000000010c76d4f6 0 + 4504081654 5 com.xamarin.introspection_watch.watchkitapp.watchkitextension 0x0000000107cffc85 mono_jit_runtime_invoke + 1621 (mini-runtime.c:3197) 6 com.xamarin.introspection_watch.watchkitapp.watchkitextension 0x0000000107e177d8 do_runtime_invoke + 54 (object.c:3052) [inlined] 7 com.xamarin.introspection_watch.watchkitapp.watchkitextension 0x0000000107e177d8 mono_runtime_invoke_checked + 136 (object.c:3220) 8 com.xamarin.introspection_watch.watchkitapp.watchkitextension 0x0000000107e1e3c5 mono_runtime_try_invoke_array + 2101 (object.c:5601) 9 com.xamarin.introspection_watch.watchkitapp.watchkitextension 0x0000000107daf977 ves_icall_InternalInvoke + 871 (icall.c:3927) 10 com.xamarin.introspection_watch.watchkitapp.watchkitextension 0x0000000107dc0167 ves_icall_InternalInvoke_raw + 103 (icall-def.h:667) 11 ??? 0x000000010a232799 0 + 4465043353 12 ??? 0x000000010c76e08b 0 + 4504084619 ``` * [tests][monotouch-test] Fix failures with xcode 13 beta 1 * [tests][mmptest] Use a FAT framework that's build with x86_64 and arm64 Co-authored-by: Alex Soto <alex@alexsoto.me> Co-authored-by: Sebastien Pouliot <sebastien.pouliot@microsoft.com> Co-authored-by: Manuel de la Pena <mandel@microsoft.com>
2021-06-11 03:07:20 +03:00
if (visitKind == VisitKind.Enter && AttributeHelpers.FindObjcDeprecated (decl.Attrs, out VersionTuple version)) {
// `(anonymous)` has a null name
var name = decl.Name;
if (name is not null)
ObjCDeprecatedItems[name] = version;
}
}
public override void VisitObjCMethodDecl (ObjCMethodDecl decl, VisitKind visitKind)
{
if (visitKind == VisitKind.Enter && AttributeHelpers.FindObjcDeprecated (decl.Attrs, out VersionTuple version)) {
var qn = decl.QualifiedName;
if (decl.IsClassMethod)
qn = "+" + qn;
ObjCDeprecatedSelectors [qn] = version;
}
}
public override void VisitFunctionDecl (FunctionDecl decl, VisitKind visitKind)
{
if (visitKind == VisitKind.Enter && AttributeHelpers.FindObjcDeprecated (decl.Attrs, out VersionTuple version))
PlainCDeprecatedFunctions [decl.QualifiedName] = version;
}
}
}