public override bool AddDeclarationHighlighting(IDeclaration element, IHighlightingConsumer consumer, IReadOnlyCallGraphContext context) { if (!(element is IFieldDeclaration field)) { return(false); } var declaredElement = field.DeclaredElement; if (declaredElement == null) { return(false); } bool isSerializedField = myUnityApi.IsSerialisedField(declaredElement); if (isSerializedField) { const string displayText = "Serializable"; const string baseTooltip = "This field is initialized from Inspector"; var containingType = declaredElement.GetContainingType(); if (containingType.DerivesFromMonoBehaviour() || containingType.DerivesFromScriptableObject()) { AddMonoBehaviourHighlighting(consumer, field, displayText, baseTooltip, context); return(true); } AddSerializableHighlighting(consumer, field, displayText, "This field is serialized by Unity", context); return(false); } return(false); }
public override IDeclaredElement Analyze(IDeclaration element, IHighlightingConsumer consumer, DaemonProcessKind kind) { if (!(element is IFieldDeclaration field)) { return(null); } var declaredElement = field.DeclaredElement; if (declaredElement == null) { return(null); } bool isSerializedField = myUnityApi.IsSerialisedField(declaredElement); if (isSerializedField) { const string displayText = "Serializable"; const string baseTooltip = "This field is initialized from Inspector"; if (myUnityApi.IsDescendantOfMonoBehaviour(declaredElement.GetContainingType())) { AddMonoBehaviourHighlighting(consumer, field, displayText, baseTooltip, kind); return(declaredElement); } else if (myUnityApi.IsDescendantOfScriptableObject(declaredElement.GetContainingType())) { AddScriptableObjectHighlighting(consumer, field, displayText, baseTooltip, kind); return(declaredElement); } else if (myUnityApi.IsInjectedField(declaredElement)) { AddECSHighlighting(consumer, field, displayText, "This field is injected by Unity", kind); return(declaredElement); } else { AddSerializableHighlighting(consumer, field, displayText, "This field is serialized by Unity", kind); } return(null); } return(null); }
void IChangeNamingRuleWindowProvider.ShowSettingsDialog(string ruleName, NamingPolicy policyToChange, IDeclaredElement declaredElement, IPsiSourceFile psiSourceFile, ITextControl textControl, NamingManager namingManager, IUIApplicationSimple uiApplicationSimple, ISolution solution) { if (declaredElement is IField field && myUnityApi.IsSerialisedField(field)) { var optionsDialogOwner = solution.TryGetComponent <IOptionsDialogViewOwner>(); if (optionsDialogOwner != null) { Logger.Catch(() => optionsDialogOwner.Show(page: UnityOptionsPage.Name)); return; } } base.ShowSettingsDialog(ruleName, policyToChange, declaredElement, psiSourceFile, textControl, namingManager, uiApplicationSimple, solution); }
public IDeclaredElement Analyze(IDeclaration element, IHighlightingConsumer consumer, DaemonProcessKind kind) { if (!(element is IFieldDeclaration field)) { return(null); } var declaredElement = field.DeclaredElement; if (declaredElement == null) { return(null); } bool isSerializedField = myUnityApi.IsSerialisedField(declaredElement); if (isSerializedField && ( myUnityApi.IsDescendantOfMonoBehaviour(declaredElement.GetContainingType()) || myUnityApi.IsDescendantOfScriptableObject(declaredElement.GetContainingType()) ) || myUnityApi.IsInjectedField(declaredElement)) { myImplicitUsageHighlightingContributor.AddUnityImplicitFieldUsage(consumer, field, "This field is initialised by Unity", "Set by Unity", kind); return(declaredElement); } if (isSerializedField && declaredElement.GetAttributeInstances(false) .All(t => !t.GetClrName().Equals(KnownTypes.SerializeField))) { myImplicitUsageHighlightingContributor.AddUnityImplicitFieldUsage(consumer, field, "This field is serialized by Unity", "Serializable", kind); return(declaredElement); } return(null); }
// Treat Unity's RangeAttribute as ReSharper's ValueRangeAttribute annotation private bool GetValueRangeAttribute(IClrDeclaredElement element, out ICollection <IAttributeInstance> collection) { collection = EmptyList <IAttributeInstance> .InstanceList; if (!(element is IField field) || !element.IsFromUnityProject()) { return(false); } if (!myUnityApi.IsSerialisedField(field)) { return(false); } // Integer value analysis only works on integers, but it will make use of annotations applied to values that // are convertible to int, such as byte/sbyte and short/ushort. It doesn't currently use values applied to // uint, or long/ulong, but it is planned, so we'll apply to all sizes of integer. var predefinedType = myPredefinedTypeCache.GetOrCreatePredefinedType(element.Module); if (!Equals(field.Type, predefinedType.Int) && !Equals(field.Type, predefinedType.Uint) && !Equals(field.Type, predefinedType.Long) && !Equals(field.Type, predefinedType.Ulong) && !Equals(field.Type, predefinedType.Short) && !Equals(field.Type, predefinedType.Ushort) && !Equals(field.Type, predefinedType.Byte) && !Equals(field.Type, predefinedType.Sbyte)) { return(false); } foreach (var attributeInstance in field.GetAttributeInstances(KnownTypes.RangeAttribute, false)) { // Values are floats, but applied to an integer field. Convert to integer values var unityFrom = attributeInstance.PositionParameter(0); var unityTo = attributeInstance.PositionParameter(1); if (!unityFrom.IsConstant || !unityFrom.ConstantValue.IsFloat() || !unityTo.IsConstant || !unityTo.ConstantValue.IsFloat()) { continue; } // The check above means this is not null. We take the floor, because that's how Unity works. // E.g. Unity's Inspector treats [Range(1.7f, 10.9f)] as between 1 and 10 inclusive var from = Convert.ToInt64(Math.Floor((float)unityFrom.ConstantValue.Value.NotNull())); var to = Convert.ToInt64(Math.Floor((float)unityTo.ConstantValue.Value.NotNull())); collection = CreateRangeAttributeInstance(element, predefinedType, from, to); return(true); } foreach (var attributeInstance in field.GetAttributeInstances(KnownTypes.MinAttribute, false)) { var unityMinValue = attributeInstance.PositionParameter(0); if (!unityMinValue.IsConstant || !unityMinValue.ConstantValue.IsFloat()) { continue; } // Even though the constructor for ValueRange takes long, it only works with int.MaxValue var min = Convert.ToInt64(Math.Floor((float)unityMinValue.ConstantValue.Value.NotNull())); var max = int.MaxValue; collection = CreateRangeAttributeInstance(element, predefinedType, min, max); return(true); } return(false); }