Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support find usages and completion for animator #1982

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
baad829
refactor: use script usages containers through interface
MToolMakerJB Oct 2, 2020
774ddc1
clean up: add nullability annotations and format
MToolMakerJB Oct 5, 2020
2106c9a
refactor: extract logic from method
MToolMakerJB Oct 21, 2020
534d5fc
move unity dll downloading to base class
MToolMakerJB Oct 30, 2020
4dfd003
RIDER-43464 implement find usages for scripts in animator state and s…
MToolMakerJB Oct 21, 2020
b57ee8a
Merge remote-tracking branch 'origin/net203' into yarkov/RIDER-43464-…
MToolMakerJB Nov 3, 2020
75ff487
clean up: use assertion instead of elvis operator
MToolMakerJB Nov 3, 2020
32838f7
clean up: drop annotation
MToolMakerJB Nov 3, 2020
18b85fc
clean up: rename file
MToolMakerJB Nov 3, 2020
9a49130
clean up: remove unused import
MToolMakerJB Nov 3, 2020
f541194
refactor: check source file before building cache
MToolMakerJB Nov 3, 2020
d48592e
clean up: drop unused using
MToolMakerJB Nov 3, 2020
390d7ea
clean up
MToolMakerJB Nov 3, 2020
e9ce896
clean up: format
MToolMakerJB Nov 3, 2020
91c65a8
decrease tree view item's ids
MToolMakerJB Nov 3, 2020
0f183ec
refactor: return previous ToHierarchyReference implementation
MToolMakerJB Nov 3, 2020
41cf6a0
don't store guid to usage index
MToolMakerJB Nov 4, 2020
bf2799e
clean up: use null propagation
MToolMakerJB Nov 4, 2020
1ee4a88
clean up: join adjacent annotations
MToolMakerJB Nov 4, 2020
6ab5bb9
Merge remote-tracking branch 'origin/net203' into yarkov/RIDER-43464-…
MToolMakerJB Nov 6, 2020
332de8e
refactor: drop LINQ syntax
MToolMakerJB Nov 6, 2020
e28058a
refactor: drop cast
MToolMakerJB Nov 6, 2020
5cc292c
clean up: rename
MToolMakerJB Nov 6, 2020
873a8ae
clean up: inline method
MToolMakerJB Nov 6, 2020
14c49b0
clean up: inline method
MToolMakerJB Nov 6, 2020
41a4b87
clean up: inline method
MToolMakerJB Nov 6, 2020
1149a17
clean up: assert not null instead of throwing exception
MToolMakerJB Nov 6, 2020
1c97419
clean up: inline method
MToolMakerJB Nov 6, 2020
434438c
clean up: drop using
MToolMakerJB Nov 6, 2020
ef512eb
use GetPlainScalarText instead of GetText
MToolMakerJB Nov 6, 2020
b6fa950
fix compile
van800 Nov 9, 2020
707d9aa
fix DEXP-554913
krasnotsvetov Nov 2, 2020
08bd002
do not connect to out-of-date protocol, because it leads to different…
krasnotsvetov Nov 2, 2020
5b9f226
add animator state and state machine icons
MToolMakerJB Nov 13, 2020
7ab5593
RIDER-43464 support find usages for animation events
MToolMakerJB Nov 13, 2020
70c570a
Merge remote-tracking branch 'origin/net203' into yarkov/RIDER-43464-…
MToolMakerJB Nov 17, 2020
00afa1a
fix find usages grouping
MToolMakerJB Nov 17, 2020
598be45
Merge remote-tracking branch 'origin/net203' into yarkov/RIDER-43464-…
MToolMakerJB Nov 17, 2020
6462da8
Merge branch 'yarkov/RIDER-43464-support-find-usages-for-animation-ev…
MToolMakerJB Nov 17, 2020
304e215
fix find usages grouping
MToolMakerJB Nov 17, 2020
72d44b6
add icons
MToolMakerJB Nov 20, 2020
c250554
RIDER-17449 implement state name completion for play Animator.Play
MToolMakerJB Nov 20, 2020
49d4cf5
add icons for animation events
MToolMakerJB Nov 23, 2020
e0b7c1b
implement animator state name inspection
MToolMakerJB Nov 23, 2020
13c5b07
clean up: drop redundant null check
MToolMakerJB Dec 2, 2020
2df1681
optimize animator states completion and inspection
MToolMakerJB Dec 2, 2020
01190b3
don't store "irrelevant file -> state names list with zero length" en…
MToolMakerJB Dec 2, 2020
32545d5
clean up: format
MToolMakerJB Dec 2, 2020
df91f13
Merge branch 'yarkov/RIDER-17449-add-animator-play-method-completion'…
MToolMakerJB Dec 2, 2020
bd397de
optimize: use CountingSet to not to store redundant files
MToolMakerJB Dec 2, 2020
2482832
optimize: use CountingSet.Add(-count) instead of loop with CountingSe…
MToolMakerJB Dec 2, 2020
430706b
optimize: use CountingSet.Add(-count) instead of loop with CountingSe…
MToolMakerJB Dec 2, 2020
0af7f23
clean up: format
MToolMakerJB Dec 3, 2020
d399688
clean up: inline
MToolMakerJB Dec 3, 2020
11fb46e
fix animation events test
MToolMakerJB Dec 4, 2020
2ede69f
support find usages on parent classes methods
MToolMakerJB Dec 3, 2020
f929c5e
clean up: revert format and comment changes
MToolMakerJB Dec 5, 2020
ab9c1ce
support animation event find usages for properties
MToolMakerJB Dec 5, 2020
d6bc6ee
Merge branch 'yarkov/RIDER-43464-support-find-usages-for-animation-ev…
MToolMakerJB Dec 22, 2020
eba7e28
Merge remote-tracking branch 'origin/net211' into net211-yarkov-suppo…
MToolMakerJB Dec 22, 2020
5b3d8c8
change test according new tree format
MToolMakerJB Dec 22, 2020
ea170bf
fix test
MToolMakerJB Dec 23, 2020
427d4d8
fix test
MToolMakerJB Dec 23, 2020
06ad4c1
Merge remote-tracking branch 'origin/net211' into net211-yarkov-suppo…
MToolMakerJB Dec 23, 2020
727261b
Merge remote-tracking branch 'origin/net211' into net211-yarkov-suppo…
MToolMakerJB Dec 31, 2020
b9d0459
Merge remote-tracking branch 'origin/net211' into net211-yarkov-suppo…
MToolMakerJB Jan 11, 2021
bea88ac
don't access external files when adding events to data element
MToolMakerJB Jan 11, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,13 @@
The same shortcut is defined for another menu item
</Description>
</Tag>

