diff --git a/.gitignore b/.gitignore
index f5c287d..636e668 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
/*/*.csproj.user
/*/bin/*
/*/obj/*
-/*/StyleCop.cache
\ No newline at end of file
+/*/StyleCop.cache
+Whut.AttachTo.sln.GhostDoc.xml
diff --git a/Whut.AttachTo/AttachTo.vsct b/Whut.AttachTo/AttachTo.vsct
index 3bde0b6..516a59d 100755
--- a/Whut.AttachTo/AttachTo.vsct
+++ b/Whut.AttachTo/AttachTo.vsct
@@ -15,13 +15,13 @@
defining some of the constants that we will use inside the file. -->
-
+
-
+
-
+
@@ -40,7 +40,7 @@
must be a menu. -->
@@ -74,7 +74,7 @@
Attach to IIS Express
-
+
@@ -93,7 +93,7 @@
bitmap strip containing the bitmaps and then there are the numeric ids of the elements used
inside a button definition. An important aspect of this declaration is that the element id
must be the actual index (1-based) of the bitmap inside the bitmap strip. -->
-
+
@@ -109,12 +109,13 @@
-
+
+
diff --git a/Whut.AttachTo/AttachToPackage.cs b/Whut.AttachTo/AttachToPackage.cs
index 05d10ad..99cc2fb 100755
--- a/Whut.AttachTo/AttachToPackage.cs
+++ b/Whut.AttachTo/AttachToPackage.cs
@@ -1,16 +1,51 @@
-using System;
-using System.ComponentModel.Design;
-using System.Linq;
-using System.Runtime.InteropServices;
-using EnvDTE;
-using Microsoft.VisualStudio;
-using Microsoft.VisualStudio.Shell;
+using PostSharp.Patterns.Diagnostics;
+using PostSharp.Extensibility;
+// --------------------------------------------------------------------------------------------------------------------
+//
+//
+//
+//
+// This is the class that implements the package exposed by this assembly.
+// The minimum requirement for a class to be considered a valid package for Visual Studio
+// is to implement the IVsPackage interface and register itself with the shell.
+// This package uses the helper classes defined inside the Managed Package Framework (MPF)
+// to do it: it derives from the Package class that provides the implementation of the
+// IVsPackage interface and uses the registration attributes defined in the framework to
+// register itself and its components with the shell.
+//
+// --------------------------------------------------------------------------------------------------------------------
namespace Whut.AttachTo
{
- //// This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is a package.
+ using System;
+ using System.ComponentModel.Design;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Linq;
+ using System.Runtime.InteropServices;
+
+ using EnvDTE;
+
+ using Microsoft.VisualStudio;
+ using Microsoft.VisualStudio.Shell;
+
+ using Process = EnvDTE.Process;
+
+ ///
+ /// This is the class that implements the package exposed by this assembly.
+ /// The minimum requirement for a class to be considered a valid package for Visual Studio
+ /// is to implement the IVsPackage interface and register itself with the shell.
+ /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
+ /// to do it: it derives from the Package class that provides the implementation of the
+ /// IVsPackage interface and uses the registration attributes defined in the framework to
+ /// register itself and its components with the shell.
+ ///
+ //// This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is
+ //// a package.
[PackageRegistration(UseManagedResourcesOnly = true)]
- //// This attribute is used to register the informations needed to show the this package in the Help/About dialog of Visual Studio.
+ //// This attribute is used to register the information needed to show this package
+ //// in the Help/About dialog of Visual Studio.
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
//// This attribute is needed to let the shell know that this package exposes some menus.
[ProvideMenuResource("Menus.ctmenu", 1)]
@@ -20,34 +55,93 @@ namespace Whut.AttachTo
[ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string)]
public sealed class AttachToPackage : Package
{
+ #region Methods
+
+ ///
+ /// Initialization of the package; this method is called right after the package is sited, so this is the place
+ /// where you can put all the initialization code that rely on services provided by VisualStudio.
+ ///
protected override void Initialize()
{
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this));
base.Initialize();
- OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
+ // Add our command handlers for menu (commands must exist in the .vsct file)
+ var oleMenuCommandService = this.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
+ if (oleMenuCommandService == null)
+ {
+ return;
+ }
+
+ // Create the command for the menu item.
+ this.AddAttachToCommand(
+ oleMenuCommandService,
+ PkgCmdIDList.cmdidWhutAttachToIIS,
+ gop => gop.ShowAttachToIIS,
+ "w3wp.exe");
- this.AddAttachToCommand(mcs, PkgCmdIDList.cmdidWhutAttachToIIS, gop => gop.ShowAttachToIIS, "w3wp.exe");
- this.AddAttachToCommand(mcs, PkgCmdIDList.cmdidWhutAttachToIISExpress, gop => gop.ShowAttachToIISExpress, "iisexpress.exe");
- this.AddAttachToCommand(mcs, PkgCmdIDList.cmdidWhutAttachToNUnit, gop => gop.ShowAttachToNUnit, "nunit-agent.exe", "nunit.exe", "nunit-console.exe", "nunit-agent-x86.exe", "nunit-x86.exe", "nunit-console-x86.exe");
+ this.AddAttachToCommand(
+ oleMenuCommandService,
+ PkgCmdIDList.cmdidWhutAttachToIISExpress,
+ gop => gop.ShowAttachToIISExpress,
+ "iisexpress.exe");
+
+ this.AddAttachToCommand(
+ oleMenuCommandService,
+ PkgCmdIDList.cmdidWhutAttachToNUnit,
+ gop => gop.ShowAttachToNUnit,
+ "nunit-agent.exe",
+ "nunit.exe",
+ "nunit-console.exe",
+ "nunit-agent-x86.exe",
+ "nunit-x86.exe",
+ "nunit-console-x86.exe");
}
- private void AddAttachToCommand(OleMenuCommandService mcs, uint commandId, Func isVisible, params string[] programsToAttach)
+ ///
+ /// Adds the attach automatic command.
+ ///
+ ///
+ /// The MCS.
+ ///
+ ///
+ /// The command unique identifier.
+ ///
+ ///
+ /// The is visible.
+ ///
+ ///
+ /// The programs automatic attach.
+ ///
+ private void AddAttachToCommand(
+ IMenuCommandService oleMenuCommandService,
+ uint commandId,
+ Func isVisible,
+ params string[] programsToAttach)
{
- OleMenuCommand menuItemCommand = new OleMenuCommand(
- delegate(object sender, EventArgs e)
- {
- DTE dte = (DTE)this.GetService(typeof(DTE));
- foreach (Process process in dte.Debugger.LocalProcesses)
+ Contract.Requires(oleMenuCommandService != null);
+
+ var menuItemCommand = new OleMenuCommand(
+ delegate
{
- if (programsToAttach.Any(p => process.Name.EndsWith(p)))
+ // ReSharper disable once IdentifierTypo
+ var dte = (DTE)this.GetService(typeof(DTE));
+ foreach (var process in
+ dte.Debugger.LocalProcesses.Cast()
+ .Where(process => programsToAttach.Any(p => process.Name.EndsWith(p))))
{
process.Attach();
}
- }
- },
+ },
new CommandID(GuidList.guidAttachToCmdSet, (int)commandId));
- menuItemCommand.BeforeQueryStatus += (s, e) => menuItemCommand.Visible = isVisible((GeneralOptionsPage)this.GetDialogPage(typeof(GeneralOptionsPage)));
- mcs.AddCommand(menuItemCommand);
+
+ menuItemCommand.BeforeQueryStatus +=
+ (s, e) =>
+ menuItemCommand.Visible = isVisible((GeneralOptionsPage)this.GetDialogPage(typeof(GeneralOptionsPage)));
+
+ oleMenuCommandService.AddCommand(menuItemCommand);
}
+
+ #endregion
}
-}
+}
\ No newline at end of file
diff --git a/Whut.AttachTo/Attributes/TraceAttribute.cs b/Whut.AttachTo/Attributes/TraceAttribute.cs
new file mode 100644
index 0000000..061c53b
--- /dev/null
+++ b/Whut.AttachTo/Attributes/TraceAttribute.cs
@@ -0,0 +1,133 @@
+namespace Whut.AttachTo.Attributes
+{
+ using System;
+ using System.Diagnostics;
+ using System.Reflection;
+ using System.Text;
+
+ using PostSharp.Aspects;
+
+ ///
+ /// The trace attribute class.
+ ///
+ [Serializable]
+ public class TraceAttribute : OnMethodBoundaryAspect
+ {
+ #region Fields
+
+ ///
+ /// The method name.
+ ///
+ private string methodName = "UnknownMethodName";
+
+ #endregion
+
+ #region Public Methods and Operators
+
+ ///
+ /// Method invoked at build time to initialize the instance fields of the current aspect. This method is invoked
+ /// before any other build-time method.
+ ///
+ ///
+ /// Method to which the current aspect is applied
+ ///
+ ///
+ /// Reserved for future usage.
+ ///
+ public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
+ {
+ base.CompileTimeInitialize(method, aspectInfo);
+
+ if (method.DeclaringType != null)
+ {
+ this.methodName = string.Format("{0}.{1}", method.DeclaringType.FullName, method.Name);
+ }
+ }
+
+ ///
+ /// Method executed before the body of methods to which this aspect is applied.
+ ///
+ ///
+ /// Event arguments specifying which method
+ /// is being executed, which are its arguments, and how should the execution continue
+ /// after the execution of
+ /// .
+ ///
+ public override void OnEntry(MethodExecutionArgs args)
+ {
+ base.OnEntry(args);
+
+ Trace.TraceInformation("{0}: Enter", this.methodName);
+ Trace.Indent();
+ }
+
+ ///
+ /// Method executed after the body of methods to which this aspect is applied,
+ /// in case that the method resulted with an exception.
+ ///
+ ///
+ /// Event arguments specifying which method is being executed and which are its arguments.
+ ///
+ public override void OnException(MethodExecutionArgs args)
+ {
+ base.OnException(args);
+
+ var stringBuilder = new StringBuilder(1024);
+
+ stringBuilder.AppendFormat("{0}(", this.methodName);
+ var instance = args.Instance;
+ if (instance != null)
+ {
+ stringBuilder.AppendFormat("this={0}", instance);
+ if (args.Arguments.Count > 0)
+ {
+ stringBuilder.Append("; ");
+ }
+ }
+
+ for (var i = 0; i < args.Arguments.Count; i++)
+ {
+ if (i > 0)
+ {
+ stringBuilder.Append(", ");
+ }
+
+ stringBuilder.Append(args.Arguments.GetArgument(i) ?? "null");
+ }
+
+ var guid = Guid.NewGuid();
+
+ stringBuilder.AppendFormat(
+ "): Exception {0} - {1}: {2}",
+ guid,
+ args.Exception.GetType().Name,
+ args.Exception.Message);
+
+ Trace.Unindent();
+ Trace.TraceError(stringBuilder.ToString());
+
+ throw new ApplicationException(
+ string.Format(
+ "An internal exception has occurred. Use the id {0} for further reference to this issue.",
+ guid));
+ }
+
+ ///
+ /// Method executed after the body of methods to which this aspect is applied,
+ /// but only when the method successfully returns (i.e. when no exception flies out
+ /// the method.).
+ ///
+ ///
+ /// Event arguments specifying which method is being executed and which are its arguments.
+ ///
+ public override void OnSuccess(MethodExecutionArgs args)
+ {
+ base.OnSuccess(args);
+
+ Trace.Unindent();
+ Trace.TraceInformation("{0}: Success", this.methodName);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Whut.AttachTo/GeneralOptionsPage.cs b/Whut.AttachTo/GeneralOptionsPage.cs
index c0d32b3..7181fe4 100755
--- a/Whut.AttachTo/GeneralOptionsPage.cs
+++ b/Whut.AttachTo/GeneralOptionsPage.cs
@@ -1,10 +1,19 @@
-using System.ComponentModel;
-using Microsoft.VisualStudio.Shell;
-
-namespace Whut.AttachTo
+namespace Whut.AttachTo
{
+ using System.ComponentModel;
+
+ using Microsoft.VisualStudio.Shell;
+
+ ///
+ /// Class GeneralOptionsPage.
+ ///
public class GeneralOptionsPage : DialogPage
{
+ #region Constructors and Destructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
public GeneralOptionsPage()
{
this.ShowAttachToIIS = true;
@@ -12,22 +21,40 @@ public GeneralOptionsPage()
this.ShowAttachToNUnit = true;
}
+ #endregion
+
+ #region Public Properties
+
+ ///
+ /// Gets or sets a value indicating whether [show attach automatic IIS].
+ ///
+ /// true if [show attach automatic IIS]; otherwise, false .
[Category("General")]
[DisplayName("Show 'Attach to IIS' command")]
[Description("Show 'Attach to IIS' command in Tools menu.")]
[DefaultValue(true)]
public bool ShowAttachToIIS { get; set; }
+ ///
+ /// Gets or sets a value indicating whether [show attach automatic IIS express].
+ ///
+ /// true if [show attach automatic IIS express]; otherwise, false .
[Category("General")]
[DisplayName("Show 'Attach to IIS Express command")]
[Description("Show 'Attach to IIS Express command in Tools menu.")]
[DefaultValue(true)]
public bool ShowAttachToIISExpress { get; set; }
+ ///
+ /// Gets or sets a value indicating whether [show attach automatic asynchronous unit].
+ ///
+ /// true if [show attach automatic asynchronous unit]; otherwise, false .
[Category("General")]
[DisplayName("Show 'Attach to NUnit' command")]
[Description("Show 'Attach to NUnit' command in Tools menu.")]
[DefaultValue(true)]
public bool ShowAttachToNUnit { get; set; }
+
+ #endregion
}
-}
+}
\ No newline at end of file
diff --git a/Whut.AttachTo/Guids.cs b/Whut.AttachTo/Guids.cs
index e609719..e1fa059 100755
--- a/Whut.AttachTo/Guids.cs
+++ b/Whut.AttachTo/Guids.cs
@@ -1,15 +1,27 @@
-// Guids.cs
-// MUST match guids.h
-using System;
-
-namespace Whut.AttachTo
+namespace Whut.AttachTo
{
+ // Guids.cs
+ // MUST match guids.h
+ using System;
+
+ ///
+ /// Class GuidList.
+ ///
public static class GuidList
{
+ ///
+ /// The unique identifier attach automatic PKG string
+ ///
public const string guidAttachToPkgString = "8d6080f0-7276-44d7-8dc4-6378fb6ce225";
+ ///
+ /// The unique identifier attach automatic command set string
+ ///
public const string guidAttachToCmdSetString = "16e2ac5c-ec3d-4ff1-a237-11ccef54fe0f";
+ ///
+ /// The unique identifier attach automatic command set
+ ///
public static readonly Guid guidAttachToCmdSet = new Guid(guidAttachToCmdSetString);
}
}
\ No newline at end of file
diff --git a/Whut.AttachTo/PkgCmdID.cs b/Whut.AttachTo/PkgCmdID.cs
index 31154ed..b24b511 100755
--- a/Whut.AttachTo/PkgCmdID.cs
+++ b/Whut.AttachTo/PkgCmdID.cs
@@ -1,14 +1,26 @@
-// PkgCmdID.cs
-// MUST match PkgCmdID.h
-
-namespace Whut.AttachTo
+namespace Whut.AttachTo
{
+ // PkgCmdID.cs
+ // MUST match PkgCmdID.h
+
+ ///
+ /// Class PkgCmdIDList.
+ ///
public static class PkgCmdIDList
{
+ ///
+ /// The cmdid whut attach automatic IIS
+ ///
public const uint cmdidWhutAttachToIIS = 0x100;
+ ///
+ /// The cmdid whut attach automatic IIS express
+ ///
public const uint cmdidWhutAttachToIISExpress = 0x101;
+ ///
+ /// The cmdid whut attach automatic asynchronous unit
+ ///
public const uint cmdidWhutAttachToNUnit = 0x102;
}
}
\ No newline at end of file
diff --git a/Whut.AttachTo/Properties/AssemblyInfo.cs b/Whut.AttachTo/Properties/AssemblyInfo.cs
index ce6778c..e433c26 100755
--- a/Whut.AttachTo/Properties/AssemblyInfo.cs
+++ b/Whut.AttachTo/Properties/AssemblyInfo.cs
@@ -3,6 +3,10 @@
using System.Resources;
using System.Runtime.InteropServices;
+using PostSharp.Extensibility;
+
+using Whut.AttachTo.Attributes;
+
// 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.
@@ -19,13 +23,14 @@
[assembly: NeutralResourcesLanguage("en-US")]
// Version information for an assembly consists of the following four values:
-//
// Major Version
// Minor Version
// Build Number
// Revision
-//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
+[assembly:
+ Trace(AttributeTargetTypes = "Whut.AttachTo", AttributeTargetTypeAttributes = MulticastAttributes.Public,
+ AttributeTargetMemberAttributes = MulticastAttributes.Public)]
diff --git a/Whut.AttachTo/Resources.Designer.cs b/Whut.AttachTo/Properties/Resources.Designer.cs
old mode 100755
new mode 100644
similarity index 91%
rename from Whut.AttachTo/Resources.Designer.cs
rename to Whut.AttachTo/Properties/Resources.Designer.cs
index 4de098e..f420ec0
--- a/Whut.AttachTo/Resources.Designer.cs
+++ b/Whut.AttachTo/Properties/Resources.Designer.cs
@@ -1,14 +1,14 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:2.0.50727.42
+// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace Whut.AttachTo {
+namespace Whut.AttachTo.Properties {
using System;
@@ -19,7 +19,7 @@ namespace Whut.AttachTo {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -39,7 +39,7 @@ internal Resources() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Whut.AttachTo.Resources", typeof(Resources).Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Whut.AttachTo.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -59,6 +59,5 @@ internal Resources() {
resourceCulture = value;
}
}
-
}
}
diff --git a/Whut.AttachTo/Resources.resx b/Whut.AttachTo/Properties/Resources.resx
old mode 100755
new mode 100644
similarity index 100%
rename from Whut.AttachTo/Resources.resx
rename to Whut.AttachTo/Properties/Resources.resx
diff --git a/Whut.AttachTo/RequiresPostSharp.cs b/Whut.AttachTo/RequiresPostSharp.cs
new file mode 100644
index 0000000..78562e4
--- /dev/null
+++ b/Whut.AttachTo/RequiresPostSharp.cs
@@ -0,0 +1,11 @@
+//
+// This file causes a build-time exception when PostSharp is not included in the build process.
+// To avoid false errors, do not open the file in Visual Studio, and ignore any error real-time
+// verifiers such as Resharper may report.
+//
+// You can safely delete this file, but it will be recreated when you upgrade the NuGet package.
+//
+
+#if !POSTSHARP
+#error PostSharp is not introduced in the build process. If NuGet just restored the PostSharp package, you need to rebuild the solution.
+#endif
\ No newline at end of file
diff --git a/Whut.AttachTo/Resources/Images.png b/Whut.AttachTo/Resources/Images.png
new file mode 100644
index 0000000..bf17e6b
Binary files /dev/null and b/Whut.AttachTo/Resources/Images.png differ
diff --git a/Whut.AttachTo/Resources/Images_32bit.bmp b/Whut.AttachTo/Resources/Images_32bit.bmp
deleted file mode 100755
index 2fa7ab0..0000000
Binary files a/Whut.AttachTo/Resources/Images_32bit.bmp and /dev/null differ
diff --git a/Whut.AttachTo/Whut.AttachTo.csproj b/Whut.AttachTo/Whut.AttachTo.csproj
index e007f33..535eb57 100755
--- a/Whut.AttachTo/Whut.AttachTo.csproj
+++ b/Whut.AttachTo/Whut.AttachTo.csproj
@@ -1,5 +1,6 @@
-
+
+
Debug
AnyCPU
@@ -12,7 +13,31 @@
AttachTo
True
Key.snk
- v4.0
+ v4.5
+ 12.0
+
+
+
+
+ 4.0
+
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+ 1
+ True
true
@@ -22,6 +47,44 @@
DEBUG;TRACE
prompt
4
+ false
+ bin\Debug\AttachTo.XML
+ true
+ True
+ False
+ False
+ True
+ False
+ True
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+ True
+ True
+ False
+ False
+
+
+
+
+
+
+
+ False
+ False
+ Full
+ DoNotBuild
+ 0
+ x86
pdbonly
@@ -31,6 +94,43 @@
prompt
4
true
+ false
+ bin\Release\AttachTo.XML
+ True
+ False
+ False
+ True
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+ True
+ True
+ False
+ False
+
+
+
+
+
+
+
+ False
+ False
+ Full
+ DoNotBuild
+ 0
+ True
+ False
+ x86
@@ -40,11 +140,25 @@
+
+ true
+
+
+ true
+
false
+
+
+
+ ..\packages\PostSharp.3.0.40\lib\net20\PostSharp.dll
+
+
+ ..\packages\PostSharp.Patterns.Diagnostics.3.0.40\lib\net40\PostSharp.Patterns.Diagnostics.dll
+
@@ -114,7 +228,7 @@
Component
-
+
True
True
Resources.resx
@@ -122,9 +236,11 @@
+
+
-
+
ResXFileCodeGenerator
Resources.Designer.cs
Designer
@@ -135,9 +251,11 @@
+
Designer
+
@@ -148,7 +266,7 @@
-
+
@@ -162,11 +280,38 @@
Always
+
+
+ False
+ Microsoft .NET Framework 4 %28x86 and x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
+ False
+ Windows Installer 4.5
+ true
+
+
true
+
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
-
+
+