Permalink
Browse files

Closed #128, adding the behavior's field type name (Behaves_like<Foo>…

…) to the ID for caching, normalizing type names across JetBrains' PSI and Metadata APIs and .NET's own type names
  • Loading branch information...
1 parent 4767654 commit faf2f716bc68eb257715fb5f710d995359243f4b @agross agross committed Jan 23, 2013
Showing with 389 additions and 325 deletions.
  1. +8 −38 Source/Machine.Specifications.ReSharperRunner.6.0/Factories/BehaviorFactory.cs
  2. +1 −0 Source/Machine.Specifications.ReSharperRunner.6.0/Factories/UnitTestTaskFactory.cs
  3. +1 −0 Source/Machine.Specifications.ReSharperRunner.6.0/Machine.Specifications.ReSharperRunner.6.0.csproj
  4. +55 −0 Source/Machine.Specifications.ReSharperRunner.6.0/NormalizedTypeName.cs
  5. +3 −3 Source/Machine.Specifications.ReSharperRunner.6.0/Presentation/BehaviorElement.cs
  6. +3 −4 ...ications.ReSharperRunner.6.0/Runners/Notifications/BehaviorSpecificationRemoteTaskNotification.cs
  7. +2 −4 ...fications.ReSharperRunner.6.0/Runners/Notifications/ContextSpecificationRemoteTaskNotification.cs
  8. +3 −3 Source/Machine.Specifications.ReSharperRunner.6.0/Runners/Notifications/RemoteTaskNotification.cs
  9. +1 −1 .../Machine.Specifications.ReSharperRunner.6.0/Runners/Notifications/SilentRemoteTaskNotification.cs
  10. +22 −12 Source/Machine.Specifications.ReSharperRunner.6.0/Runners/PerContextRunListener.cs
  11. +13 −1 Source/Machine.Specifications.ReSharperRunner.6.0/Tasks/BehaviorTask.cs
  12. +3 −0 Source/Machine.Specifications.ReSharperRunner.6.1/Machine.Specifications.ReSharperRunner.6.1.csproj
  13. +3 −0 Source/Machine.Specifications.ReSharperRunner.7.0/Machine.Specifications.ReSharperRunner.7.0.csproj
  14. +3 −0 Source/Machine.Specifications.ReSharperRunner.7.1/Machine.Specifications.ReSharperRunner.7.1.csproj
  15. +3 −0 Source/Machine.Specifications.dotCoverRunner.2.0/Machine.Specifications.dotCoverRunner.2.0.csproj
  16. +3 −0 Source/Machine.Specifications.dotCoverRunner.2.1/Machine.Specifications.dotCoverRunner.2.1.csproj
  17. +262 −259 Source/Machine.Specifications.dotCoverRunner.2.2/Machine.Specifications.dotCoverRunner.2.2.csproj
