static void Main(string[] args)
        {
            /** GlobalFunction 
            [VScript]: ---[[AddFOWViewer  Add temporary vision for a given team(nTeamID, vLocation, flRadius, flDuration, bObstructedVision)]]
            [VScript]: -- @return void
            [VScript]: -- @param int_1 int
            [VScript]: -- @param Vector_2 Vector
            [VScript]: -- @param float_3 float
            [VScript]: -- @param float_4 float
            [VScript]: -- @param bool_5 bool
            [VScript]: function AddFOWViewer(int_1, Vector_2, float_3, float_4, bool_5 ) end
            */

            /** NoneGlobalFunction
            [   VScript ]: ---[[ CDOTA_BaseNPC:HasAbility  See whether this unit has an ability by name. ]]
            [   VScript ]: -- @return bool
            [   VScript ]: -- @param pszAbilityName string
            [   VScript ]: function CDOTA_BaseNPC:HasAbility( pszAbilityName ) end
            */

            foreach (string ga in File.ReadAllLines("ga"))
                GlobalAccessor[ga.Split('=')[1]] = ga.Split('=')[0];
            Console.WriteLine("all global accossors count = " + GlobalAccessor.Count);

            string funcStart = @"[   VScript ]: function ";
            string paramStart = @"[   VScript ]: -- @param ";
            string commentStart = @"[   VScript ]: ---[[";
            string returnStart = @"[   VScript ]: -- @return ";
            string[] lines = File.ReadAllLines("script_help2");

            List<D2Function> allFuncs = new List<D2Function>();

            for(int i = 0; i < lines.Length; i++)
            {
                string line = lines[i];
                if (!isStartWith(line, funcStart))
                    continue;
                else
                {

                    D2Function func = new D2Function();
                    string funcBody = getBody(line, funcStart);
                    DealWithFuncBody(funcBody, ref func);

                    //int paramIndex = 0;

                    for(int j = i - 1; j>=0;j--)
                    {
                        string ll = lines[j];
                        if (isStartWith(ll, funcStart))
                            break;
                        else
                        {
                            if (isStartWith(ll, commentStart))
                            {
                                ll = getBody(ll, commentStart);
                                DealWithCommentLine(ll, ref func);
                            }
                            //if (isStartWith(ll, returnStart))
                            //{
                            //    ll = getBody(ll, returnStart);
                            //    DealWithReturnLine(ll, ref func);
                            //}
                            //if (isStartWith(ll, paramStart))
                            //{
                            //    ll = getBody(ll, paramStart);
                            //    DealWithParameters(ll, paramIndex, ref func);
                            //    paramIndex ++;
                            //}
                        }
                    }

                    allFuncs.Add(func);
                }

            }

            StringBuilder sb = new StringBuilder();
            sb.Append("// This file is auto generated by a tool\n{\r\t\"scope\": \t\"source.lua\",\r\t\"completions\":\r\t[\r");
            foreach (D2Function func in allFuncs)
            {
                if (func.Class != null)
                    sb.AppendLine("\t\t" + func.ToCompletionWithClass(GlobalAccessor) + ",");
                sb.AppendLine("\t\t" + func.ToCompletionWithoutClass() + ",");
            }

            string s = sb.ToString().Substring(0, sb.ToString().Length - 3);
            sb = new StringBuilder(s);
            sb.Append("\r\t]\r}");
            File.WriteAllText("Functions.sublime-completions",sb.ToString());

            Console.Write("DONE! PRESS ANYKEY TO EXIT");
            Console.ReadKey();
        }
        private static void DealWithCommentLine(string ll, ref D2Function func)
        {
            if(ll.IndexOf(")") > 0 && ll.IndexOf("(") > 0)
            {
                string[] paramAlias = ll.Split('(')[1].Split(')')[0].Split(',');
                if (paramAlias.Length > func.Parameters.Count())
                    Console.WriteLine("Warning!, out of range of parameters in function => " + func.FunctionName);
                for (int i = 0; i < paramAlias.Length; i++)
                {
                    if (i < func.Parameters.Count())
                        func.Parameters[i].ParamNameAlias = paramAlias[i].Trim();
                }
            }

            func.Comment = ll;
            //throw new NotImplementedException();
        }
 private static void DealWithParameters(string ll, ref D2Function func)
 {
     string name = ll.Trim().Split(' ')[0];
     string type = ll.Trim().Split(' ')[1];
     // func.Parameters.Add(new ParamPair(type,name));
     //func.GetParamterByName(name).ParamType = type;
     //throw new NotImplementedException();
 }
 private static void DealWithReturnLine(string ll, ref D2Function func)
 {
     func.ReturnType = ll.Trim();
     //throw new NotImplementedException();
 }
        private static void DealWithFuncBody(string funcBody, ref D2Function func)
        {
            if (funcBody.IndexOf(":") >= 0)
            {
                func.Class = new D2Class(funcBody.Trim().Substring(0, funcBody.IndexOf(":") - 1));
                funcBody = funcBody.Substring(funcBody.IndexOf(":") + 1);
                // Console.WriteLine(string.Format("{0}:{1}", func.Class, funcBody));
            }

            func.FunctionName = funcBody.Trim().Split('(')[0].Trim();
            string paras = funcBody.Trim().Split('(')[1].Split(')')[0].Trim();
            foreach(string para in paras.Split(','))
            {
                if(String.IsNullOrEmpty(para.Trim())||para.Trim() == "")
                    continue;
                ParamPair param = new ParamPair();
                param.ParamName = para;
                func.Parameters.Add(param);
            }
        }