<Tag externalName="UnknownAnimatorStateNameWarning.HIGHLIGHTING_ID" default="WARNING">
<Title>There is no animator state with the same name in the project.</Title>
<Description>
There is no animator state with the same name in the project.
</Description>
</Tag>
</Group>
</SeverityConfiguration>

Expand All @@ -289,6 +296,13 @@
to use ERROR mode)
-->

<Warning name="UnknownAnimatorStateName" configurableSeverity="Unity.UnknownAnimatorStateName">
<Parameter type="IArgument" name="argument" />
<Message value="There is no animator state with the same name in the project." />
<Range>Argument.GetDocumentRange()</Range>
<Behavour overlapResolvePolicy="WARNING" />
</Warning>

<Warning name="UnknownInputAxes" configurableSeverity="Unity.UnknownInputAxes">
<Parameter type="ITreeNode" name="node" />
<Message value="The name is not defined in the Input manager. The call is likely to fail at runtime." />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Linq;
using JetBrains.Annotations;
using JetBrains.DataFlow;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Daemon;
using JetBrains.ReSharper.Plugins.Unity.CSharp.Daemon.Errors;
using JetBrains.ReSharper.Plugins.Unity.Yaml;
using JetBrains.ReSharper.Plugins.Unity.Yaml.Psi.DeferredCaches.AnimatorUsages;
using JetBrains.ReSharper.Plugins.Yaml.Settings;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.Tree;