@@ -1,6 +1,3 @@
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-
using JetBrains.Metadata.Reader.API;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Psi;
@@ -19,7 +16,6 @@ internal class BehaviorFactory
readonly ProjectModelElementEnvoy _projectEnvoy;
readonly MSpecUnitTestProvider _provider;
readonly ContextCache _cache;
- static readonly IDictionary<string, string> TypeNameCache = new Dictionary<string, string>();
readonly IProject _project;
#if RESHARPER_61
readonly IUnitTestElementManager _manager;
@@ -58,16 +54,11 @@ public BehaviorElement CreateBehavior(IDeclaredElement field)
return null;
}
- string fullyQualifiedTypeName = null;
- if (field is ITypeOwner)
- {
- // Work around the difference in how the MetaData API and Psi API return different type strings for generics.
- TypeNameCache.TryGetValue(GetFirstGenericNormalizedTypeName(field), out fullyQualifiedTypeName);
- }
+ var fullyQualifiedTypeName = new NormalizedTypeName(field as ITypeOwner);
return GetOrCreateBehavior(_provider,
#if RESHARPER_61
- _manager, _psiModuleManager, _cacheManager,
+ _manager, _psiModuleManager, _cacheManager,
#endif
_project,
_projectEnvoy,
@@ -92,7 +83,7 @@ public BehaviorElement CreateBehavior(IDeclaredElement field)
bool isIgnored,
string fullyQualifiedTypeName)
{
- var id = BehaviorElement.CreateId(context, fieldName);
+ var id = BehaviorElement.CreateId(context, fullyQualifiedTypeName, fieldName);
#if RESHARPER_61
var behavior = manager.GetElementById(project, id) as BehaviorElement;
#else
@@ -107,7 +98,7 @@ public BehaviorElement CreateBehavior(IDeclaredElement field)
return new BehaviorElement(provider,
#if RESHARPER_61
- psiModuleManager, cacheManager,
+ psiModuleManager, cacheManager,
#else
provider.PsiModuleManager, provider.CacheManager,
#endif
@@ -123,12 +114,12 @@ public BehaviorElement CreateBehavior(ContextElement context, IMetadataField beh
{
var typeContainingBehaviorSpecifications = behavior.GetFirstGenericArgument();
- var fullyQualifiedTypeName = behavior.FirstGenericArgumentClass().FullyQualifiedName();
- var typeName = GetNormalizedTypeName(fullyQualifiedTypeName);
+ var metadataTypeName = behavior.FirstGenericArgumentClass().FullyQualifiedName();
+ var fullyQualifiedTypeName = new NormalizedTypeName(metadataTypeName);
var behaviorElement = GetOrCreateBehavior(_provider,
#if RESHARPER_61
- _manager, _psiModuleManager, _cacheManager,
+ _manager, _psiModuleManager, _cacheManager,
#endif
_project,
_projectEnvoy,
@@ -138,28 +129,7 @@ public BehaviorElement CreateBehavior(ContextElement context, IMetadataField beh
behavior.IsIgnored() || typeContainingBehaviorSpecifications.IsIgnored(),
fullyQualifiedTypeName);
- if (!TypeNameCache.ContainsKey(typeName))
- {
- TypeNameCache.Add(typeName, fullyQualifiedTypeName);
- }
-
return behaviorElement;
}
-
- static string GetFirstGenericNormalizedTypeName(IDeclaredElement field)
- {
- var typeName = ((ITypeOwner) field).Type.ToString();
- typeName = typeName.Substring(typeName.IndexOf("-> ") + 3);
- typeName = typeName.Remove(typeName.Length - 1);
- typeName = Regex.Replace(typeName, @"\[.*->\s", "[");
- return typeName;
- }
-
- static string GetNormalizedTypeName(string fullyQualifiedTypeName)
- {
- var typeName = Regex.Replace(fullyQualifiedTypeName, @"\,.+]", "]");
- typeName = Regex.Replace(typeName, @"\[\[", "[");
- return typeName;
- }
}
-}
+}
@@ -49,6 +49,7 @@ public UnitTestTask CreateBehaviorTask(ContextElement context, BehaviorElement b
new BehaviorTask(_providerId,
context.AssemblyLocation,
context.GetTypeClrName(),
+ behavior.FullyQualifiedTypeName,
behavior.FieldName,
false));
}
@@ -136,6 +136,7 @@
<Compile Include="MSpecUnitTestElementComparer.cs" />
<Compile Include="MSpecUnitTestPresenter.cs" />
<Compile Include="MSpecUnitTestProvider.cs" />
+ <Compile Include="NormalizedTypeName.cs" />
<Compile Include="Presentation\BehaviorElement.cs" />
<Compile Include="Presentation\BehaviorSpecificationElement.cs" />
<Compile Include="Presentation\ContextElement.cs" />
@@ -0,0 +1,55 @@
+using System;
+using System.Text.RegularExpressions;
+
+using JetBrains.ReSharper.Psi;
+
+namespace Machine.Specifications.ReSharperRunner
+{
+ class NormalizedTypeName
+ {
+ readonly string _normalized;
+ static readonly Regex OpenBracketFollowedByDart = new Regex(@"\[.*->\s", RegexOptions.Compiled);
+ static readonly Regex DoubleOpenBrackets = new Regex(@"\[\[", RegexOptions.Compiled);
+
+ public NormalizedTypeName(string fullyQualifiedTypeName)
+ {
+ _normalized = QualifiedNetNotationWithoutAssembly(fullyQualifiedTypeName);
+ }
+
+ public NormalizedTypeName(ITypeOwner field)
+ {
+ _normalized = QualifiedNetNotationWithoutAssembly(field);
+ }
+
+ public override string ToString()
+ {
+ return _normalized;
+ }
+
+ public static implicit operator String(NormalizedTypeName instance)
+ {
+ return instance.ToString();
+ }
+
+ static string QualifiedNetNotationWithoutAssembly(ITypeOwner field)
+ {
+ if (field == null)
+ {
+ throw new ArgumentException("Tried to create normalized type from a null reference.");
+ }
+
+ var typeName = field.Type.ToString();
+ typeName = typeName.Substring(typeName.IndexOf("-> ") + 3);
+ typeName = typeName.Remove(typeName.Length - 1);
+ typeName = OpenBracketFollowedByDart.Replace(typeName, "[");
+ return typeName;
+ }
+
+ static string QualifiedNetNotationWithoutAssembly(string fullyQualifiedTypeName)
+ {
+ var typeName = Regex.Replace(fullyQualifiedTypeName, @"\,.+]", "]");
+ typeName = DoubleOpenBrackets.Replace(typeName, "[");
+ return typeName;
+ }
+ }
+}
@@ -29,8 +29,8 @@ public class BehaviorElement : FieldElement
string fullyQualifiedTypeName)
: base(provider, psiModuleManager, cacheManager, context, projectEnvoy, declaringTypeName, fieldName, isIgnored || context.Explicit)
{
- _id = CreateId(context, fieldName);
FullyQualifiedTypeName = fullyQualifiedTypeName;
+ _id = CreateId(context, fullyQualifiedTypeName, fieldName);
}
public ContextElement Context
@@ -103,9 +103,9 @@ public override string Id
get { return _id; }
}
- public static string CreateId(ContextElement contextElement, string fieldName)
+ public static string CreateId(ContextElement contextElement, string fullyQualifiedTypeName, string fieldName)
{
- return String.Format("{0}.{1}", contextElement.Id, fieldName);
+ return String.Format("{0}.{1}.{2}", contextElement.Id, fullyQualifiedTypeName, fieldName);
}
}
}
@@ -3,14 +3,13 @@
using JetBrains.ReSharper.TaskRunnerFramework;
using Machine.Specifications.ReSharperRunner.Tasks;
-using Machine.Specifications.Utility;
-using Machine.Specifications.Utility.Internal;
namespace Machine.Specifications.ReSharperRunner.Runners.Notifications
{
internal class BehaviorSpecificationRemoteTaskNotification : RemoteTaskNotification
{
readonly TaskExecutionNode _node;
+
readonly BehaviorSpecificationTask _task;
public BehaviorSpecificationRemoteTaskNotification(TaskExecutionNode node)
@@ -24,9 +23,9 @@ protected override string ContainingType
get { return _task.BehaviorTypeName; }
}
- protected override string Name
+ protected override string FieldName
{
- get { return _task.SpecificationFieldName.ToFormat(); }
+ get { return _task.SpecificationFieldName; }
}
public override IEnumerable<RemoteTask> RemoteTasks
@@ -3,8 +3,6 @@
using JetBrains.ReSharper.TaskRunnerFramework;
using Machine.Specifications.ReSharperRunner.Tasks;
-using Machine.Specifications.Utility;
-using Machine.Specifications.Utility.Internal;
namespace Machine.Specifications.ReSharperRunner.Runners.Notifications
{
@@ -24,9 +22,9 @@ protected override string ContainingType
get { return _task.ContextTypeName; }
}
- protected override string Name
+ protected override string FieldName
{
- get { return _task.SpecificationFieldName.ToFormat(); }
+ get { return _task.SpecificationFieldName; }
}
public override IEnumerable<RemoteTask> RemoteTasks
@@ -13,7 +13,7 @@ internal abstract class RemoteTaskNotification
get;
}
- protected abstract string Name
+ protected abstract string FieldName
{
get;
}
@@ -25,8 +25,8 @@ internal abstract class RemoteTaskNotification
public virtual bool Matches(SpecificationInfo specification)
{
- return ContainingType == specification.ContainingType &&
- Name == specification.Name;
+ return ContainingType == new NormalizedTypeName(specification.ContainingType) &&
+ FieldName == specification.FieldName;
}
}
}
@@ -11,7 +11,7 @@ protected override string ContainingType
get { return null; }
}
- protected override string Name
+ protected override string FieldName
{
get { return null; }
}
@@ -111,23 +111,33 @@ internal void RegisterTaskNotification(RemoteTaskNotification notification)
Action<Action<RemoteTask>> CreateTaskNotificationFor(SpecificationInfo specification)
{
return actionToBePerformedForEachTask =>
+ {
+ bool invoked = false;
+
+ foreach (var notification in _taskNotifications)
{
- foreach (var notification in _taskNotifications)
+ if (notification.Matches(specification))
{
- if (notification.Matches(specification))
+ Debug.WriteLine(String.Format("Notification for {0} {1}, with {2} remote tasks",
+ specification.ContainingType,
+ specification.FieldName,
+ notification.RemoteTasks.Count()));
+ invoked = true;
+
+ foreach (var task in notification.RemoteTasks)
{
- Debug.WriteLine(String.Format("Notifcation for {0} {1}, with {2} remote tasks",
- specification.ContainingType,
- specification.FieldName,
- notification.RemoteTasks.Count()));
-
- foreach (var task in notification.RemoteTasks)
- {
- actionToBePerformedForEachTask(task);
- }
+ actionToBePerformedForEachTask(task);
}
}
- };
+ }
+
+ if (!invoked)
+ {
+ Debug.WriteLine(String.Format("IGNORED notification for {0} {1}",
+ specification.ContainingType,
+ specification.FieldName));
+ }
+ };
}
delegate void Action<T>(T arg);
@@ -7,22 +7,31 @@ namespace Machine.Specifications.ReSharperRunner.Tasks
internal class BehaviorTask : Task, IEquatable<BehaviorTask>
{
readonly string _behaviorFieldName;
+ readonly string _behaviorFieldType;
public BehaviorTask(XmlElement element) : base(element)
{
+ _behaviorFieldType = GetXmlAttribute(element, "BehaviorFieldType");
_behaviorFieldName = GetXmlAttribute(element, "BehaviorFieldName");
}
public BehaviorTask(string providerId,
string assemblyLocation,
string contextTypeName,
+ string behaviorFieldType,
string behaviorFieldName,
bool runExplicitly)
: base(providerId, assemblyLocation, contextTypeName, runExplicitly)
{
+ _behaviorFieldType = behaviorFieldType;
_behaviorFieldName = behaviorFieldName;
}
+ public string BehaviorFieldType
+ {
+ get { return _behaviorFieldType; }
+ }
+
public string BehaviorFieldName
{
get { return _behaviorFieldName; }
@@ -32,6 +41,7 @@ public override void SaveXml(XmlElement element)
{
base.SaveXml(element);
+ SetXmlAttribute(element, "BehaviorFieldType", BehaviorFieldType);
SetXmlAttribute(element, "BehaviorFieldName", BehaviorFieldName);
}
@@ -45,6 +55,7 @@ public override int GetHashCode()
unchecked
{
int result = base.GetHashCode();
+ result = (result * 397) ^ BehaviorFieldType.GetHashCode();
result = (result * 397) ^ BehaviorFieldName.GetHashCode();
return result;
}
@@ -62,7 +73,8 @@ public bool Equals(BehaviorTask other)
return false;
}
- return Equals(BehaviorFieldName, other.BehaviorFieldName);
+ return Equals(BehaviorFieldType, other.BehaviorFieldType) &&
+ Equals(BehaviorFieldName, other.BehaviorFieldName);
}
}
}
@@ -126,6 +126,9 @@
<Compile Include="..\Machine.Specifications.ReSharperRunner.6.0\Factories\UnitTestTaskFactory.cs">
<Link>Factories\UnitTestTaskFactory.cs</Link>
</Compile>
+ <Compile Include="..\Machine.Specifications.ReSharperRunner.6.0\NormalizedTypeName.cs">
+ <Link>NormalizedTypeName.cs</Link>
+ </Compile>
<Compile Include="..\Machine.Specifications.ReSharperRunner.6.0\PsiExtensions.cs">
<Link>PsiExtensions.cs</Link>
</Compile>
@@ -129,6 +129,9 @@
<Compile Include="..\Machine.Specifications.ReSharperRunner.6.0\MSpecUnitTestElementComparer.cs">
<Link>MSpecUnitTestElementComparer.cs</Link>
</Compile>
+ <Compile Include="..\Machine.Specifications.ReSharperRunner.6.0\NormalizedTypeName.cs">
+ <Link>NormalizedTypeName.cs</Link>
+ </Compile>
<Compile Include="..\Machine.Specifications.ReSharperRunner.6.0\PsiExtensions.cs">
<Link>PsiExtensions.cs</Link>
</Compile>
Oops, something went wrong.

0 comments on commit faf2f71

Please sign in to comment.