User: xtoff
Date: 2009/10/29 08:43 AM
Added:
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Properties/
Settings.Designer.cs, Settings.settings
Modified:
/DynamicProxy/trunk/lib/mono-3.5/
Castle.Core.dll, Castle.Core.xml
/DynamicProxy/trunk/lib/net-2.0/
Castle.Core.dll, Castle.Core.xml
/DynamicProxy/trunk/lib/net-3.5/
Castle.Core.dll, Castle.Core.xml
/DynamicProxy/trunk/lib/silverlight-2.0/
Castle.Core.dll, Castle.Core.xml
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
App.config, BasePEVerifyTestCase.cs, Castle.DynamicProxy.Tests-vs2008.csproj,
GenerationHookTestCase.cs, GenericInterfaceProxyTestCase.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
MembersCollector.cs
Log:
- Changed how DP tests look for PEVerify. It is now possible to add more paths
to look for. Also Tests look for the PeVerify just once before running a whole
fixture, not during each test as it used to be, which in theory should speed
tests up.
- Updated references to Core
- Fixed issue with proxy generation hook methods being invoked twice for the
same
File Changes:
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
=============================================================
File [modified]: App.config
Delta lines: +28 -15
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/BasePEVerifyTestCase.cs
2009-10-29 14:57:19 UTC (rev 6290)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/BasePEVerifyTestCase.cs
2009-10-29 15:43:17 UTC (rev 6291)
@@ -15,11 +15,37 @@
namespace Castle.DynamicProxy.Tests
{
using System;
- using System.Configuration;
using System.Diagnostics;
using System.IO;
+ using Castle.DynamicProxy.Tests.Properties;
using NUnit.Framework;
+#if !MONO && !SILVERLIGHT // mono doesn't have PEVerify
+ [SetUpFixture]
+ public class FindPeVerify
+ {
+ [SetUp]
+ public void FindPeVerifySetUp()
+ {
+ var peVerifyProbingPaths =
Settings.Default.PeVerifyProbingPaths;
+ foreach (var path in peVerifyProbingPaths)
+ {
+ var file = Path.Combine(path, "peverify.exe");
+ if (File.Exists(file))
+ {
+ PeVerifyPath = file;
+ return;
+ }
+ }
+ throw new FileNotFoundException(
+ "Please check the PeVerifyProbingPaths
configuration setting and set it to the folder where peverify.exe is located");
+ }
+
+ public static string PeVerifyPath { get; set; }
+ }
+#endif
+
+
public abstract class BasePEVerifyTestCase
{
protected ProxyGenerator generator;
@@ -69,20 +95,7 @@
{
Process process = new Process();
- string path =
Path.Combine(ConfigurationManager.AppSettings["sdkDir"], "peverify.exe");
-
- if (!File.Exists(path))
- {
- path =
Path.Combine(ConfigurationManager.AppSettings["x86SdkDir"], "peverify.exe");
- }
-
- if (!File.Exists(path))
- {
- throw new FileNotFoundException(
- "Please check the sdkDir configuration
setting and set it to the location of peverify.exe");
- }
-
- process.StartInfo.FileName = path;
+ process.StartInfo.FileName = FindPeVerify.PeVerifyPath;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
File [modified]: BasePEVerifyTestCase.cs
Delta lines: +9 -3
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Castle.DynamicProxy.Tests-vs2008.csproj
2009-10-29 14:57:19 UTC (rev 6290)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Castle.DynamicProxy.Tests-vs2008.csproj
2009-10-29 15:43:17 UTC (rev 6291)
@@ -118,6 +118,10 @@
<Link>CastleKey.snk</Link>
</None>
<None Include="App.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
</ItemGroup>
<ItemGroup>
<Compile Include="Classes\ClassWithExplicitInterface.cs" />
@@ -212,6 +216,11 @@
<Compile Include="OutRefParams.cs" />
<Compile Include="PersistentProxyBuilderTestCase.cs" />
<Compile Include="Interceptors\ProceedOnTypeInterceptor.cs" />
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ <DependentUpon>Settings.settings</DependentUpon>
+ </Compile>
<Compile Include="ProxyGenerationOptionsTestCase.cs" />
<Compile Include="Interceptors\RequiredParamInterceptor.cs" />
<Compile Include="ProxyKind.cs" />
@@ -227,9 +236,6 @@
<ItemGroup>
<Service Include="{B4F97281-0DBD-4835-9ED8-7DFB966E87FF}" />
</ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets
below and uncomment it.
File [modified]: Castle.DynamicProxy.Tests-vs2008.csproj
Delta lines: +1 -1
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenerationHookTestCase.cs
2009-10-29 14:57:19 UTC (rev 6290)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenerationHookTestCase.cs
2009-10-29 15:43:17 UTC (rev 6291)
@@ -26,7 +26,7 @@
[TestFixture]
public class GenerationHookTestCase : BasePEVerifyTestCase
{
- [Test, Ignore("Until we fix DYNPROXY-ISSUE-89 this test will
fail. Since it's not critical it's ignored for now.")]
+ [Test]
public void HookIsUsedForConcreteClassProxy()
{
File [modified]: GenerationHookTestCase.cs
Delta lines: +1 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenericInterfaceProxyTestCase.cs
2009-10-29 14:57:19 UTC (rev 6290)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/GenericInterfaceProxyTestCase.cs
2009-10-29 15:43:17 UTC (rev 6291)
@@ -397,7 +397,7 @@
[Test(Description = "There is a strange CLR bug resulting from
our loading the tokens of methods in generic types. "
+ "This test ensures we do not trigger
it.")]
- [Ignore("Currently, we trigger the bug, and work around it -
see MethodFinder")]
+ //[Ignore("Currently, we trigger the bug, and work around it -
see MethodFinder")]
public void TypeGetMethodsIsStable()
{
File [modified]: GenericInterfaceProxyTestCase.cs
Delta lines: +41 -0
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Properties/Settings.Designer.cs
(rev 0)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Properties/Settings.Designer.cs
2009-10-29 15:43:17 UTC (rev 6291)
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.4927
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Castle.DynamicProxy.Tests.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator",
"9.0.0.0")]
+ internal sealed partial class Settings :
global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance =
((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new
Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute(@"<?xml
version=""1.0"" encoding=""utf-16""?>
+<ArrayOfString xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
+ <string>%PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\Bin</string>
+ <string>%PROGRAMFILES(x86)%\Microsoft Visual Studio 8\SDK\v2.0\bin</string>
+</ArrayOfString>")]
+ public global::System.Collections.Specialized.StringCollection
PeVerifyProbingPaths {
+ get {
+ return
((global::System.Collections.Specialized.StringCollection)(this["PeVerifyProbingPaths"]));
+ }
+ set {
+ this["PeVerifyProbingPaths"] = value;
+ }
+ }
+ }
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
====================================================================
File [modified]: MembersCollector.cs
Delta lines: +19 -5
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/App.config 2009-10-29
14:57:19 UTC (rev 6290)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/App.config 2009-10-29
15:43:17 UTC (rev 6291)
@@ -1,7 +1,21 @@
-<?xml version="1.0" encoding="utf-8" ?>
+<?xml version="1.0" encoding="utf-8"?>
<configuration>
- <appSettings>
- <add key="sdkDir" value="c:\Program Files\Microsoft
SDKs\Windows\v6.0A\Bin" />
- <add key="x86SdkDir" value="C:\Program Files (x86)\Microsoft Visual
Studio 8\SDK\v2.0\bin" />
- </appSettings>
+ <configSections>
+ <sectionGroup name="userSettings"
type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+ <section name="Castle.DynamicProxy.Tests.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
+ </sectionGroup>
+ </configSections>
+ <userSettings>
+ <Castle.DynamicProxy.Tests.Properties.Settings>
+ <setting name="PeVerifyProbingPaths" serializeAs="Xml">
+ <value>
+ <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <string>c:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin</string>
+ <string>C:\Program Files (x86)\SMicrosoft Visual Studio
8\SDK\v2.0\bin</string>
+ </ArrayOfString>
+ </value>
+ </setting>
+ </Castle.DynamicProxy.Tests.Properties.Settings>
+ </userSettings>
</configuration>
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Properties/
========================================================================
File [added]: Settings.Designer.cs
Delta lines: +13 -0
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Properties/Settings.settings
(rev 0)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Properties/Settings.settings
2009-10-29 15:43:17 UTC (rev 6291)
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile
xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings"
CurrentProfile="(Default)"
GeneratedClassNamespace="Castle.DynamicProxy.Tests.Properties"
GeneratedClassName="Settings">
+ <Profiles />
+ <Settings>
+ <Setting Name="PeVerifyProbingPaths"
Type="System.Collections.Specialized.StringCollection" Scope="User">
+ <Value Profile="(Default)"><?xml version="1.0" encoding="utf-16"?>
+<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <string>%PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\Bin</string>
+ <string>%PROGRAMFILES(x86)%\Microsoft Visual Studio
8\SDK\v2.0\bin</string>
+</ArrayOfString></Value>
+ </Setting>
+ </Settings>
+</SettingsFile>
File [added]: Settings.settings
Delta lines: +0 -0
===================================================================
Directory: /DynamicProxy/trunk/lib/mono-3.5/
============================================
File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +13 -10
===================================================================
--- DynamicProxy/trunk/lib/net-2.0/Castle.Core.xml 2009-10-29 14:57:19 UTC
(rev 6290)
+++ DynamicProxy/trunk/lib/net-2.0/Castle.Core.xml 2009-10-29 15:43:17 UTC
(rev 6291)
@@ -220,21 +220,24 @@
</summary>
<value>The type of the lifestyle handler.</value>
</member>
- <member name="T:Castle.Core.Interceptor.IAttributeDisassembler">
+ <member name="T:Castle.DynamicProxy.IAttributeDisassembler">
<summary>
- Encapsulates process of custom attribute dissassembly back to <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/>.
+ Provides functionality for disassembling instances of attributes
to CustomAttributeBuilder form, during the process of emiting new types by
Dynamic Proxy.
</summary>
- <remarks>
- This interface is used for custom attribute replication in Dynamic
Proxy and to put additional custom attributes on proxy type.
- Implement it if default implementatio does not meet your needs or
does not support your scenario.
- </remarks>
</member>
- <member
name="M:Castle.Core.Interceptor.IAttributeDisassembler.Disassemble(System.Attribute)">
+ <member
name="M:Castle.DynamicProxy.IAttributeDisassembler.Disassemble(System.Attribute)">
<summary>
- Dissassembles given <paramref name="attribute"/> to <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/>.
+ Disassembles given attribute instance back to corresponding
CustomAttributeBuilder.
</summary>
- <param name="attribute">Custom attribute instance to
disassemble.</param>
- <returns>Builder that represents <paramref
name="attribute"/>.</returns>
+ <param name="attribute">An instance of attribute to
disassemble</param>
+ <returns><see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/> corresponding 1 to 1
to given attribute instance, or null reference.</returns>
+ <remarks>
+ Implementers should return <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/> that corresponds to
given attribute instance 1 to 1,
+ that is after calling specified constructor with specified
arguments, and setting specified properties and fields with values specified
+ we should be able to get an attribute instance identical to the
one passed in <paramref name="attribute"/>. Implementer can return null
+ if it wishes to opt out of replicating the attribute. Notice
however, that for some cases, like attributes passed explicitly by the user
+ it is illegal to return null, and doing so will result in
exception.
+ </remarks>
</member>
<member name="T:Castle.Core.Interceptor.IInterceptor">
Directory: /DynamicProxy/trunk/lib/net-2.0/
===========================================
File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +13 -10
===================================================================
--- DynamicProxy/trunk/lib/net-3.5/Castle.Core.xml 2009-10-29 14:57:19 UTC
(rev 6290)
+++ DynamicProxy/trunk/lib/net-3.5/Castle.Core.xml 2009-10-29 15:43:17 UTC
(rev 6291)
@@ -220,21 +220,24 @@
</summary>
<value>The type of the lifestyle handler.</value>
</member>
- <member name="T:Castle.Core.Interceptor.IAttributeDisassembler">
+ <member name="T:Castle.DynamicProxy.IAttributeDisassembler">
<summary>
- Encapsulates process of custom attribute dissassembly back to <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/>.
+ Provides functionality for disassembling instances of attributes
to CustomAttributeBuilder form, during the process of emiting new types by
Dynamic Proxy.
</summary>
- <remarks>
- This interface is used for custom attribute replication in Dynamic
Proxy and to put additional custom attributes on proxy type.
- Implement it if default implementatio does not meet your needs or
does not support your scenario.
- </remarks>
</member>
- <member
name="M:Castle.Core.Interceptor.IAttributeDisassembler.Disassemble(System.Attribute)">
+ <member
name="M:Castle.DynamicProxy.IAttributeDisassembler.Disassemble(System.Attribute)">
<summary>
- Dissassembles given <paramref name="attribute"/> to <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/>.
+ Disassembles given attribute instance back to corresponding
CustomAttributeBuilder.
</summary>
- <param name="attribute">Custom attribute instance to
disassemble.</param>
- <returns>Builder that represents <paramref
name="attribute"/>.</returns>
+ <param name="attribute">An instance of attribute to
disassemble</param>
+ <returns><see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/> corresponding 1 to 1
to given attribute instance, or null reference.</returns>
+ <remarks>
+ Implementers should return <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/> that corresponds to
given attribute instance 1 to 1,
+ that is after calling specified constructor with specified
arguments, and setting specified properties and fields with values specified
+ we should be able to get an attribute instance identical to the
one passed in <paramref name="attribute"/>. Implementer can return null
+ if it wishes to opt out of replicating the attribute. Notice
however, that for some cases, like attributes passed explicitly by the user
+ it is illegal to return null, and doing so will result in
exception.
+ </remarks>
</member>
<member name="T:Castle.Core.Interceptor.IInterceptor">
Directory: /DynamicProxy/trunk/lib/net-3.5/
===========================================
File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +13 -10
===================================================================
--- DynamicProxy/trunk/lib/silverlight-2.0/Castle.Core.xml 2009-10-29
14:57:19 UTC (rev 6290)
+++ DynamicProxy/trunk/lib/silverlight-2.0/Castle.Core.xml 2009-10-29
15:43:17 UTC (rev 6291)
@@ -220,21 +220,24 @@
</summary>
<value>The type of the lifestyle handler.</value>
</member>
- <member name="T:Castle.Core.Interceptor.IAttributeDisassembler">
+ <member name="T:Castle.DynamicProxy.IAttributeDisassembler">
<summary>
- Encapsulates process of custom attribute dissassembly back to <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/>.
+ Provides functionality for disassembling instances of attributes
to CustomAttributeBuilder form, during the process of emiting new types by
Dynamic Proxy.
</summary>
- <remarks>
- This interface is used for custom attribute replication in Dynamic
Proxy and to put additional custom attributes on proxy type.
- Implement it if default implementatio does not meet your needs or
does not support your scenario.
- </remarks>
</member>
- <member
name="M:Castle.Core.Interceptor.IAttributeDisassembler.Disassemble(System.Attribute)">
+ <member
name="M:Castle.DynamicProxy.IAttributeDisassembler.Disassemble(System.Attribute)">
<summary>
- Dissassembles given <paramref name="attribute"/> to <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/>.
+ Disassembles given attribute instance back to corresponding
CustomAttributeBuilder.
</summary>
- <param name="attribute">Custom attribute instance to
disassemble.</param>
- <returns>Builder that represents <paramref
name="attribute"/>.</returns>
+ <param name="attribute">An instance of attribute to
disassemble</param>
+ <returns><see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/> corresponding 1 to 1
to given attribute instance, or null reference.</returns>
+ <remarks>
+ Implementers should return <see
cref="T:System.Reflection.Emit.CustomAttributeBuilder"/> that corresponds to
given attribute instance 1 to 1,
+ that is after calling specified constructor with specified
arguments, and setting specified properties and fields with values specified
+ we should be able to get an attribute instance identical to the
one passed in <paramref name="attribute"/>. Implementer can return null
+ if it wishes to opt out of replicating the attribute. Notice
however, that for some cases, like attributes passed explicitly by the user
+ it is illegal to return null, and doing so will result in
exception.
+ </remarks>
</member>
<member name="T:Castle.Core.Interceptor.IInterceptor">
Directory: /DynamicProxy/trunk/lib/silverlight-2.0/
===================================================
File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +14 -2
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MembersCollector.cs
2009-10-29 14:57:19 UTC (rev 6290)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MembersCollector.cs
2009-10-29 15:43:17 UTC (rev 6291)
@@ -17,7 +17,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
- using System.Reflection.Emit;
using Generators;
public class MembersCollector
@@ -25,12 +24,13 @@
private const BindingFlags Flags = BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance;
protected readonly bool onlyProxyVirtual;
protected readonly InterfaceMapping map;
-
+ private IList<MethodInfo> checkedMethods = new
List<MethodInfo>();
private readonly IDictionary<PropertyInfo, PropertyToGenerate>
properties = new Dictionary<PropertyInfo, PropertyToGenerate>();
private readonly IDictionary<EventInfo, EventToGenerate> events
= new Dictionary<EventInfo, EventToGenerate>();
private readonly IDictionary<MethodInfo, MethodToGenerate>
methodsToProxy = new Dictionary<MethodInfo, MethodToGenerate>();
private readonly Type type;
+
protected readonly ITypeContributor contributor;
public MembersCollector(Type type, ITypeContributor
contributor, bool onlyProxyVirtual, InterfaceMapping map)
@@ -58,12 +58,18 @@
public void CollectMembersToProxy(IProxyGenerationHook hook)
{
+ if(checkedMethods==null)// this method was already
called!
+ {
+ throw new InvalidOperationException("Can't call
CollectMembersToProxy twice");
+ }
CollectProperties(hook);
CollectEvents(hook);
// Methods go last, because properties and events have
methods too (getters/setters add/remove)
// and we don't want to get duplicates, so we collect
property and event methods first
// then we collect methods, and add only these that
aren't there yet
CollectMethods(hook);
+
+ checkedMethods = null; // this is ugly, should have a
boolean flag for this or something
}
private void CollectProperties(IProxyGenerationHook hook)
@@ -152,6 +158,12 @@
private MethodToGenerate AddMethod(MethodInfo method,
IProxyGenerationHook hook, bool isStandalone)
{
+ if (checkedMethods.Contains(method))
+ {
+ return null;
+ }
+ checkedMethods.Add(method);
+
if (methodsToProxy.ContainsKey(method))
{
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Castle Project Commits" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/castle-project-commits?hl=en
-~----------~----~----~----~------~----~------~--~---