public override IDeclaredElement Analyze(IDeclaration node, IHighlightingConsumer consumer, DaemonProcessKind kind) { if (!(node is IClassLikeDeclaration element)) { return(null); } var typeElement = element.DeclaredElement; if (typeElement != null) { if (myUnityApi.IsDescendantOfMonoBehaviour(typeElement)) { AddMonoBehaviourHiglighting(consumer, element, "Script", "Unity script", kind); } else if (myUnityApi.IsDescendantOf(KnownTypes.Editor, typeElement) || myUnityApi.IsDescendantOf(KnownTypes.EditorWindow, typeElement)) { AddEditorHiglighting(consumer, element, "Editor", "Custom Unity Editor", kind); } else if (myUnityApi.IsUnityType(typeElement)) { AddUnityTypeHighlighting(consumer, element, "Unity type", "Custom Unity type", kind); } else if (myUnityApi.IsUnityECSType(typeElement)) { AddUnityECSHighlighting(consumer, element, "Unity ECS", "Unity entity component system object", kind); } return(typeElement); } return(null); }
private bool IsEventHandler(UnityApi unityApi, [CanBeNull] IMethod method) { if (method == null) { return(false); } var type = method.GetContainingType(); if (!unityApi.IsUnityType(type)) { return(false); } var solution = method.GetSolution(); var assetSerializationMode = solution.GetComponent <AssetSerializationMode>(); var yamlParsingEnabled = solution.GetComponent <AssetIndexingSupport>().IsEnabled; // TODO: These two are usually used together. Consider combining in some way if (!yamlParsingEnabled.Value || !assetSerializationMode.IsForceText || !solution.GetComponent <DeferredCacheController>().CompletedOnce.Value) { return(unityApi.IsPotentialEventHandler(method, false)); // if yaml parsing is disabled, we will consider private methods as unused } var eventsCount = solution .GetComponent <UnityEventsElementContainer>() .GetAssetUsagesCount(method, out bool estimatedResult); return(eventsCount > 0 || estimatedResult); }
private bool GetCoroutineMustUseReturnValueAttribute(IClrDeclaredElement element, out ICollection <IAttributeInstance> collection) { collection = EmptyList <IAttributeInstance> .Instance; var method = element as IMethod; var type = method?.GetContainingType(); if (type == null || !myUnityApi.IsUnityType(type)) { return(false); } var returnType = method.ReturnType; var predefinedType = myPredefinedTypeCache.GetOrCreatePredefinedType(element.Module); if (!Equals(returnType, predefinedType.IEnumerator)) { return(false); } // The ctorArguments lambda result is not cached, so let's allocate everything up front var args = new[] { new AttributeValue( new ConstantValue("Coroutine will not continue if return value is ignored", predefinedType.String)) }; collection = new[] { new SpecialAttributeInstance(ourMustUseReturnValueAttributeFullName, GetModule(element), () => args) }; return(true); }
private bool IsEventHandler(UnityApi unityApi, [CanBeNull] IMethod method) { if (method == null) { return(false); } var type = method.GetContainingType(); if (!unityApi.IsUnityType(type)) { return(false); } var solution = method.GetSolution(); var assetSerializationMode = solution.GetComponent <AssetSerializationMode>(); var yamlParsingEnabled = solution.GetComponent <UnityYamlSupport>().IsUnityYamlParsingEnabled; // TODO: These two are usually used together. Consider combining in some way if (!yamlParsingEnabled.Value || !assetSerializationMode.IsForceText) { return(unityApi.IsPotentialEventHandler(method, false)); // if yaml parsing is disabled, we will consider private methods as unused } return(method.GetSolution().GetComponent <UnitySceneDataLocalCache>().IsEventHandler(method)); }
private bool GetCoroutineMustUseReturnValueAttribute(IClrDeclaredElement element, out ICollection <IAttributeInstance> collection) { collection = EmptyList <IAttributeInstance> .Instance; var method = element as IMethod; var type = method?.GetContainingType(); if (type == null || !myUnityApi.IsUnityType(type)) { return(false); } var returnType = method.ReturnType; var predefinedType = myPredefinedTypeCache.GetOrCreatePredefinedType(element.Module); if (!Equals(returnType, predefinedType.IEnumerator)) { return(false); } collection = new[] { new SpecialAttributeInstance( ourMustUseReturnValueAttributeFullName, myAnnotationsPsiModule, () => new[] { new AttributeValue( new ConstantValue("Coroutine will not continue if return value is ignored", predefinedType.String)), }) }; return(true); }
public IDeclaredElement Analyze(IDeclaration node, IHighlightingConsumer consumer, DaemonProcessKind kind) { if (!(node is IClassLikeDeclaration element)) { return(null); } var typeElement = element.DeclaredElement; if (typeElement != null) { if (myUnityApi.IsUnityType(typeElement)) { myContributor.AddUnityImplicitClassUsage(consumer, element, "Unity scripting component", "Scripting component", kind); } else if (myUnityApi.IsUnityECSType(typeElement)) { myContributor.AddUnityImplicitClassUsage(consumer, element, "Unity entity component system object", "Unity ECS", kind); } return(typeElement); } return(null); }
public override bool AddDeclarationHighlighting(IDeclaration node, IHighlightingConsumer consumer, DaemonProcessKind kind) { if (!(node is IClassLikeDeclaration element)) { return(false); } var typeElement = element.DeclaredElement; if (typeElement != null) { if (typeElement.DerivesFromMonoBehaviour()) { AddMonoBehaviourHiglighting(consumer, element, "Script", "Unity script", kind); } else if (typeElement.DerivesFrom(KnownTypes.Editor) || typeElement.DerivesFrom(KnownTypes.EditorWindow)) { AddEditorHiglighting(consumer, element, "Editor", "Custom Unity Editor", kind); } else if (typeElement.DerivesFromScriptableObject()) { AddMonoBehaviourHiglighting(consumer, element, "Scriptable object", "Scriptable Object", kind); } else if (myUnityApi.IsUnityType(typeElement)) { AddUnityTypeHighlighting(consumer, element, "Unity type", "Custom Unity type", kind); } else if (myUnityApi.IsUnityECSType(typeElement)) { AddUnityECSHighlighting(consumer, element, "Unity ECS", "Unity entity component system object", kind); } return(true); } return(false); }
// Best effort attempt at preventing false positives for type members that are actually being used inside a // scene. We don't have enough information to do this by name, so we'll mark all potential event handlers as // implicitly used by Unity // See https://github.com/Unity-Technologies/UnityCsReference/blob/02f8e8ca594f156dd6b2088ad89451143ca1b87e/Editor/Mono/Inspector/UnityEventDrawer.cs#L397 private static bool IsPotentialEventHandler(UnityApi unityApi, [CanBeNull] IMethod method) { if (method == null) { return(false); } if (!method.ReturnType.IsVoid()) { return(false); } // Type.GetMethods() returns public instance methods only if (method.GetAccessRights() != AccessRights.PUBLIC || method.IsStatic) { return(false); } return(unityApi.IsUnityType(method.GetContainingType()) && !method.HasAttributeInstance(PredefinedType.OBSOLETE_ATTRIBUTE_CLASS, true)); }
protected override void Run(IClassLikeDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { if (data.ProcessKind != DaemonProcessKind.VISIBLE_DOCUMENT) { return; } if (element.GetProject().IsUnityProject()) { var @class = element.DeclaredElement; if (@class != null) { if (myUnityApi.IsUnityType(@class)) { var documentRange = element.GetNameDocumentRange(); var highlighting = new UnityMarkOnGutter(element, documentRange, "Unity Scripting Type"); consumer.AddHighlighting(highlighting, documentRange); } } } }
private bool CheckPosition(CSharpCodeCompletionContext context, UnityApi unityApi, out IClassDeclaration classDeclaration, out AccessRights accessRights, out bool hasReturnType) { classDeclaration = GetClassDeclaration(context.NodeInFile); accessRights = AccessRights.NONE; hasReturnType = false; if (classDeclaration == null) { return(false); } // Make sure we're completing an identifier if (!(context.UnterminatedContext.TreeNode is ICSharpIdentifier identifier)) { return(false); } if (!unityApi.IsUnityType(classDeclaration.DeclaredElement)) { return(false); } // Make sure we're in the correct place for showing Unity event functions. if (!ShouldComplete(context.NodeInFile, identifier)) { return(false); } // We know we're in a place where we can complete, so now configure what we // complete and what we display hasReturnType = HasExistingReturnType(identifier, out var typeUsage); accessRights = GetAccessRights(typeUsage); return(true); }
public ICollection <IAttributeInstance> GetSpecialAttributeInstances(IClrDeclaredElement element) { var method = element as IMethod; var type = method?.GetContainingType(); if (type != null && myUnityApi.IsUnityType(type)) { var returnType = method.ReturnType; var predefinedType = myPredefinedTypeCache.GetOrCreatePredefinedType(element.Module); if (Equals(returnType, predefinedType.IEnumerator)) { var @string = predefinedType.String; return(new[] { new SpecialAttributeInstance( OurMustUseReturnValueAttributeFullName, myAnnotationsPsiModule, () => new[] { new AttributeValue(new ConstantValue("Coroutine will not continue if return value is ignored", @string)), }) }); } } return(EmptyList <IAttributeInstance> .Instance); }
private bool HasUnityBaseType(CSharpGeneratorContext context) { return(context.ClassDeclaration.DeclaredElement is IClass typeElement && myUnityApi.IsUnityType(typeElement)); }