예제 #1
0
        /// <summary>
        /// 変換メソッド:else
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemElseClause item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // 定義
            if (item.Conditions.Any())
            {
                result.AppendLine($"{indentSpace}else if ({ConvertConditions(item.Conditions)}) {{");
            }
            else
            {
                result.AppendLine($"{indentSpace}else {{");
            }

            // メンバー追加
            foreach (var member in item.Block)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            return(result.ToString());
        }
예제 #2
0
        /// <summary>
        /// 変換メソッド:switch
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemSwitch item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // caseがtypeチェックとローカルフィールド設定か否か
            var existsTypes = item.Cases.Where(caseItem => ExistsTypeCase(caseItem as IItemSwitchCase)).Any();


            if (!existsTypes)
            {
                // 定義(switchのみ)
                result.AppendLine($"{indentSpace}switch ({ExpressionsToString(item.Conditions)}) {{");

                // caseはインデントをインクリメント
                indent++;
            }

            // メンバー追加
            foreach (var member in item.Cases)
            {
                result.Append(ConvertUtility.Convert(member, config, indent, otherScripts));
            }

            if (!existsTypes)
            {
                // 定義(switchのみ)
                result.AppendLine($"{indentSpace}}}");
            }

            return(result.ToString());
        }
예제 #3
0
        /// <summary>
        /// 変換メソッド:if
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemIf item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // 定義
            result.AppendLine($"{indentSpace}if ({ConvertConditions(item.Conditions)}) {{");

            // メンバー追加
            foreach (var member in item.TrueBlock)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            // else構文追加
            foreach (var block in item.FalseBlocks)
            {
                result.Append(ConvertUtility.Convert(block, config, indent, otherScripts));
            }

            return(result.ToString());
        }
예제 #4
0
        /// <summary>
        /// 変換メソッド:for
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemFor item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // 定義
            var declarations = GetDeclarations(item);
            var letKeyword   = item.IsVar ? "let " : string.Empty;
            var incrementors = item.Incrementors.Select(incrementor => ExpressionsToString(incrementor));

            result.AppendLine($"{indentSpace}for ({letKeyword}{string.Join(", ", declarations)}; {ExpressionsToString(item.Conditions)}; {string.Join(", ", incrementors)}) {{");

            // メンバー追加
            foreach (var member in item.Members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            return(result.ToString());
        }
