Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

ReSharper support for derived Subject attributes

  • Loading branch information...
commit 100958467dd86606ab2dbc91ea1e572ab3a13d3a 1 parent 12c6f6b
@citizenmatt citizenmatt authored agross committed
View
7 Machine.Specifications.sln
@@ -90,6 +90,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Machine.Specifications.ReSh
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Machine.Specifications.dotCoverRunner.2.2", "Source\Machine.Specifications.dotCoverRunner.2.2\Machine.Specifications.dotCoverRunner.2.2.csproj", "{B88940C4-9552-4C47-85F2-33E820CD9FD1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Machine.Specifications.Example.DerivedSubject", "Source\Machine.Specifications.Example.DerivedSubject\Machine.Specifications.Example.DerivedSubject.csproj", "{13650EC6-35A0-429A-A779-DCA0214E7F79}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -228,6 +230,10 @@ Global
{B88940C4-9552-4C47-85F2-33E820CD9FD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B88940C4-9552-4C47-85F2-33E820CD9FD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B88940C4-9552-4C47-85F2-33E820CD9FD1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {13650EC6-35A0-429A-A779-DCA0214E7F79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {13650EC6-35A0-429A-A779-DCA0214E7F79}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {13650EC6-35A0-429A-A779-DCA0214E7F79}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {13650EC6-35A0-429A-A779-DCA0214E7F79}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -242,6 +248,7 @@ Global
{1295C389-FCE4-4425-93E4-E4AE239B3E35} = {85BC2C4A-493A-476C-971E-BE9CE51ECF5D}
{0CE411DF-CFC3-45E3-96AD-2F872D99E1B1} = {85BC2C4A-493A-476C-971E-BE9CE51ECF5D}
{A6B234F5-5D96-4809-BD25-86F6544BF838} = {85BC2C4A-493A-476C-971E-BE9CE51ECF5D}
+ {13650EC6-35A0-429A-A779-DCA0214E7F79} = {85BC2C4A-493A-476C-971E-BE9CE51ECF5D}
{E57865B9-C7EF-4340-8AF2-5D85F2545EC6} = {3D475ECE-C800-4087-8FC5-B9A13E76ABC4}
{CFF4B323-24C1-4B19-98CA-7DF92755458E} = {3D475ECE-C800-4087-8FC5-B9A13E76ABC4}
{F25C7917-4ED6-4261-B262-43C56D0CD37F} = {3D475ECE-C800-4087-8FC5-B9A13E76ABC4}
View
66 Source/Machine.Specifications.Example.DerivedSubject/DerivedSubjectSpecs.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Machine.Specifications.Example.DerivedSubject
+{
+ public class Account
+ {
+ private decimal _balance;
+
+ public decimal Balance
+ {
+ get { return _balance; }
+ set { _balance = value; }
+ }
+
+ public void Transfer(decimal amount, Account toAccount)
+ {
+ if (amount > _balance)
+ {
+ throw new Exception(String.Format("Cannot transfer ${0}. The available balance is ${1}.", amount, _balance));
+ }
+
+ _balance -= amount;
+ toAccount.Balance += amount;
+ }
+ }
+
+ [MySubject(typeof(Account), "Funds transfer")]
+ public class when_transferring_between_two_accounts_with_derived_subject
+ : AccountSpecs
+ {
+ Because of = () =>
+ fromAccount.Transfer(1m, toAccount);
+
+ It should_debit_the_from_account_by_the_amount_transferred = () =>
+ fromAccount.Balance.ShouldEqual(0m);
+
+ It should_credit_the_to_account_by_the_amount_transferred = () =>
+ toAccount.Balance.ShouldEqual(2m);
+ }
+
+ [Subject(typeof(Account), "Funds transfer")]
+ public class when_transferring_between_two_accounts_with_normal_subject
+ : AccountSpecs
+ {
+ Because of = () =>
+ fromAccount.Transfer(1m, toAccount);
+
+ It should_debit_the_from_account_by_the_amount_transferred = () =>
+ fromAccount.Balance.ShouldEqual(0m);
+
+ It should_credit_the_to_account_by_the_amount_transferred = () =>
+ toAccount.Balance.ShouldEqual(2m);
+ }
+
+ public abstract class AccountSpecs
+ {
+ protected static Account fromAccount;
+ protected static Account toAccount;
+
+ Establish context = () =>
+ {
+ fromAccount = new Account { Balance = 1m };
+ toAccount = new Account { Balance = 1m };
+ };
+ }
+}
View
106 Source/Machine.Specifications.Example.DerivedSubject/Machine.Specifications.Example.DerivedSubject.csproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{13650EC6-35A0-429A-A779-DCA0214E7F79}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Machine.Specifications.Example.DerivedSubject</RootNamespace>
+ <AssemblyName>Machine.Specifications.Example.DerivedSubject</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoWarn>169</NoWarn>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\SharedAssemblyInfo.cs">
+ <Link>Properties\SharedAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\VersionInfo.cs">
+ <Link>Properties\VersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="DerivedSubjectSpecs.cs" />
+ <Compile Include="MySubjectAttribute.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Machine.Specifications\Machine.Specifications.csproj">
+ <Project>{CCD02629-1262-4F78-9E9F-AC97B942D0E7}</Project>
+ <Name>Machine.Specifications</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
19 Source/Machine.Specifications.Example.DerivedSubject/MySubjectAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Machine.Specifications.Example.DerivedSubject
+{
+ public class MySubjectAttribute : SubjectAttribute
+ {
+ public MySubjectAttribute(Type subjectType) : base(subjectType)
+ {
+ }
+
+ public MySubjectAttribute(Type subjectType, string subject) : base(subjectType, subject)
+ {
+ }
+
+ public MySubjectAttribute(string subject) : base(subject)
+ {
+ }
+ }
+}
View
21 Source/Machine.Specifications.Example.DerivedSubject/Properties/AssemblyInfo.cs
@@ -0,0 +1,21 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Machine.Specifications.Example.DerivedSubject")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("e01bfd4e-4f67-4681-b84e-1aaa4217f239")]
View
9 Source/Machine.Specifications.ReSharperRunner.6.0/MetadataExtensions.cs
@@ -51,7 +51,7 @@ public static IEnumerable<IMetadataField> GetBehaviors(this IMetadataTypeInfo ty
public static string GetSubjectString(this IMetadataEntity type)
{
- var attributes = type.GetCustomAttributes(typeof(SubjectAttribute).FullName);
+ var attributes = GetSubjectAttributes(type);
if (attributes.Count != 1)
{
var asMember = type as IMetadataTypeMember;
@@ -78,6 +78,13 @@ public static string GetSubjectString(this IMetadataEntity type)
return String.Join(" ", parameters);
}
+ private static IList<IMetadataCustomAttribute> GetSubjectAttributes(IMetadataEntity type)
+ {
+ return (from customAttribute in type.CustomAttributes
+ where customAttribute.AndAllBaseTypes().Any(i => i.FullyQualifiedName == typeof(SubjectAttribute).FullName)
+ select customAttribute).ToList();
+ }
+
public static ICollection<string> GetTags(this IMetadataEntity type)
{
return type.AndAllBaseTypes()
View
14 Source/Machine.Specifications.ReSharperRunner.6.0/PsiExtensions.cs
@@ -9,6 +9,8 @@
using CLRTypeName = JetBrains.ReSharper.Psi.ClrTypeName;
+using JetBrains.ReSharper.Psi.Util;
+
namespace Machine.Specifications.ReSharperRunner
{
internal static partial class PsiExtensions
@@ -129,9 +131,7 @@ public static bool IsIgnored(this IDeclaredElement element)
public static string GetSubjectString(this IAttributesOwner type)
{
- var attribute = type.GetAttributeInstances(new CLRTypeName(typeof(SubjectAttribute).FullName), true)
- .FirstOrDefault();
-
+ var attribute = GetSubjectAttribute(type);
if (attribute == null)
{
var containingType = type.GetContainingType();
@@ -179,6 +179,14 @@ public static string GetSubjectString(this IAttributesOwner type)
}
}
+ private static IAttributeInstance GetSubjectAttribute(IAttributesSet type)
+ {
+ return (from a in type.GetAttributeInstances(true)
+ let h = (new[] { a.AttributeType}).Concat(a.AttributeType.GetSuperTypes())
+ where h.Any(t => t.GetClrName().FullName == typeof(SubjectAttribute).FullName)
+ select a).FirstOrDefault();
+ }
+
public static ICollection<string> GetTags(this IAttributesOwner type)
{
return type.GetAttributeInstances(new CLRTypeName(typeof(TagsAttribute).FullName), true)
Please sign in to comment.
Something went wrong with that request. Please try again.