namespace JetBrains.ReSharper.Plugins.Unity.CSharp.Daemon.Stages.Analysis
{
[ElementProblemAnalyzer(typeof(IInvocationExpression),
HighlightingTypes = new[] {typeof(UnknownAnimatorStateNameWarning)})]
public class PlayAnimatorStateAnalyzer : UnityElementProblemAnalyzer<IInvocationExpression>
{
[NotNull] private readonly AssetSerializationMode myAssetSerializationMode;
[NotNull] private readonly YamlSupport myUnityYamlSupport;

public PlayAnimatorStateAnalyzer([NotNull] UnityApi unityApi,
[NotNull] AssetSerializationMode assetSerializationMode,
[NotNull] YamlSupport unityYamlSupport)
: base(unityApi)
{
myAssetSerializationMode = assetSerializationMode;
myUnityYamlSupport = unityYamlSupport;
}

protected override void Analyze([NotNull] IInvocationExpression invocation,
ElementProblemAnalyzerData data,
[NotNull] IHighlightingConsumer consumer)
{
if (!myAssetSerializationMode.IsForceText || !myUnityYamlSupport.IsParsingEnabled.Value) return;
var argument = GetStateNameArgumentFrom(invocation);
if (!(argument?.Value is ICSharpLiteralExpression literal) ||
!invocation.InvocationExpressionReference.IsAnimatorPlayMethod()) return;
var container = invocation.GetSolution().TryGetComponent<AnimatorScriptUsagesElementContainer>();
if (container == null ||
!(literal.ConstantValue.Value is string stateName) ||
container.ContainsStateName(stateName)) return;
consumer.AddHighlighting(new UnknownAnimatorStateNameWarning(argument));
}

[CanBeNull]
private static ICSharpArgument GetStateNameArgumentFrom([NotNull] IInvocationExpression invocationExpression)
{
return invocationExpression
.ArgumentList?
.Arguments
.FirstOrDefault(t =>
t != null &&
(t.IsNamedArgument && t.ArgumentName?.Equals("stateName") == true || !t.IsNamedArgument));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using JetBrains.Application.UI.Controls.BulbMenu.Items;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Daemon;
using JetBrains.ReSharper.Plugins.Unity.CSharp.Daemon.Errors;
using JetBrains.ReSharper.Plugins.Unity.CSharp.Daemon.Stages.ContextSystem;
using JetBrains.ReSharper.Plugins.Unity.CSharp.Daemon.Stages.PerformanceCriticalCodeAnalysis.ContextSystem;
using JetBrains.ReSharper.Plugins.Unity.Yaml.Psi.DeferredCaches.AnimationEventsUsages;
using JetBrains.ReSharper.Plugins.Unity.Yaml.Psi.DeferredCaches.UnityEvents;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp.Tree;
Expand All @@ -18,33 +20,91 @@ namespace JetBrains.ReSharper.Plugins.Unity.CSharp.Daemon.Stages.Highlightings.I
public class EventHandlerDetector : UnityDeclarationHighlightingProviderBase
{
protected readonly UnityEventsElementContainer UnityEventsElementContainer;

private readonly AnimationEventUsagesContainer myAnimationEventUsagesContainer;

public EventHandlerDetector(ISolution solution, IApplicationWideContextBoundSettingStore settingsStore,
UnityEventsElementContainer unityEventsElementContainer,
PerformanceCriticalContextProvider contextProvider)
PerformanceCriticalContextProvider contextProvider,
[NotNull] AnimationEventUsagesContainer animationEventUsagesContainer)
: base(solution, settingsStore, contextProvider)
{
UnityEventsElementContainer = unityEventsElementContainer;
myAnimationEventUsagesContainer = animationEventUsagesContainer;
}

public override bool AddDeclarationHighlighting(IDeclaration treeNode, IHighlightingConsumer consumer,
IReadOnlyCallGraphContext context)
{
var declaredElement = treeNode.DeclaredElement;
var method = declaredElement as IMethod;
if (method is IAccessor)
return false;
if (method is IAccessor)
return TryAddAnimationEventHighlightingForAccessorMethod(treeNode, consumer, context, method);

if (declaredElement is IProperty property)
{
TryAddAnimationEventHighlightingForPropertyGetter(treeNode, consumer, context, property);
method = property.Setter;
}

return method != null && TryAddMethodHighlighting(treeNode, consumer, context, method);
}

if (method != null && UnityEventsElementContainer.GetAssetUsagesCount(method, out _) > 0)
private bool TryAddAnimationEventHighlightingForAccessorMethod(ITreeNode treeNode,
IHighlightingConsumer consumer,
IReadOnlyCallGraphContext context,
IDeclaredElement method)
{
var isAnimationEvent = myAnimationEventUsagesContainer.GetEventUsagesCountFor(method, out _) > 0;
if (isAnimationEvent) AddAnimationEventHighlighting(treeNode, consumer, context);
return isAnimationEvent;
}

private void TryAddAnimationEventHighlightingForPropertyGetter(ITreeNode treeNode,
IHighlightingConsumer consumer,
IReadOnlyCallGraphContext context,
IProperty property)
{
var getter = property.Getter;
if (getter != null && myAnimationEventUsagesContainer.GetEventUsagesCountFor(getter, out _) > 0)
{
AddHighlighting(consumer, treeNode as ICSharpDeclaration, "Event handler", "Unity event handler", context);
return true;
AddAnimationEventHighlighting(treeNode, consumer, context);
}
}

return false;
private bool TryAddMethodHighlighting(IDeclaration treeNode, IHighlightingConsumer consumer, IReadOnlyCallGraphContext context,
IMethod method)
{
var eventHandlersCount = UnityEventsElementContainer.GetAssetUsagesCount(method, out _);
var animationEventsCount = myAnimationEventUsagesContainer.GetEventUsagesCountFor(method, out _);
if (eventHandlersCount + animationEventsCount <= 0) return false;
if (eventHandlersCount != 0 && animationEventsCount == 0)
AddEventHandlerHighlighting(treeNode, consumer, context);
if (eventHandlersCount == 0 && animationEventsCount != 0)
AddAnimationEventHighlighting(treeNode, consumer, context);
AddAnimationEventAndEventHandlerHighlighting(treeNode, consumer, context);
return true;
}

private void AddEventHandlerHighlighting([NotNull] ITreeNode treeNode,
[NotNull] IHighlightingConsumer consumer,
IReadOnlyCallGraphContext context)
{
AddHighlighting(consumer, treeNode as ICSharpDeclaration, "Event handler", "Unity event handler", context);
}

private void AddAnimationEventHighlighting([NotNull] ITreeNode treeNode,
[NotNull] IHighlightingConsumer consumer,
IReadOnlyCallGraphContext context)
{
AddHighlighting(consumer, treeNode as ICSharpDeclaration, "Animation event", "Unity animation event", context);
}

private void AddAnimationEventAndEventHandlerHighlighting([NotNull] ITreeNode treeNode,
[NotNull] IHighlightingConsumer consumer,
IReadOnlyCallGraphContext context)
{
AddHighlighting(consumer, treeNode as ICSharpDeclaration, "Animation event and event handler",
"Unity animation event and Unity animation event", context);
}

protected override void AddHighlighting(IHighlightingConsumer consumer, ICSharpDeclaration element, string text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using JetBrains.ReSharper.Daemon.UsageChecking;
using JetBrains.ReSharper.Plugins.Unity.Feature.Caches;
using JetBrains.ReSharper.Plugins.Unity.Yaml;
using JetBrains.ReSharper.Plugins.Unity.Yaml.Psi.DeferredCaches.AnimationEventsUsages;
using JetBrains.ReSharper.Plugins.Unity.Yaml.Psi.DeferredCaches.UnityEvents;
using JetBrains.ReSharper.Psi;

Expand Down Expand Up @@ -70,7 +71,9 @@ public bool SuppressUsageInspectionsOnElement(IDeclaredElement element, out Impl
return false;
}

if (IsEventHandler(unityApi, method) || IsRequiredSignatureMethod(method) ||
if (IsEventHandler(unityApi, method) ||
IsRequiredSignatureMethod(method) ||
IsAnimationEvent(solution, method) ||
IsImplicitlyUsedInterfaceMethod(method))
{
flags = ImplicitUseKindFlags.Access;
Expand All @@ -82,7 +85,9 @@ public bool SuppressUsageInspectionsOnElement(IDeclaredElement element, out Impl
flags = ImplicitUseKindFlags.Assign;
return true;

case IProperty property when IsEventHandler(unityApi, property.Setter) || IsImplicitlyUsedInterfaceProperty(property):
case IProperty property when IsEventHandler(unityApi, property.Setter) ||
IsImplicitlyUsedInterfaceProperty(property) ||
IsAnimationEvent(solution, property):
flags = ImplicitUseKindFlags.Assign;
return true;
}
Expand All @@ -91,6 +96,13 @@ public bool SuppressUsageInspectionsOnElement(IDeclaredElement element, out Impl
return false;
}

private static bool IsAnimationEvent(ISolution solution, IDeclaredElement property)
{
return solution
.GetComponent<AnimationEventUsagesContainer>()
.GetEventUsagesCountFor(property, out var isEstimatedResult) > 0 || isEstimatedResult;
}

private bool IsImplicitlyUsedInterfaceType(ITypeElement typeElement)
{
foreach (var implicitlyUsedTypeName in myImplicitlyUsedInterfaces)
Expand Down Expand Up @@ -152,7 +164,10 @@ private bool IsEventHandler(UnityApi unityApi, [CanBeNull] IMethod method)
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

return solution.GetComponent<UnityEventsElementContainer>().GetAssetUsagesCount(method, out bool estimatedResult) > 0 || estimatedResult;
var eventsCount = solution
.GetComponent<UnityEventsElementContainer>()
.GetAssetUsagesCount(method, out bool estimatedResult);
return eventsCount > 0 || estimatedResult;
}

// If the method is marked with an attribute that has a method that is itself marked with RequiredSignature,
Expand Down
18 changes: 15 additions & 3 deletions resharper/resharper-unity/src/CSharp/ExpressionReferenceUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,20 @@ private static bool IsSpecificMethod(IInvocationExpression invocationExpression,

public static bool IsSceneManagerSceneRelatedMethod(this IInvocationExpressionReference reference)
{
return IsSceneRelatedMethod(reference, IsSceneManagerLoadScene);
return IsRelatedMethod(reference, IsSceneManagerLoadScene);
}

public static bool IsEditorSceneManagerSceneRelatedMethod(this IInvocationExpressionReference reference)
{
return IsSceneRelatedMethod(reference, IsEditorSceneManagerLoadScene);
return IsRelatedMethod(reference, IsEditorSceneManagerLoadScene);
}

public static bool IsAnimatorPlayMethod(this IInvocationExpressionReference reference)
{
return IsRelatedMethod(reference, IsAnimatorPlay);
}

private static bool IsSceneRelatedMethod(IInvocationExpressionReference reference, Func<IMethod, bool> checker)
private static bool IsRelatedMethod(IInvocationExpressionReference reference, Func<IMethod, bool> checker)
{
var result = reference.Resolve();
if (checker(result.DeclaredElement as IMethod))
Expand Down Expand Up @@ -117,5 +122,12 @@ private static bool IsSceneManagerLoadScene(IMethod method)

return false;
}

private static bool IsAnimatorPlay(IMethod method)
{
return method != null &&
method.ShortName.StartsWith("Play") &&
method.GetContainingType()?.GetClrName().Equals(KnownTypes.Animator) == true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using JetBrains.ReSharper.Feature.Services.Lookup;
using JetBrains.ReSharper.Features.Intellisense.CodeCompletion.CSharp.Rules;
using JetBrains.ReSharper.Plugins.Unity.Yaml.Psi.Caches;
using JetBrains.ReSharper.Plugins.Unity.Yaml.Psi.DeferredCaches.AnimatorUsages;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.CSharp.Tree;
Expand Down Expand Up @@ -41,6 +42,11 @@ protected override bool AddLookupItems(CSharpCodeCompletionContext context, IIte
var cache = context.NodeInFile.GetSolution().GetComponent<UnityProjectSettingsCache>();
completionItems = cache.GetAllPossibleSceneNames();

} // animator state completion
else if (IsSpecificArgumentInSpecificMethod(context, out argumentLiteral, IsPlayAnimationMethod, IsCorrespondingArgument("stateName")))
{
var container = context.NodeInFile.GetSolution().GetComponent<AnimatorScriptUsagesElementContainer>();
completionItems = container.GetStateNames();
} // tag completion, tag == "..."
else if (IsTagEquality(context, out argumentLiteral))
{
Expand Down Expand Up @@ -137,6 +143,11 @@ private bool IsLoadSceneMethod(IInvocationExpression invocationExpression)
return invocationExpression.InvocationExpressionReference.IsSceneManagerSceneRelatedMethod() ||
invocationExpression.InvocationExpressionReference.IsEditorSceneManagerSceneRelatedMethod();
}

private static bool IsPlayAnimationMethod([NotNull] IInvocationExpression invocationExpression)
{
return invocationExpression.InvocationExpressionReference.IsAnimatorPlayMethod();
}

private bool IsTagEquality(CSharpCodeCompletionContext context, out ICSharpLiteralExpression stringLiteral)
{
Expand Down
Loading