예제 #5
0
        /// <summary>
        /// 変換メソッド
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="indent">インデント数</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemClass item, Config config, int indent, List <string> otherScripts)
        {
            var result    = new StringBuilder();
            var classType = GetClassType(item);

            // 内部クラスの場合はインデント固定
            if (classType == ClassType.Inner)
            {
                indent = 1;
            }
            var indentSpace = GetIndentSpace(indent);

            // クラスコメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // クラス定義
            result.Append(indentSpace);
            switch (classType)
            {
            case ClassType.Normal:
                result.Append($"{GetScope(item)}class {item.Name}{GetClassInfo(item)}");
                break;

            case ClassType.Inner:
                result.Append($"export class {item.Name}{GetClassInfo(item)}");
                break;
            }
            result.AppendLine(" {");

            // メンバー追加
            var members = item.Members;

            if (config.Mode.Value == OutputMode.Mode.WithoutMethod)
            {
                members = members.Where(member => member is IItemField || member is IItemProperty || member is IItemClass || member is IItemInterface).ToList();
            }

            foreach (var member in members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            // 内部クラスの場合はotherScriptsに格納
            if (classType == ClassType.Inner)
            {
                otherScripts.Add($"export namespace {GetParentClessName(item)} {{");
                otherScripts.Add($"{result.ToString()}}}");
                otherScripts.Add($"");

                // 親クラスのメンバーに含めない
                result.Clear();
            }

            return(result.ToString());
        }
예제 #6
0
        public string Convert(IItemInterface item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // インターフェイス定義
            result.Append(indentSpace);
            result.Append($"{GetScope(item)}interface {item.Name}");

            // ジェネリックスクラス
            if (item.GenericTypes.Any())
            {
                result.Append("<");
                result.Append(string.Join(", ", item.GenericTypes.Select(typeItem => GetTypeScriptType(typeItem))));
                result.Append(">");
            }

            // インターフェイスあり
            if (item.Interfaces.Any())
            {
                var interfaceList = new List <string>();
                foreach (var targetItemList in item.Interfaces)
                {
                    // インターフェース名追加
                    interfaceList.Add(ExpressionsToString(targetItemList));
                }

                result.Append(" implements ");
                result.Append(string.Join(", ", interfaceList.Select(typeItem => GetTypeScriptType(typeItem))));
            }

            result.AppendLine(" {");

            // メンバー追加
            var members = item.Members;

            if (config.Mode.Value == OutputMode.Mode.WithoutMethod)
            {
                members = members.Where(member => member is IItemField || member is IItemProperty || member is IItemClass || member is IItemInterface).ToList();
            }

            foreach (var member in members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            return(result.ToString());
        }
예제 #7
0
        public override ValueProvider <TResult> TryEvaluate(TContext context, string reference)
        {
            if (string.IsNullOrEmpty(reference) == false && (this.Settings.RequireSymbolForMemberReferences == false || reference[0] == '$'))
            {
                string     error;
                MethodInfo method;
                var        name = reference.TrimStart('$');
                if (MemberFinder.Start(context.GetParentType())
                    .IsMethod()
                    .HasNoParameters()
                    .HasConvertableReturnType <TResult>()
                    .IsNamed(name)
                    .TryGetMember <MethodInfo>(out method, out error))
                {
                    bool isStatic = method.IsStatic();
                    Func <object, TResult> methodCaller;

                    if (isStatic)
                    {
                        // TODO: Emit
                        methodCaller = instance =>
                        {
                            return(ConvertUtility.Convert <TResult>(method.Invoke(null, null)));
                        };
                    }
                    else
                    {
                        // TODO: Emit
                        methodCaller = instance =>
                        {
                            if (instance == null)
                            {
                                throw new NullReferenceException();
                            }

                            return(ConvertUtility.Convert <TResult>(method.Invoke(instance, null)));
                        };
                    }

                    return(new FuncValueProvider <TResult>(context, isStatic == false, methodCaller));
                }
                else
                {
                    context.LogFailInfoFormat(this, " - {0} {1}", typeof(TResult).GetNiceName(), name);
                    return(null);
                }
            }
            else
            {
                return(null);
            }
        }
예제 #8
0
        /// <summary>
        /// 変換メソッド:case
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemSwitchCase item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // typeチェックとローカルフィールド設定か否か
            var existsTypes = ExistsTypeCase(item);

            // 定義 case か if の出力分岐
            if (existsTypes)
            {
                result.Append(CreateCaseIf(item, indent));
            }
            else
            {
                // case
                foreach (var label in item.Labels)
                {
                    result.Append($"{indentSpace}");
                    if (label.First().TypeName != "Default")
                    {
                        result.Append("case ");
                    }
                    result.AppendLine($"{ExpressionsToString(label)}:");
                }
            }

            // メンバー追加
            foreach (var member in item.Members)
            {
                // if構文に変化した場合はbreakを除外
                if (existsTypes && member is IItemBreak)
                {
                    continue;
                }

                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            if (existsTypes)
            {
                // if : ブロック終了
                result.AppendLine($"{indentSpace}}}");
            }

            return(result.ToString());
        }
예제 #9
0
        /// <summary>
        /// プロパティのset/get用Typescriptを返す
        /// </summary>
        /// <param name="accessorItem">set/get用のアイテム</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="scope">スコープ名</param>
        /// <param name="propertyName">プロパティ名</param>
        /// <param name="propertyType">プロパティの型</param>
        /// <param name="refTarget">参照名(インスタンス参照の場合はthis)</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>set/get用Typescriptの文字列</returns>
        private string GetAccessorString(IAnalyzeItem accessorItem, Config config, int indent, string scope, string propertyName, string propertyType, string refTarget, List <string> otherScripts)
        {
            var indentSpace = GetIndentSpace(indent);

            var result          = new StringBuilder();
            var notExistsMember = true;

            if (accessorItem.Members.Any())
            {
                notExistsMember = false;
            }

            // set/getの設定
            var accessorItemName = accessorItem.Name.ToLower(CultureInfo.CurrentCulture);

            switch (accessorItemName)
            {
            case "set":
                result.AppendLine($"{indentSpace}{scope}set {propertyName}(value: {propertyType}) {{");

                if (notExistsMember)
                {
                    result.AppendLine($"{GetIndentSpace(indent + 1)}{refTarget}._{propertyName}_ = value;");
                }
                break;

            case "get":
                result.AppendLine($"{indentSpace}{scope}get {propertyName}(): {propertyType} {{");

                if (notExistsMember)
                {
                    result.AppendLine($"{GetIndentSpace(indent + 1)}return {refTarget}._{propertyName}_;");
                }
                break;

            default:
                return(result.ToString());
            }

            // メンバー追加
            foreach (var member in accessorItem.Members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            return(result.ToString());
        }
예제 #10
0
        /// <summary>
        /// 変換メソッド
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemLocalFunction item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // パラメータ取得
            var args = new List <string>();

            foreach (var arg in item.Args)
            {
                args.Add($"{arg.name}: {ExpressionsToString(arg.expressions)}");
            }

            // ジェネリックスクラス
            var genericTypes = new StringBuilder();

            if (item.GenericTypes.Any())
            {
                genericTypes.Append("<");
                genericTypes.Append(string.Join(", ", item.GenericTypes.Select(typeItem => GetTypeScriptType(typeItem))));
                genericTypes.Append(">");
            }

            // 定義
            result.Append($"{indentSpace}let {item.Name} = {genericTypes.ToString()}(");
            result.Append(string.Join(", ", args));
            result.AppendLine($"): {ExpressionsToString(item.MethodTypes)} => {{");

            // メンバー追加
            foreach (var member in item.Members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}};");

            return(result.ToString());
        }
예제 #11
0
        /// <summary>
        /// 変換メソッド:while
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemWhile item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // 定義
            result.AppendLine($"{indentSpace}while ({ExpressionsToString(item.Conditions)}) {{");

            // メンバー追加
            foreach (var member in item.Members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            return(result.ToString());
        }
예제 #12
0
        /// <summary>
        /// 変換メソッド:foreach
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemForEach item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // 定義
            var isMultiParams       = false;
            var multiParamLocalName = string.Empty;
            var localName           = ExpressionsToString(item.Local);

            if (item.CollectionTypes.First().Name == "Dictionary")
            {
                multiParamLocalName = localName;
                isMultiParams       = true;
                localName           = "[k, v]";
            }

            result.AppendLine($"{indentSpace}for (let {localName} of {ExpressionsToString(item.Collection)}) {{");

            // 複数要素の場合はローカル変数作成
            if (isMultiParams)
            {
                result.AppendLine($"{GetIndentSpace(indent + 1)}let {multiParamLocalName} = {{ \"Key\": k, \"Value\": v }};");
            }

            // メンバー追加
            foreach (var member in item.Members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            return(result.ToString());
        }
예제 #13
0
        /// <summary>
        /// 変換メソッド
        /// </summary>
        /// <param name="item">C#解析結果</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string Convert(IItemConstructor item, Config config, int indent, List <string> otherScripts)
        {
            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // クラス情報を取得
            var classInstanse = item.Parent as IItemClass;
            var className     = classInstanse.Name;
            var targetIndex   = 1;
            var targetItems   = classInstanse.Members.Where(member => member is IItemConstructor)
                                .Select(member => (index: targetIndex++, item: member as IItemConstructor)).ToList();
            var existSuper = classInstanse.SuperClass.Any();
            var isOverload = targetItems.Count() > 1;

            // 複数コンストラクタの存在確認
            var indexValue = string.Empty;

            if (isOverload)
            {
                // インデックスの設定
                foreach (var targetItem in targetItems)
                {
                    if (targetItem.item == item)
                    {
                        indexValue = $"{targetItem.index}";
                    }
                }
            }

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // パラメータ取得
            var args = new List <string>();

            foreach (var arg in item.Args)
            {
                args.Add($"{arg.name}: {ExpressionsToString(arg.expressions)}");
            }

            // 定義
            var scope = GetScope(item);

            if (scope == "public ")
            {
                scope = string.Empty;
            }
            if (isOverload)
            {
                scope = "private ";
            }
            result.Append($"{indentSpace}{scope}{BaseMethodName}{indexValue}");
            result.Append("(");
            result.Append(string.Join(", ", args));
            result.Append(")");
            result.AppendLine(" {");

            // メンバー追加
            if (existSuper)
            {
                // スーパークラスありの場合はコンストラクタを呼び出す
                result.Append($"{GetIndentSpace(indent + 1)}base(");
                result.Append(string.Join(", ", item.BaseArgs));
                result.AppendLine(");");
            }
            foreach (var member in item.Members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            // 複数メソッドで最終メソッドの場合は総括メソッドを作成する
            if (isOverload && targetItems.Last().item == item)
            {
                // 総合メソッド内処理用文字列
                var methodResult = new StringBuilder();

                // パラメータ数のリスト取得
                var paramCounts     = targetItems.Select(member => member.item.Args.Count);
                var existsNoneParam = paramCounts.Min() <= 0;
                var maxParamCount   = paramCounts.Max();

                // パラメータリストを生成
                var methodArgs = new Dictionary <int, List <string> >();
                for (var index = 1; index <= maxParamCount; index++)
                {
                    methodArgs.Add(index, new List <string>());
                }

                // メソッドパラメータの格納とメソッド内処理の作成
                foreach (var targetItem in targetItems)
                {
                    // 1メソッドのパラメータ取得
                    var argIndex         = 1;
                    var ifConditions     = new List <string>();
                    var callMethodParams = new List <string>();
                    foreach (var arg in targetItem.item.Args)
                    {
                        var expressionsValue = ExpressionsToString(arg.expressions);

                        // メソッドパラメータに追加
                        if (!methodArgs[argIndex].Contains(expressionsValue))
                        {
                            methodArgs[argIndex].Add(expressionsValue);
                        }

                        // メソッド内条件
                        ifConditions.Add(GetCondition(argIndex, expressionsValue));

                        // 呼び出しメソッドのパラメータ
                        callMethodParams.Add($"param{argIndex}");

                        argIndex++;
                    }
                    // メソッド内条件の追加
                    while (argIndex <= maxParamCount)
                    {
                        ifConditions.Add(GetCondition(argIndex, "undefined"));
                        argIndex++;
                    }

                    // メソッド内処理の追加
                    var methodSpace = GetIndentSpace(indent + 1);
                    methodResult.AppendLine($"{methodSpace}if ({string.Join(" && ", ifConditions)}) {{");
                    methodResult.Append($"{GetIndentSpace(indent + 2)}this.{BaseMethodName}{targetItem.index}");
                    methodResult.Append("(");
                    methodResult.Append(string.Join(", ", callMethodParams));
                    methodResult.AppendLine(");");
                    methodResult.AppendLine($"{GetIndentSpace(indent + 2)}return;");
                    methodResult.AppendLine($"{methodSpace}}}");
                }

                // 総合メソッドの作成
                scope = GetScope(item);
                if (scope == "public ")
                {
                    scope = string.Empty;
                }
                result.Append($"{indentSpace}{scope}{BaseMethodName}(");
                for (var index = 1; index <= maxParamCount; index++)
                {
                    if (index > 1)
                    {
                        result.Append(", ");
                    }

                    result.Append($"param{index}");
                    if (existsNoneParam)
                    {
                        result.Append("?");
                    }
                    result.Append($": {string.Join(" | ", methodArgs[index])}");
                }
                result.AppendLine(") {");
                result.Append(methodResult.ToString());
                result.AppendLine($"{indentSpace}}}");
            }

            return(result.ToString());
        }
예제 #14
0
        /// <summary>
        /// 変換メソッド メイン処理(class)
        /// </summary>
        /// <param name="parentInstanse">親インスタンス</param>
        /// <param name="item">C#解析結果</param>
        /// <param name="config">設定情報</param>
        /// <param name="indent">インデント数</param>
        /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param>
        /// <returns>TypeScript変換結果</returns>
        private string ConvertMain(IItemClass parentInstanse, IItemMethod item, Config config, int indent, List <string> otherScripts)
        {
            // 親インスタンスがnullの場合はそのまま終了
            if (parentInstanse is null)
            {
                return(string.Empty);
            }

            var result      = new StringBuilder();
            var indentSpace = GetIndentSpace(indent);

            // メソッド名
            string BaseMethodName = item.Name;

            // クラス情報(親インスタンス)を取得
            var className   = parentInstanse.Name;
            var targetIndex = 1;
            var targetItems = parentInstanse.Members.Where(member => member is IItemMethod && member.Name == BaseMethodName)
                              .Select(member => (index: targetIndex++, item: member as IItemMethod)).ToList();
            var isOverload = targetItems.Count() > 1;
            var returnType = ExpressionsToString(item.MethodTypes);
            var isReturn   = returnType != "void";

            // 複数コンストラクタの存在確認
            var indexValue = string.Empty;

            if (isOverload)
            {
                // インデックスの設定
                foreach (var targetItem in targetItems)
                {
                    if (targetItem.item == item)
                    {
                        indexValue = $"{targetItem.index}";
                    }
                }
            }

            // コメント
            result.Append(GetTypeScriptComments(item, indentSpace));

            // パラメータ取得
            var args = new List <string>();

            foreach (var arg in item.Args)
            {
                args.Add($"{arg.name}: {ExpressionsToString(arg.expressions)}");
            }

            // 定義
            var scope = GetScope(item);

            if (isOverload)
            {
                scope = "private ";
            }
            if (item.Modifiers.Contains("static"))
            {
                scope += "static ";
            }

            result.Append($"{indentSpace}{scope}{BaseMethodName}{indexValue}");
            // ジェネリックスクラス
            if (item.GenericTypes.Any())
            {
                result.Append("<");
                result.Append(string.Join(", ", item.GenericTypes.Select(typeItem => GetTypeScriptType(typeItem))));
                result.Append(">");
            }
            result.Append("(");
            result.Append(string.Join(", ", args));
            result.Append($"): {returnType}");
            result.AppendLine(" {");

            // メンバー追加
            foreach (var member in item.Members)
            {
                result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts));
            }

            result.AppendLine($"{indentSpace}}}");

            // 複数メソッドで最終メソッドの場合は総括メソッドを作成する
            if (isOverload && targetItems.Last().item == item)
            {
                // 総合メソッド内処理用文字列
                var methodResult = new StringBuilder();

                // パラメータ数のリスト取得
                var paramCounts     = targetItems.Select(member => member.item.Args.Count);
                var existsNoneParam = paramCounts.Min() <= 0;
                var maxParamCount   = paramCounts.Max();

                // 戻り値の取得
                var retrunTypes = targetItems.
                                  Select(returnTypeItem => ExpressionsToString(returnTypeItem.item.MethodTypes)).
                                  Distinct();
                var isMultiReturnType = retrunTypes.Count() > 1;

                // パラメータリストを生成
                var methodArgs = new Dictionary <int, List <string> >();
                for (var index = 1; index <= maxParamCount; index++)
                {
                    methodArgs.Add(index, new List <string>());
                }

                // メソッドパラメータの格納とメソッド内処理の作成
                foreach (var targetItem in targetItems)
                {
                    // 1メソッドのパラメータ取得
                    var argIndex         = 1;
                    var ifConditions     = new List <string>();
                    var callMethodParams = new List <string>();
                    foreach (var arg in targetItem.item.Args)
                    {
                        var expressionsValue = ExpressionsToString(arg.expressions);

                        // メソッドパラメータに追加
                        if (!methodArgs[argIndex].Contains(expressionsValue))
                        {
                            methodArgs[argIndex].Add(expressionsValue);
                        }

                        // メソッド内条件
                        ifConditions.Add(GetCondition(argIndex, expressionsValue));

                        // 呼び出しメソッドのパラメータ
                        callMethodParams.Add($"param{argIndex}");

                        argIndex++;
                    }
                    // メソッド内条件の追加
                    while (argIndex <= maxParamCount)
                    {
                        ifConditions.Add(GetCondition(argIndex, "undefined"));
                        argIndex++;
                    }

                    // メソッド内処理の追加
                    var methodSpace = GetIndentSpace(indent + 1);
                    methodResult.AppendLine($"{methodSpace}if ({string.Join(" && ", ifConditions)}) {{");

                    methodResult.Append($"{GetIndentSpace(indent + 2)}");
                    if (isMultiReturnType)
                    {
                        methodResult.Append($"return ");
                    }
                    methodResult.Append($"this.{BaseMethodName}{targetItem.index}");
                    methodResult.Append("(");
                    methodResult.Append(string.Join(", ", callMethodParams));
                    methodResult.AppendLine(");");
                    if (!isMultiReturnType)
                    {
                        methodResult.AppendLine($"{GetIndentSpace(indent + 2)}return;");
                    }

                    methodResult.AppendLine($"{methodSpace}}}");
                }

                // 総合メソッドの作成
                result.Append($"{indentSpace}{GetScope(item)}{BaseMethodName}(");

                // パラメータ設定
                for (var index = 1; index <= maxParamCount; index++)
                {
                    if (index > 1)
                    {
                        result.Append(", ");
                    }

                    result.Append($"param{index}");
                    if (existsNoneParam)
                    {
                        result.Append("?");
                    }
                    result.Append($": {string.Join(" | ", methodArgs[index])}");
                }

                // 戻り値
                var methodType = string.Join(" | ", retrunTypes);
                //if(isMultiReturnType)
                //{
                //  methodType = "any";
                //}

                result.Append($"): {methodType}");
                result.AppendLine(" {");
                result.Append(methodResult.ToString());
                result.AppendLine($"{GetIndentSpace(indent + 1)}throw new Error('Error');");
                result.AppendLine($"{indentSpace}}}");
            }

            return(result.ToString());
        }
