private void ShowFormattedSummary(IndentingTextWriter writer, string summary, int?columns)
        {
            _env.AssertValue(writer);

            if (string.IsNullOrWhiteSpace(summary))
            {
                return;
            }

            // REVIEW: should we replace consecutive spaces with a single space as a preprocessing step?
            int screenWidth = (columns ?? Console.BufferWidth) - 1;

            // Console.BufferWidth returns 0 if command redirection operator is used
            if (screenWidth <= 0)
            {
                screenWidth = 80;
            }

            const int indentLen = 3;
            string    indent    = new string(' ', indentLen);
            var       builder   = new StringBuilder();

            // REVIEW: is using StringSplitOptions.RemoveEmptyEntries the right thing to do here?
            var blocks = summary.Split(new[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < blocks.Length; i++)
            {
                AppendFormattedText(builder, blocks[i], indent, screenWidth);
            }

            writer.WriteLine("Summary:");
            writer.WriteLine(builder);
        }
Exemple #2
0
        protected void GenerateMethodSignature(IndentingTextWriter w, CmdParser.ArgInfo.Arg arg, string parent, string parentType, string parentValue, ref string linePrefix, string argSuffix)
        {
            if (Exclude.Contains(arg.LongName))
            {
                return;
            }

            if (arg.IsSubComponentItemType)
            {
                // We need to create a tree with all the subcomponents, unless the subcomponent is a Trainer.
                Contracts.Assert(arg.ItemType.GetGenericTypeDefinition() == typeof(SubComponent <,>));
                var types    = arg.ItemType.GetGenericArguments();
                var baseType = types[0];
                var sigType  = types[1];
                if (sigType == typeof(SignatureDataLoader))
                {
                    return;
                }
                w.WriteLine(linePrefix);
                linePrefix = ",";
                if (IsTrainer(sigType))
                {
                    w.WriteLine("[DataLabInputPort(FriendlyName = \"Untrained model\", DisplayName = \"Untrained model\", IsOptional = false, DataTypes = WellKnownDataTypeIds.ILearnerDotNet, Description = \"An untrained model\")]");
                    GenerateParameter(w, "ILearner", arg.LongName + argSuffix);
                    return;
                }
                var typeName = EnumName(arg, sigType);
                GenerateDataLabParameterAttribute(w, arg.LongName, false, arg.LongName, arg.DefaultValue != null ? typeName + "." + arg.DefaultValue : null, arg.HelpText, parent, parentType, parentValue);
                GenerateParameter(w, typeName, arg.LongName + argSuffix);
                var infos = ComponentCatalog.GetAllDerivedClasses(baseType, sigType);
                foreach (var info in infos)
                {
                    var args = info.CreateArguments();
                    if (args == null)
                    {
                        continue;
                    }
                    var argInfo = CmdParser.GetArgInfo(args.GetType(), args);
                    foreach (var a in argInfo.Args)
                    {
                        GenerateMethodSignature(w, a, arg.LongName, typeName, info.LoadNames[0], ref linePrefix, argSuffix + info.LoadNames[0]);
                    }
                }
            }
            else
            {
                w.WriteLine(linePrefix);
                linePrefix = ",";
                if (IsColumnType(arg))
                {
                    GenerateDataLabParameterAttribute(w, arg.LongName, false, arg.LongName, null, arg.HelpText, parent, parentType, parentValue);
                    GenerateParameter(w, "string", arg.LongName + argSuffix);
                }
                else
                {
                    GenerateDataLabParameterAttribute(w, arg.LongName, IsOptional(arg), arg.LongName, Stringify(arg.DefaultValue), arg.HelpText, parent, parentType, parentValue);
                    GenerateParameter(w, GetCSharpTypeName(arg.ItemType), arg.LongName + argSuffix);
                }
            }
        }
        protected void GenerateImplBody(IndentingTextWriter w, CmdParser.ArgInfo.Arg arg, string argSuffix)
        {
            if (Exclude.Contains(arg.LongName))
            {
                return;
            }

            if (arg.IsCollection)
            {
                if (IsColumnType(arg))
                {
                    w.WriteLine("args{0}.{1} = {1}.Select({2}.Parse).ToArray();", argSuffix, arg.LongName, GetCSharpTypeName(arg.ItemType));
                }
                else if (IsStringColumnType(arg))
                {
                    w.WriteLine("args{0}.{1} = {2};", argSuffix, arg.LongName, arg.LongName + argSuffix);
                }
                else
                {
                    w.WriteLine("args{0}.{1} = new[] {{ {2} }};", argSuffix, arg.LongName, arg.LongName + argSuffix);
                }
            }
            else
            {
                w.WriteLine("args{0}.{1} = {2};", argSuffix, arg.LongName, arg.LongName + argSuffix);
            }
        }
Exemple #4
0
        /// <summary>
        /// Called at the beginning of a test - it dumps the usage of the Arguments class(es).
        /// </summary>
        private static void Init(IndentingTextWriter wrt, object defaults)
        {
            var env = new TlcEnvironment(seed: 42);

            wrt.WriteLine("Usage:");
            wrt.WriteLine(CmdParser.ArgumentsUsage(env, defaults.GetType(), defaults, false, 200));
        }
 protected override void GenerateOutputPort(IndentingTextWriter w)
 {
     w.WriteLine(
         "[DataLabOutputPort(FriendlyName = \"Transformed IDataView\", DisplayName = \"Transformed IDataView\", Position = 0, DataType = WellKnownDataTypeIds.IDataViewDotNet, Description = \"Transformed data (IDataView)\")]");
     w.WriteLine(
         "[DataLabOutputPort(FriendlyName = \"Transformed data model\", DisplayName = \"Transformed data model\", Position = 1, DataType = WellKnownDataTypeIds.ITransformDotNet, Description = \"Transformed data model (ITransform)\")]");
 }
        private void GenerateImplCall(IndentingTextWriter w, CmdParser.ArgInfo.Arg arg, string parent, string parentType, string parentValue, string argSuffix)
        {
            if (Exclude.Contains(arg.LongName))
            {
                return;
            }

            if (arg.IsSubComponentItemType)
            {
                // We need to create a tree with all the subcomponents, unless the subcomponent is a Trainer.
                Contracts.Assert(arg.ItemType.GetGenericTypeDefinition() == typeof(SubComponent <,>));
                var types    = arg.ItemType.GetGenericArguments();
                var baseType = types[0];
                var sigType  = types[1];
                if (sigType == typeof(SignatureDataLoader))
                {
                    return;
                }
                if (IsTrainer(sigType))
                {
                    return;
                }
                var typeName = EnumName(arg, sigType);
                GenerateImplCall(w, typeName, arg.LongName + argSuffix);
                var infos = ComponentCatalog.GetAllDerivedClasses(baseType, sigType);
                foreach (var info in infos)
                {
                    var args = info.CreateArguments();
                    if (args == null)
                    {
                        continue;
                    }
                    var argInfo = CmdParser.GetArgInfo(args.GetType(), args);
                    foreach (var a in argInfo.Args)
                    {
                        GenerateImplCall(w, a, arg.LongName, typeName, info.LoadNames[0], argSuffix + info.LoadNames[0]);
                    }
                }
            }
            else
            {
                if (IsColumnType(arg) || IsStringColumnType(arg))
                {
                    string name = arg.LongName + argSuffix;
                    if (arg.IsCollection)
                    {
                        w.WriteLine("builder.{0} = ((string)parameters[\"{1}\"]).Split('|');", Capitalize(name), name);
                    }
                    else
                    {
                        w.WriteLine("builder.{0} = (string)parameters[\"{1}\"];", Capitalize(name), name);
                    }
                }
                else
                {
                    GenerateImplCall(w, GetCSharpTypeName(arg.ItemType), arg.LongName + argSuffix);
                }
            }
        }
 protected override void GenerateMethodSignature(IndentingTextWriter w, string prefix, ComponentCatalog.LoadableClassInfo component)
 {
     w.WriteLine("/// <summary>");
     w.WriteLine("/// Creates a {0}", component.LoadNames[0]);
     w.WriteLine("/// </summary>");
     w.WriteLine("/// <returns>A tuple containing learner name and settings.</returns>");
     w.WriteLine("public Tuple<string, string> GetTlcSettings()");
 }
        protected override void GenerateClassName(IndentingTextWriter w, string prefix, ComponentCatalog.LoadableClassInfo component)
        {
            w.WriteLine();
            var className = prefix + component.LoadNames[0];

            w.WriteLine("/// <summary>Module: {0}</summary>", className);
            w.WriteLine("public static class {0}EntryPoint", className);
            w.WriteLine("{");
        }
Exemple #9
0
        protected virtual void GenerateClassName(IndentingTextWriter w, string prefix, ComponentCatalog.LoadableClassInfo component)
        {
            w.WriteLine();
            var className = prefix + component.LoadNames[0];

            w.WriteLine("/// <summary>Module: {0}</summary>", className);
            w.WriteLine("public partial class {0}", className);
            w.WriteLine("{");
        }
Exemple #10
0
        private void GenerateInputOutput(IndentingTextWriter writer, ModuleCatalog.EntryPointInfo entryPointInfo, ModuleCatalog catalog)
        {
            var classAndMethod = CSharpGeneratorUtils.GetEntryPointMetadata(entryPointInfo);

            writer.WriteLine($"namespace {classAndMethod.Namespace}");
            writer.WriteLine("{");
            writer.Indent();
            GenerateInput(writer, entryPointInfo, catalog);
            writer.Outdent();
            writer.WriteLine("}");
            writer.WriteLine();
        }
 public static void GenerateSummary(IndentingTextWriter writer, string summary)
 {
     if (string.IsNullOrEmpty(summary))
     {
         return;
     }
     writer.WriteLine("/// <summary>");
     foreach (var line in summary.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
     {
         writer.WriteLine($"/// {line}");
     }
     writer.WriteLine("/// </summary>");
 }
Exemple #12
0
        protected void GenerateImplCall(IndentingTextWriter w, CmdParser.ArgInfo.Arg arg, string argSuffix)
        {
            if (Exclude.Contains(arg.LongName))
            {
                return;
            }

            if (arg.IsSubComponentItemType)
            {
                Contracts.Assert(arg.ItemType.GetGenericTypeDefinition() == typeof(SubComponent <,>));
                var types    = arg.ItemType.GetGenericArguments();
                var baseType = types[0];
                var sigType  = types[1];
                if (sigType == typeof(SignatureDataLoader))
                {
                    return;
                }
                if (IsTrainer(sigType))
                {
                    w.WriteLine("builder.{0} = {1};", Capitalize(arg.LongName + argSuffix), arg.LongName + argSuffix);
                    return;
                }
                w.WriteLine("builder.{0} = {1};", Capitalize(arg.LongName + argSuffix), arg.LongName + argSuffix);
                var infos = ComponentCatalog.GetAllDerivedClasses(baseType, sigType);
                foreach (var info in infos)
                {
                    var args = info.CreateArguments();
                    if (args == null)
                    {
                        continue;
                    }
                    var argInfo = CmdParser.GetArgInfo(args.GetType(), args);
                    foreach (var a in argInfo.Args)
                    {
                        GenerateImplCall(w, a, argSuffix + info.LoadNames[0]);
                    }
                }
            }
            else
            {
                if (IsColumnType(arg))
                {
                    w.WriteLine("builder.{0} = {1}.Split('|');", Capitalize(arg.LongName + argSuffix), arg.LongName + argSuffix);
                }
                else
                {
                    w.WriteLine("builder.{0} = {1}{2};", Capitalize(arg.LongName + argSuffix), CastIfNeeded(arg), arg.LongName + argSuffix);
                }
            }
        }
 private void GenerateParameterAttribute(IndentingTextWriter w, string displayName, object defaultValue, string description,
                                         string parent = null, string parentType = null, string parentValue = null)
 {
     w.WriteLine("[Help(Display = @\"{0}\", ToolTip = \"{1}\")]", PrettyPrintDisplayName(displayName), description);
     if (parent != null)
     {
         w.WriteLine("[Relevancy(Key = \"{0}\", Values = new object[] {{ {1}.{2} }})]", parent, parentType, parentValue);
     }
     if (defaultValue != null)
     {
         w.WriteLine("[Domain(DefaultValue = {0})]", defaultValue);
     }
     w.WriteLine("[ModuleParameter]");
 }
        private void ListKinds(IndentingTextWriter writer)
        {
            var sigs = _env.ComponentCatalog.GetAllSignatureTypes()
                       .Select(ComponentCatalog.SignatureToString)
                       .OrderBy(x => x);

            writer.WriteLine("Available component kinds:");
            using (writer.Nest())
            {
                foreach (var sig in sigs)
                {
                    writer.WriteLine(sig);
                }
            }
        }
Exemple #15
0
 protected override void GenerateUsings(IndentingTextWriter w)
 {
     w.WriteLine("using System;");
     w.WriteLine("using System.Diagnostics.CodeAnalysis;");
     w.WriteLine("using System.Linq;");
     w.WriteLine("using Microsoft.Analytics.MachineLearning;");
     w.WriteLine("using Microsoft.Analytics.Modules;");
     w.WriteLine("using Microsoft.ML.Runtime;");
     w.WriteLine("using Microsoft.ML.Runtime.CommandLine;");
     w.WriteLine("using Microsoft.ML.Runtime.Data;");
     w.WriteLine("using Microsoft.ML.Runtime.Internal.Internallearn;");
 }
Exemple #16
0
        protected void GenerateImplCall(IndentingTextWriter w, CmdParser.ArgInfo.Arg arg, string argSuffix)
        {
            if (Exclude.Contains(arg.LongName))
            {
                return;
            }

            if (IsColumnType(arg))
            {
                w.WriteLine("builder.{0} = {1}.Split('|');", Capitalize(arg.LongName + argSuffix), arg.LongName + argSuffix);
            }
            else
            {
                w.WriteLine("builder.{0} = {1}{2};", Capitalize(arg.LongName + argSuffix), CastIfNeeded(arg), arg.LongName + argSuffix);
            }
        }
        protected override void GenerateEnumValue(IndentingTextWriter w, ComponentCatalog.LoadableClassInfo info)
        {
            var name = info != null ? info.LoadNames[0] : "None";

            w.WriteLine("/// <summary> {0} option </summary>", name);
            w.Write("{0}", name);
        }
        private static void ShowMetadata(IndentingTextWriter itw, ISchema schema, int col, bool showVals)
        {
            Contracts.AssertValue(itw);
            Contracts.AssertValue(schema);
            Contracts.Assert(0 <= col && col < schema.ColumnCount);

            using (itw.Nest())
            {
                foreach (var kvp in schema.GetMetadataTypes(col).OrderBy(p => p.Key))
                {
                    Contracts.AssertNonEmpty(kvp.Key);
                    Contracts.AssertValue(kvp.Value);
                    var type = kvp.Value;
                    itw.Write("Metadata '{0}': {1}", kvp.Key, type);
                    if (showVals)
                    {
                        if (!type.IsVector)
                        {
                            ShowMetadataValue(itw, schema, col, kvp.Key, type);
                        }
                        else
                        {
                            ShowMetadataValueVec(itw, schema, col, kvp.Key, type);
                        }
                    }
                    itw.WriteLine();
                }
            }
        }
Exemple #19
0
        protected void GenerateModuleType(IndentingTextWriter w, ComponentCatalog.LoadableClassInfo component)
        {
            string cat;

            if (component.IsOfType(typeof(SignatureBinaryClassifierTrainer)))
            {
                cat = "BinaryClassifier";
            }
            else if (component.IsOfType(typeof(SignatureMultiClassClassifierTrainer)))
            {
                cat = "MultiClassClassifier";
            }
            else if (component.IsOfType(typeof(SignatureRegressorTrainer)))
            {
                cat = "Regression";
            }
            else if (component.IsOfType(typeof(SignatureAnomalyDetectorTrainer)))
            {
                cat = "AnomalyDetector";
            }
            else
            {
                cat = "None";
            }
            w.WriteLine("[DataLabModuleType(Type = ModuleType.{0})]", cat);
        }
        protected override void GenerateUsings(IndentingTextWriter w)
        {
            var allNamespaces = new HashSet <string>();

            foreach (var ns in Namespaces)
            {
                allNamespaces.Add(ns);
            }
            allNamespaces.Add("System.Collections.Generic");
            allNamespaces.Add("Microsoft.Analytics.Modules.Common");
            allNamespaces.Add("Microsoft.Analytics.Platform.ML.Models");
            allNamespaces.Add("Microsoft.ML.Runtime.Data");
            allNamespaces.Add("Microsoft.ML.Runtime.Modules.Contracts");
            allNamespaces.Add("Microsoft.ML.Runtime.Modules.Contracts.Attributes");
            allNamespaces.Add("Microsoft.ML.Runtime.Modules.Contracts.Types");
            var namespaces = allNamespaces.ToArray();

            Array.Sort(namespaces,
                       (a, b) =>
                       a.StartsWith("System") && !b.StartsWith("System") ? -1
                    : !a.StartsWith("System") && b.StartsWith("System") ? 1
                    : string.CompareOrdinal(a, b));
            foreach (var ns in namespaces)
            {
                w.WriteLine("using {0};", ns);
            }
        }
 protected override void GenerateMethodSignature(IndentingTextWriter w, string prefix,
                                                 ComponentCatalog.LoadableClassInfo component)
 {
     w.WriteLine("public static Tuple<IDataView, DataTransform> Create{0}{1}(", prefix, component.LoadNames[0]);
     using (w.Nest())
     {
         var argumentInfo = CmdParser.GetArgInfo(component.ArgType, component.CreateArguments());
         w.WriteLine("[DataLabInputPort(FriendlyName = \"IDataView\", DisplayName = \"IDataView\", IsOptional = false, DataTypes = WellKnownDataTypeIds.IDataViewDotNet, Description = \"Input data (IDataView)\")]");
         w.Write("IDataView data");
         var pre = ",";
         foreach (var arg in argumentInfo.Args.Where(a => !a.IsHidden))
         {
             GenerateMethodSignature(w, arg, null, null, null, ref pre, "");
         }
         w.WriteLine(")");
     }
 }
 protected override void GenerateImplBody(IndentingTextWriter w, ComponentCatalog.LoadableClassInfo component)
 {
     w.WriteLine("{");
     using (w.Nest())
     {
         w.WriteLine("var args = new {0}();", GetCSharpTypeName(component.ArgType));
         w.WriteLine("var defs = new {0}();", GetCSharpTypeName(component.ArgType));
         var argumentInfo = CmdParser.GetArgInfo(component.ArgType, component.CreateArguments());
         var arguments    = argumentInfo.Args.Where(a => !a.IsHidden).ToArray();
         foreach (var arg in arguments)
         {
             GenerateImplBody(w, arg, "");
         }
         w.WriteLine("return new Tuple<string, string>(\"{0}\", CmdParser.GetSettings(args, defs));", component.LoadNames[0]);
     }
     w.WriteLine("}");
 }
 protected override void GenerateImplCall(IndentingTextWriter w, string prefix, ComponentCatalog.LoadableClassInfo component)
 {
     w.WriteLine("{");
     using (w.Nest())
     {
         var className = prefix + component.LoadNames[0];
         w.WriteLine("var builder = new {0}();", className);
         var argumentInfo = CmdParser.GetArgInfo(component.ArgType, component.CreateArguments());
         var arguments    = argumentInfo.Args.Where(a => !a.IsHidden).ToArray();
         foreach (var arg in arguments)
         {
             GenerateImplCall(w, arg, "");
         }
         w.WriteLine("var learner = builder.GetTlcSettings();");
         w.WriteLine("return new TlcTrainer(learner.Item1, learner.Item2);");
     }
     w.WriteLine("}");
 }
Exemple #24
0
        protected override void GenerateEnumValue(IndentingTextWriter w, ComponentCatalog.LoadableClassInfo info)
        {
            var userName = info != null ? info.UserName : "******";
            var name     = info != null ? info.LoadNames[0] : "None";

            w.WriteLine("[ItemInfo(FriendlyName = \"{0}\", DisplayValue = \"{1}\")]", userName,
                        userName);
            w.Write("{0}", name);
        }
 protected override void GenerateMethodSignature(IndentingTextWriter w, string prefix, ComponentCatalog.LoadableClassInfo component)
 {
     w.WriteLine("/// <summary>");
     w.WriteLine("/// Creates a {0}", component.LoadNames[0]);
     w.WriteLine("/// </summary>");
     w.WriteLine("/// <param name=\"env\">The environment</param>");
     w.WriteLine("/// <param name=\"data\">The data set</param>");
     w.WriteLine("/// <returns>The transformed data.</returns>");
     w.WriteLine("public IDataView Create{0}{1}Impl(", prefix, component.LoadNames[0]);
     using (w.Nest())
     {
         w.WriteLine("IHostEnvironment env,");
         w.WriteLine("IDataView data)");
     }
 }
        private void ShowUsage(IndentingTextWriter writer, string kind, string summary, string loadName,
                               IReadOnlyList <string> loadNames, object args, int?columns)
        {
            _env.Assert(loadName == loadNames[0]);

            writer.WriteLine("Help for {0}: '{1}'", kind, loadName);
            using (writer.Nest())
                ShowAliases(writer, loadNames);

            writer.WriteLine();
            ShowFormattedSummary(writer, summary, columns);

            if (args == null)
            {
                writer.WriteLine("Component '{0}' is not configurable", loadName);
                writer.WriteLine();
            }
            else
            {
                writer.WriteLine(CmdParser.ArgumentsUsage(_env, args.GetType(), args, false, columns));
            }
        }
        protected override void GenerateSummaryComment(IndentingTextWriter w, ComponentCatalog.LoadableClassInfo component)
        {
            w.WriteLine("/// <summary>");
            var desc = component.Summary ?? component.LoadNames[0];

            using (var sr = new StringReader(desc))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    w.WriteLine("/// {0}", line);
                }
            }
            w.WriteLine("/// </summary>");
            var argumentInfo = CmdParser.GetArgInfo(component.ArgType, component.CreateArguments());
            var arguments    = argumentInfo.Args.Where(a => !a.IsHidden).ToArray();

            foreach (var arg in arguments)
            {
                GenerateSummaryComment(w, arg, "");
            }
        }
Exemple #28
0
        private void GenerateOutput(IndentingTextWriter writer, ModuleCatalog.EntryPointInfo entryPointInfo, out HashSet <string> outputVariableNames)
        {
            outputVariableNames = new HashSet <string>();
            string classBase = "";

            if (entryPointInfo.OutputKinds != null)
            {
                classBase = $" : {string.Join(", ", entryPointInfo.OutputKinds.Select(CSharpGeneratorUtils.GetCSharpTypeName))}";
            }
            writer.WriteLine($"public sealed class Output{classBase}");
            writer.WriteLine("{");
            writer.Indent();

            var outputType = entryPointInfo.OutputType;

            if (outputType.IsGenericType && outputType.GetGenericTypeDefinition() == typeof(CommonOutputs.MacroOutput <>))
            {
                outputType = outputType.GetGenericTypeArgumentsEx()[0];
            }
            foreach (var fieldInfo in outputType.GetFields())
            {
                var outputAttr = fieldInfo.GetCustomAttributes(typeof(TlcModule.OutputAttribute), false)
                                 .FirstOrDefault() as TlcModule.OutputAttribute;
                if (outputAttr == null)
                {
                    continue;
                }

                CSharpGeneratorUtils.GenerateSummary(writer, outputAttr.Desc);
                var outputTypeString = CSharpGeneratorUtils.GetOutputType(fieldInfo.FieldType);
                outputVariableNames.Add(CSharpGeneratorUtils.Capitalize(outputAttr.Name ?? fieldInfo.Name));
                writer.WriteLine($"public {outputTypeString} {CSharpGeneratorUtils.Capitalize(outputAttr.Name ?? fieldInfo.Name)} {{ get; set; }} = new {outputTypeString}();");
                writer.WriteLine();
            }

            writer.Outdent();
            writer.WriteLine("}");
        }
 protected override void GenerateUsings(IndentingTextWriter w)
 {
     w.WriteLine("using System;");
     w.WriteLine("using System.Linq;");
     w.WriteLine("using Microsoft.ML.Runtime;");
     w.WriteLine("using Microsoft.ML.Runtime.CommandLine;");
     w.WriteLine("using Microsoft.ML.Runtime.Data;");
     w.WriteLine("using Microsoft.ML.Runtime.Internal.Internallearn;");
 }
 protected override void GenerateMethodSignature(IndentingTextWriter w, string prefix, ComponentCatalog.LoadableClassInfo component)
 {
     w.Write("public static Tuple<ITrainer> Create{0}{1}(", prefix, component.LoadNames[0]);
     using (w.Nest())
     {
         var argumentInfo = CmdParser.GetArgInfo(component.ArgType, component.CreateArguments());
         var arguments    = argumentInfo.Args.Where(a => !a.IsHidden).ToArray();
         var pre          = "";
         foreach (var arg in arguments)
         {
             GenerateMethodSignature(w, arg, null, null, null, ref pre, "");
         }
         w.WriteLine(")");
     }
 }
        private static bool WriteUnitOfWork( IndentingTextWriter writer, InterfaceDeclaration declaration, ICollection<string> implementedInterfaces )
        {
            Contract.Requires( writer != null );
            Contract.Requires( declaration != null );
            Contract.Requires( implementedInterfaces != null );

            if ( implementedInterfaces.Contains( declaration.TypeName ) )
                return false;

            implementedInterfaces.Add( declaration.TypeName );

            writer.WriteLine( "bool {0}.HasPendingChanges", declaration.TypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "get" );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "return ChangeTracker.HasChanges();" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "void {0}.RegisterNew( {1} item )", declaration.TypeName, declaration.ArgumentTypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "Set<{0}>().Add( item );", declaration.ArgumentTypeName );
            writer.WriteLine( "OnPropertyChanged( new PropertyChangedEventArgs( \"HasPendingChanges\" ) );" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "void {0}.RegisterRemoved( {1} item )", declaration.TypeName, declaration.ArgumentTypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "Set<{0}>().Remove( item );", declaration.ArgumentTypeName );
            writer.WriteLine( "OnPropertyChanged( new PropertyChangedEventArgs( \"HasPendingChanges\" ) );" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "void {0}.RegisterChanged( {1} item )", declaration.TypeName, declaration.ArgumentTypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "if ( Entry( item ).State != EntityState.Detached )" );
            writer.Indent();
            writer.WriteLine( "return;" );
            writer.Unindent();
            writer.WriteLine();
            writer.WriteLine( "Set<{0}>().Attach( item );", declaration.ArgumentTypeName );
            writer.WriteLine( "Entry( item ).State = EntityState.Modified;" );
            writer.WriteLine( "OnPropertyChanged( new PropertyChangedEventArgs( \"HasPendingChanges\" ) );" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "void {0}.Unregister( {1} item )", declaration.TypeName, declaration.ArgumentTypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "Entry( item ).State = EntityState.Detached;" );
            writer.WriteLine( "OnPropertyChanged( new PropertyChangedEventArgs( \"HasPendingChanges\" ) );" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "void {0}.Rollback()", declaration.TypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "foreach ( var entry in ChangeTracker.Entries<{0}>() )", declaration.ArgumentTypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "switch ( entry.State )" );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "case EntityState.Modified:" );
            writer.WriteLine( "case EntityState.Deleted:" );
            writer.Indent();
            writer.WriteLine( "entry.CurrentValues.SetValues( entry.OriginalValues );" );
            writer.WriteLine( "entry.State = EntityState.Unchanged;" );
            writer.WriteLine( "break;" );
            writer.Unindent();
            writer.WriteLine( "case EntityState.Added:" );
            writer.Indent();
            writer.WriteLine( "entry.State = EntityState.Detached;" );
            writer.WriteLine( "break;" );
            writer.Unindent();
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "OnPropertyChanged( new PropertyChangedEventArgs( \"HasPendingChanges\" ) );" );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "async Task {0}.CommitAsync( CancellationToken cancellationToken )", declaration.TypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "await SaveChangesAsync( cancellationToken ).ConfigureAwait( false );" );
            writer.WriteLine( "OnPropertyChanged( new PropertyChangedEventArgs( \"HasPendingChanges\" ) );" );
            writer.Unindent();
            writer.WriteLine( "}" );

            return true;
        }
        private static bool WriteReadOnlyRepository( IndentingTextWriter writer, InterfaceDeclaration declaration, ICollection<string> implementedInterfaces )
        {
            Contract.Requires( writer != null );
            Contract.Requires( implementedInterfaces != null );

            if ( implementedInterfaces.Contains( declaration.TypeName ) )
                return false;

            implementedInterfaces.Add( declaration.TypeName );

            writer.WriteLine( "async Task<IEnumerable<{1}>> {0}.GetAsync( Func<IQueryable<{1}>, IQueryable<{1}>> queryShaper, CancellationToken cancellationToken )", declaration.TypeName, declaration.ArgumentTypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "return await queryShaper( Set<{0}>() ).ToArrayAsync( cancellationToken ).ConfigureAwait( false );", declaration.ArgumentTypeName );
            writer.Unindent();
            writer.WriteLine( "}" );
            writer.WriteLine();
            writer.WriteLine( "async Task<TResult> {0}.GetAsync<TResult>( Func<IQueryable<{1}>, TResult> queryShaper, CancellationToken cancellationToken )", declaration.TypeName, declaration.ArgumentTypeName );
            writer.WriteLine( "{" );
            writer.Indent();
            writer.WriteLine( "return await Task<TResult>.Factory.StartNew( () => queryShaper( Set<{0}>() ), cancellationToken ).ConfigureAwait( false );", declaration.ArgumentTypeName );
            writer.Unindent();
            writer.WriteLine( "}" );

            return true;
        }
        private static bool WritePropertyChangedImplementation( IndentingTextWriter writer, ICollection<string> implementedInterfaces )
        {
            Contract.Requires( writer != null );
            Contract.Requires( implementedInterfaces != null );

            if ( implementedInterfaces.Contains( INotifyPropertyChanged ) )
                return false;

            implementedInterfaces.Add( INotifyPropertyChanged );

            writer.WriteLine( "public event PropertyChangedEventHandler PropertyChanged;" );
            writer.WriteLine();
            writer.WriteLine( "private void OnPropertyChanged( PropertyChangedEventArgs e ) => PropertyChanged?.Invoke( this, e );" );

            return true;
        }
        private static void ImplementInterface( IndentingTextWriter writer, InterfaceDeclaration declaration, ICollection<string> implementedInterfaces )
        {
            Contract.Requires( writer != null );
            Contract.Requires( declaration != null );
            Contract.Requires( implementedInterfaces != null );

            switch ( declaration.Key )
            {
                case IReadOnlyRepository:
                    WriteReadOnlyRepository( writer, declaration, implementedInterfaces );
                    break;
                case IRepository:
                    var inheritedDeclaration = new InterfaceDeclaration( IReadOnlyRepository, declaration );

                    if ( WritePropertyChangedImplementation( writer, implementedInterfaces ) )
                        writer.WriteLine();

                    if ( WriteReadOnlyRepository( writer, inheritedDeclaration, implementedInterfaces ) )
                        writer.WriteLine();

                    WriteRepository( writer, declaration, implementedInterfaces );
                    break;
                case IUnitOfWork:
                    if ( WritePropertyChangedImplementation( writer, implementedInterfaces ) )
                        writer.WriteLine();

                    WriteUnitOfWork( writer, declaration, implementedInterfaces );
                    break;
            }
        }
        private static void WriteEndClass( IndentingTextWriter writer, bool hasNamespace )
        {
            Contract.Requires( writer != null );

            if ( hasNamespace )
            {
                writer.Unindent();
                writer.WriteLine( "}" );
            }

            writer.Unindent();
            writer.Write( "}" );
        }
        private static bool WriteStartClass(
            IndentingTextWriter writer,
            string defaultNamespace,
            IReadOnlyList<UsingDirectiveSyntax> usings,
            ClassDeclarationSyntax @class )
        {
            Contract.Requires( writer != null );
            Contract.Requires( defaultNamespace != null );
            Contract.Requires( usings != null );
            Contract.Requires( @class != null );

            var @namespace = ResolveNamespace( @class, defaultNamespace );
            var hasNamespace = !string.IsNullOrEmpty( @namespace );
            var className = @class.Identifier.Text;

            if ( hasNamespace )
            {
                writer.WriteLine( "namespace {0}", @namespace );
                writer.WriteLine( "{" );
                writer.Indent();
            }

            WriteUsings( writer, usings );
            writer.WriteLine();
            writer.WriteLine( "/// <content>" );
            writer.WriteLine( "/// Provides auto-generated interfaces for the <see cref=\"{0}\" /> class. To add addition interfaces,", className );
            writer.WriteLine( "/// implement the interface in the main source file." );
            writer.WriteLine( "/// <seealso cref=\"IReadOnlyRepository{T}\" />" );
            writer.WriteLine( "/// <seealso cref=\"IRepository{T}\" />" );
            writer.WriteLine( "/// <seealso cref=\"IUnitOfWork{T}\" />." );
            writer.WriteLine( "/// <content>" );
            writer.WriteLine( "[GeneratedCode( \"More Framework\", \"1.0\" )]" );
            writer.WriteLine( "{0}partial class {1}", ResolveScopeModifier( @class ), className );
            writer.WriteLine( "{" );
            writer.Indent();

            return hasNamespace;
        }
        private static void WriteUsings( IndentingTextWriter writer, IReadOnlyList<UsingDirectiveSyntax> declaredUsings )
        {
            Contract.Requires( writer != null );
            Contract.Requires( declaredUsings != null );

            var usings = new SortedSet<UsingDirectiveSyntax>( UsingDirectiveComparer.Instance );

            // merge sorted, distinct list of required and declared usings
            usings.AddRange( RequiredUsings );
            usings.AddRange( declaredUsings );

            // write out required usings
            foreach ( var @using in usings )
                writer.WriteLine( @using );
        }