예제 #15
0
        public override ValueProvider <TResult> TryEvaluate(TContext context, string reference)
        {
            if (string.IsNullOrEmpty(reference) == false && (this.Settings.RequireSymbolForMemberReferences == false || reference[0] == '$'))
            {
                string name = reference.TrimStart('$');

                var finder = MemberFinder.Start(context.GetParentType())
                             .HasNoParameters()
                             .HasConvertableReturnType <TResult>()
                             .IsNamed(name);

                if (this.IsStatic(context))
                {
                    finder = finder.IsStatic();
                }

                string     error;
                MemberInfo member;
                if (finder.TryGetMember(out member, out error))
                {
                    bool isStatic = member.IsStatic();
                    Func <object, TResult> getter;

                    if (isStatic)
                    {
                        if (member is MethodInfo)
                        {
                            // TODO: Emit.
                            var method = member as MethodInfo;
                            getter = instance =>
                            {
                                return(ConvertUtility.Convert <TResult>(method.Invoke(null, null)));
                            };
                        }
                        else
                        {
                            // TODO: Emit
                            getter = instance =>
                            {
                                return(ConvertUtility.Convert <TResult>(member.GetMemberValue(null)));
                            };
                        }
                    }
                    else
                    {
                        if (member is MethodInfo)
                        {
                            // TODO: Emit.
                            var method = member as MethodInfo;
                            getter = instance =>
                            {
                                if (instance == null)
                                {
                                    throw new NullReferenceException("Parent instance missing.");
                                }

                                return(ConvertUtility.Convert <TResult>(method.Invoke(instance, null)));
                            };
                        }
                        else
                        {
                            // TODO: Emit
                            getter = instance =>
                            {
                                if (instance == null)
                                {
                                    throw new NullReferenceException("Parent instance missing.");
                                }

                                return(ConvertUtility.Convert <TResult>(member.GetMemberValue(instance)));
                            };
                        }
                    }

                    return(new FuncValueProvider <TResult>(context, isStatic == false, getter));

                    //if (member.IsStatic())
                    //{
                    //    if (member is MethodInfo)
                    //    {
                    //        var method = member as MethodInfo;
                    //        return new FuncValueProvider<TResult>(context, false, o => ConvertUtility.Convert<TResult>(method.Invoke(null, null)));
                    //    }
                    //    // TODO: Can PropertyInfo and FieldInfo be straight as one?
                    //    else if (member is PropertyInfo)
                    //    {

                    //        EmitUtilities.CreateGetter
                    //    }
                    //    else if (member is FieldInfo)
                    //    {
                    //        var field = member as FieldInfo;
                    //        //EmitUtilities.CreateStaticFieldGetter
                    //        //return new FuncValueProvider<TResult>(context, false, o => ConvertUtility.Convert<TResult>(member.GetMemberValue(null)));
                    //        if (typeof(TResult).IsAssignableFrom(field.GetReturnType()))
                    //        {
                    //            var getter = EmitUtilities.CreateStaticFieldGetter<TResult>(field);
                    //            return new StaticFuncValueProvider<TResult>(context, getter);
                    //        }
                    //        else
                    //        {
                    //            var getter = EmitUtilities.CreateWeakStaticFieldGetter(field);
                    //            return new StaticFuncValueProvider<TResult>(context, () => ConvertUtility.Convert<TResult>(getter()));
                    //        }
                    //    }
                    //    else
                    //    {
                    //        throw new InvalidOperationException("Hang on that's not right.");
                    //    }
                    //}
                    //else
                    //{
                    //    return new MemberValueProvider<TResult>(context, member);
                    //}
                }
                else
                {
                    context.LogFailInfo(this, "Cannot find a member in type '" + context.GetParentType().GetNiceName() + "' named '" + name + "' with a return type castable to '" + typeof(TResult).GetNiceName() + "'");
                }
            }

            return(null);
        }
        public override ValueProvider <TResult> TryEvaluate(TContext context, string reference)
        {
            if (string.IsNullOrEmpty(reference) == false && reference[0] == '@')
            {
                string expression = reference.Substring(1);
                bool   isStatic   = this.IsStatic(context);

                var parameters = context.GetExpressionParameters();

                if (parameters != null && parameters.Length > 0)
                {
                    string[]        pNames   = new string[parameters.Length];
                    Type[]          pTypes   = new Type[parameters.Length];
                    Func <object>[] pGetters = new Func <object> [parameters.Length];

                    for (int i = 0; i < parameters.Length; i++)
                    {
                        pNames[i]   = parameters[i].Name;
                        pTypes[i]   = parameters[i].Type;
                        pGetters[i] = parameters[i].GetValue;
                    }

                    string error;
                    var    method = ExpressionUtility.ParseExpression(expression, isStatic, context.GetParentType(), pTypes, pNames, out error);

                    if (!method.Method.ReturnType.IsCastableTo(typeof(TResult)))
                    {
                        error = "The expression '" + expression + "' evaluates to type '" + method.Method.ReturnType.GetNiceName() + "', which cannot be cast to expected type '" + typeof(TResult).GetNiceName() + "'.";
                    }

                    if (error != null)
                    {
                        context.LogFailInfo(this, error);
                        return(null);
                    }
                    else if (isStatic)
                    {
                        object[] valueBuffer = new object[parameters.Length];
                        return(new FuncValueProvider <TResult>(context, false, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke(GetValues(valueBuffer, pGetters)))));
                    }
                    else
                    {
                        object[] valueBuffer = new object[parameters.Length + 1];
                        return(new FuncValueProvider <TResult>(context, true, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke(GetValues(valueBuffer, instance, pGetters)))));
                    }
                }
                else
                {
                    string error;
                    var    method = ExpressionUtility.ParseExpression(expression, isStatic, context.GetParentType(), out error);

                    if (!method.Method.ReturnType.IsCastableTo(typeof(TResult)))
                    {
                        error = "The expression '" + expression + "' evaluates to type '" + method.Method.ReturnType.GetNiceName() + "', which cannot be cast to expected type '" + typeof(TResult).GetNiceName() + "'.";
                    }

                    if (error != null)
                    {
                        context.LogFailInfo(this, error);
                        return(null);
                    }
                    else if (isStatic)
                    {
                        return(new FuncValueProvider <TResult>(context, false, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke())));
                    }
                    else
                    {
                        return(new FuncValueProvider <TResult>(context, true, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke(instance))));
                    }
                }
            }
            else
            {
                return(null);
            }
        }