Beispiel #1
0
 def linesToFile(self, targetFolderPath_: str, lines_: list, chapterCount_: int):
     # 有内容,就形成文件
     if len(lines_) > 0:
         _splitFileContent = "".join(lines_)  # 拼接内容
         _splitFileName = str(chapterCount_).rjust(3) + "_" + lines_[0] + ".txt"  # 第一行做文件名
         fileUtils.writeFileWithStr(targetFolderPath_ + "/" + _splitFileName, _splitFileContent)
Beispiel #2
0
 def removeFirstCharsInEveryLine(self, filePath_: str, charCount_: int):
     _lines = fileUtils.linesFromFile(filePath_)
     for _i in range(len(_lines)):
         _lines[_i] = _lines[_i][charCount_:]
     fileUtils.writeFileWithStr(filePath_, "".join(_lines))
     return
Beispiel #3
0
 def writeJsonToResPath(self):
     self.testJsonStr = '{"result":1245186,"roomCardCount":1000000,"battleId":0,"roomId":0,"marqueeVersion":{"low":1,"high":0,"unsigned":false},"newMail":null,"newLimitedCostlessActivity":false,"noticeVersion":{"low":0,"high":0,"unsigned":false},"activityInfo":[{"id":300001,"startTime":{"low":-576284416,"high":345,"unsigned":false},"endTime":{"low":-72284416,"high":345,"unsigned":false}},{"id":300005,"startTime":{"low":-224153600,"high":349,"unsigned":false},"endTime":{"low":438245400,"high":350,"unsigned":false}},{"id":300008,"startTime":{"low":-2140022784,"high":353,"unsigned":false},"endTime":{"low":-238493672,"high":133356,"unsigned":false}},{"id":300004,"startTime":{"low":-1994684416,"high":345,"unsigned":false},"endTime":{"low":-1908285416,"high":345,"unsigned":false}},{"id":300002,"startTime":{"low":131409920,"high":355,"unsigned":false},"endTime":{"low":217808920,"high":355,"unsigned":false}},{"id":300007,"startTime":{"low":-2140022784,"high":353,"unsigned":false},"endTime":{"low":-584823784,"high":353,"unsigned":false}},{"id":300000,"startTime":{"low":-576284416,"high":345,"unsigned":false},"endTime":{"low":46435072,"high":368,"unsigned":false}}],"buttonValue":13,"timeStamp":{"low":1316055502,"high":355,"unsigned":false},"clubId":null,"createTime":{"low":1037369829,"high":355,"unsigned":false},"connGroup":"c74d97b01eae257e44aa9d5bade97baf","isIdentityVerify":false,"isAgency":false,"agtWebUrl":"","combatId":0,"area":10002,"displayId":5198814,"mttStartTime":{"low":0,"high":0,"unsigned":false},"ticket":0,"phone":"","notifyRedDot":[],"pushRegisterId":""}'
     fileUtils.writeFileWithStr(self.testJsonFilePath, self.testJsonStr)
Beispiel #4
0
    def toDotDict(self, componentRequireDict_: dict,
                  jsProtoRelationDict_: dict, protoList_: list):
        _keyList = []
        _valueAllList = []
        _relationDictList = []
        _relationColorDict = {}
        _colorCurrentIdx = 0
        _colorList = [
            "blue",
            "blue4",
            "brown1",
            "brown4",
            "burlywood1",
            "burlywood4",
            "cadetblue1",
            "cadetblue4",
            "chartreuse1",
            "chartreuse4",
            "chocolate1",
            "chocolate4",
            "cornflowerblue",
            "darkslateblue",
            "dodgerblue4",
            "darkgreen",
            "darkseagreen4",
            "forestgreen",
            "black",
            "purple1",
            "purple3",
            "slateblue1",
            "slateblue3",
            "deepskyblue1",
            "deepskyblue4",
            "crimson",
            "lightsteelblue1",
            "lightsteelblue4",
            "aquamarine1",
            "aquamarine4",
        ]

        # 使用protobuf的js代码,也是Component或者是moudle.export
        for _key in jsProtoRelationDict_.keys():
            _justName = _key.split("/").pop().split(".js")[0]
            if _justName in self.componentNameList:
                if not (_key in _keyList):
                    _keyList.append(_key)
            else:
                if not (_key in _valueAllList):
                    _valueAllList.append(_key)

        for _key in componentRequireDict_.keys():
            _valueList = componentRequireDict_[_key]

            # 保存所有 _key
            _keyList.append(_key)
            for _value in _valueList:
                # 不是.js结尾的
                if not _value.endswith(".js"):
                    continue
                # 保存所有值
                if not (_value in _valueAllList):
                    _valueAllList.append(_value)

                # 建立关系,并根据目标配色
                _relationsDict = dict()
                _relationTo = '"' + _value.split("/").pop() + '"'
                if not (_relationTo in _relationColorDict):
                    # 关联颜色
                    if _colorCurrentIdx == len(_colorList):
                        _colorCurrentIdx = 0
                    _relationColorDict[_relationTo] = _colorList[
                        _colorCurrentIdx]
                    _colorCurrentIdx += 1
                # 确认关系
                _relationsDict["to"] = _relationTo
                _relationsDict["from"] = '"' + _key.split("/").pop() + '"'
                _relationDictList.append(_relationsDict)

        _keyDict = {}
        for _key in _keyList:
            _keyArr = _key.split("/")
            if len(_keyArr) != 2:
                continue
            _folder = _keyArr[0]
            _file = _keyArr[1]
            if not (_folder in _keyDict):
                _keyDict[_folder] = []
            if not (_file in _keyDict[_folder]):
                _keyDict[_folder].append(_file)

        _valueDict = {}
        for _value in _valueAllList:
            _valueArr = _value.split("/")
            if len(_valueArr) != 2:
                continue
            _folder = _valueArr[0]
            _file = _valueArr[1]
            if not (_folder in _valueDict):
                _valueDict[_folder] = []
            if not (_file in _valueDict[_folder]):
                _valueDict[_folder].append(_file)

        _mapName = "relation"
        _dotPicFolder = "/Volumes/18604037792/develop/ShunYuan/"

        # 构成 dot 文件
        _dotStr = "digraph " + _mapName + " {\n"
        _dotStr += '  rankdir = LR;\n'
        _dotStr += '  splines = polyline;\n'
        _dotStr += 'size="50,50"; ratio=fill; node[fontsize=24];\n'

        for _folder, _fileList in _keyDict.items():
            _fileListStr = ""
            for _file in _fileList:
                _fileListStr += '"' + _file + '" [shape = note];'
            _dotStr += 'subgraph "cluster_' + _folder + '" { node [style=filled]; label="' + _folder + '"; ' + _fileListStr + ' };\n'

        for _folder, _fileList in _valueDict.items():
            _fileListStr = ""
            for _file in _fileList:
                _fileListStr += '"' + _file + '";'
            _dotStr += 'subgraph "cluster_' + _folder + '" { label="' + _folder + '"; ' + _fileListStr + ' };\n'

        _reqListStr = ""
        _resListStr = ""
        _synListStr = ""

        for _proto in protoList_:
            if _proto in self.protoReq:
                _reqListStr += _proto + ' [shape=rarrow, color = "blue" , fontcolor = "blue", fontcolor = "white"];'
            elif _proto in self.protoRes:
                _resListStr += _proto + ' [shape=larrow, color = "purple", fontcolor = "purple", fontcolor = "white"];'
            elif _proto in self.protoSyn:
                _synListStr += _proto + ' [shape=invhouse, color = "peru", fontcolor = "peru", fontcolor = "white"];'

        for _i in range(len(self.protoResAndReq)):
            if _i % 2 == 0:
                _protoName = self.protoResAndReq[_i].split("Req")[0]
                _dotStr += 'subgraph "cluster_' + _protoName + '" { label="' + _protoName + '"; node [style=filled]; ' + \
                           self.protoResAndReq[_i] + ' [shape = rarrow, color = "blue" , fontcolor = "white"]; ' + \
                           self.protoResAndReq[
                               _i + 1] + ' [shape = larrow, color = "purple" , fontcolor = "white"];' + ' };\n'

        _dotStr += 'subgraph "cluster_reqProto" { label="Req"; node [style=filled];' + _reqListStr + ' };\n'
        _dotStr += 'subgraph "cluster_resProto" { label="Res"; node [style=filled];' + _resListStr + ' };\n'
        _dotStr += 'subgraph "cluster_otherProto" { label="Other"; node [style=filled]; ' + _synListStr + ' };\n'

        for _i in range(len(_relationDictList)):
            _dot_trans_dict = _relationDictList[_i]
            _dotStr += "  " + _dot_trans_dict["from"] + " -> " + _dot_trans_dict["to"] + " [color = " + \
                       _relationColorDict[_dot_trans_dict["to"]] + "];\n"

        _dotStr += "\n"

        for _jsShortName, _protoInfo in jsProtoRelationDict_.items():
            _send = _protoInfo["send"]
            for _protoName in _send:
                _dotStr += '  "' + _jsShortName.split(
                    "/").pop() + '" -> ' + _protoName + ' [color = blue];\n'

            _onAndOff = _protoInfo["onAndOff"]
            for _protoName in _onAndOff:
                _dotStr += '  "' + _jsShortName.split(
                    "/").pop() + '" -> ' + _protoName + ' [color = green];\n'

            _onNotOff = _protoInfo["onNotOff"]
            for _protoName in _onNotOff:
                _dotStr += '  "' + _jsShortName.split(
                    "/").pop() + '" -> ' + _protoName + ' [color = red];\n'

        _dotStr += "}\n"
        _dotFilePath = _dotPicFolder + _mapName + ".dot"
        fileUtils.writeFileWithStr(_dotFilePath, _dotStr)
        _cmd = 'dot ' + _mapName + '.dot -T png -o ' + _mapName + '.png'
        print(_cmd)
        subprocess.Popen(_cmd, shell=True, cwd=_dotPicFolder)
Beispiel #5
0
    def buildMiniClient_WeChat(self):
        # 工程路径
        _projectFolderPath = sysUtils.folderPathFixEnd(
            "/Volumes/Files/develop/loho/mini-game/miniclient/")
        _assetsFolderPath = sysUtils.folderPathFixEnd(_projectFolderPath +
                                                      "assets")
        _appConfigJsonPath = _projectFolderPath + "assets/resources/configs/AppConfig.json"
        # 打包配置路径
        _miniClientJsonPath = fileUtils.getPath(self.resPath,
                                                "WeChatGameConfig.json")
        # 打包配置内容
        _miniClientJsonDict = fileUtils.dictFromJsonFile(_miniClientJsonPath)
        # 获取构建之后的目录
        _buildFolderPath = sysUtils.folderPathFixEnd(
            _miniClientJsonDict["buildPath"]) + "wechatgame"
        # 获取构建之后的res目录
        _resFolderPath = sysUtils.folderPathFixEnd(_buildFolderPath) + "res/"

        print("请确保所有内容都已经 push 到远程,这样才能创建正确的 TAG")
        # 获取Git链接
        _repo = gitUtils.getRepo(_projectFolderPath)
        # 获取当前满足版本格式的Tag中最大的tag号
        _tagStrList = [
            str(_tagName) for _tagName in _repo.tags
            if strUtils.isVersionStr(str(_tagName))
        ]
        _tagStrList = sorted(_tagStrList,
                             key=functools.cmp_to_key(strUtils.versionCompare),
                             reverse=True)
        # 记录版本号
        _biggestTar = _tagStrList[0]
        print("当前最大 TAG : " + _biggestTar)
        # 增加最后一位的版本号
        _tagIntList = [int(_tarStr) for _tarStr in _biggestTar.split(".")]
        _tagIntList[-1] = _tagIntList[-1] + 1
        _currentTar = ".".join([str(_tarInt) for _tarInt in _tagIntList])
        # 填写到AppConfig.json中
        print("修改本地的AppConfig版本号为 : " + _currentTar)
        print("  *请注意,只是修改本地。从本地提交到微信小程序测试工具中。不通过Git Remote 推送")
        self.changeAppConfigJson(_appConfigJsonPath, _currentTar)
        # 在 Git 上创建 tag
        print("创建新 TAG : " + _currentTar)
        _repo.create_tag(_currentTar)

        # 构建工程
        _cmd = self.getBuildCmd(_projectFolderPath, _miniClientJsonPath)
        print("获取构建命令: \n" + _cmd)

        # 获取构建的LOG 并记录下来。
        _cmdLogFile = "\n".join(os.popen(_cmd).readlines())
        fileUtils.writeFileWithStr(_buildFolderPath + "buildLog.log",
                                   _cmdLogFile)

        # 修改game.json内的超时时间
        self.changeGameJson(_buildFolderPath)

        print("正在获取FTP链接")
        # 获取要上传的ftp的host
        _ftpHost = "ftp网址"
        _ftpUserName = "******"
        _ftpPassWord = "******"
        _ftpSync = ftpUtils.getFTPSync(_ftpHost, _ftpUserName, _ftpPassWord,
                                       "路径/文件夹")
        print("ftp链接获取成功,正在上传请稍后")

        # 指定目录为 res ,那么res中的内容对应同步
        ftpUtils.uploadFolder(_ftpSync, _resFolderPath)
        print("资源上传成功")

        return
Beispiel #6
0
 def mergeNotCodeLineInFile(self, logFilePath_: str,
                            justCodeLogFilePath_: str):
     _lines = fileUtils.linesFromFileWithOutEncode(logFilePath_)
     _lines = self.mergeNotCodeLine(_lines)
     fileUtils.writeFileWithStr(justCodeLogFilePath_,
                                listUtils.joinListToStr(_lines, ""))
Beispiel #7
0
    def analyseSingle(self, filePath_: str, folderName_: str):
        _funcLineCount = 0
        # 做判断的,用来显示的路径
        fileShowName = filePath_.split(folderName_)[1]

        # 实质内容的行数
        currentLine = 0
        # 行数
        lineCount = 0
        # 多行注释堆栈
        multiCommon = False
        # 记录判断修改后的行
        jsLines = []
        # 读每一行
        jsCodes = fileUtils.linesFromFile(filePath_)

        # 逐行循环
        for jsLine in jsCodes:
            # 记录行号
            lineCount = lineCount + 1
            # 临时的行副本
            tempJsLine = jsLine

            # 多行注释/*...
            if multiCommon == False:
                commonMatchBegin = re.search(r'/\*.*', tempJsLine)
                if commonMatchBegin:
                    # /* ... */
                    commonMatchOneLine = re.search(r'/\*.*\*/(.*)', tempJsLine)
                    if commonMatchOneLine:
                        multiCommon = False
                        tempJsLine = commonMatchOneLine.group(1)
                    else:
                        multiCommon = True
                        tempJsLine = ''
            else:
                # ...*/
                commonMatchEnd = re.search(r'.*\*/(.*)', tempJsLine)
                if commonMatchEnd:
                    multiCommon = False
                    tempJsLine = commonMatchEnd.group(1)
            if multiCommon:
                # 处于多行注释,相当于代码是空行
                jsLine = "\n"
                jsLines.append(jsLine)
                continue

            # 单行注释
            commonMatch = re.search(r'(.*)//.*', tempJsLine)

            if commonMatch:
                # 排除网址,最后一个字符为\这样的字符串拼接.字符串拼接里面的//不是代码的注释,是字符串的一部分.
                if tempJsLine.find("http://") < 0 and \
                        tempJsLine.find("https://") < 0 and \
                        tempJsLine.strip()[len(tempJsLine.strip()) - 1] != "\\" and \
                        tempJsLine.find("wss://") < 0 and \
                        tempJsLine.find("ws://") < 0:
                    tempJsLine = commonMatch.group(1)
                    # 分割注释,提取非注释部分
                    jsLine = tempJsLine + "\n"
                    # 去空格及特殊符号
                    tempJsLine = tempJsLine.strip()

            # 去掉空白行
            if tempJsLine.strip() == '':
                jsLines.append("\n")
                continue

                # 不考虑 '...function...' 以及 "...function..." 的情况。。。

            # 有实质内容,行数叠加
            currentLine = currentLine + 1

            # log取得
            logMatch = re.search(r'(.*)cc\.log\(.*\);?(.*)', tempJsLine)
            # 含log
            if logMatch:
                # 去掉原有log
                jsLine = logMatch.group(1) + logMatch.group(2)
            # log取得
            logMatch = re.search(r'(.*)console\.log\(.*\);?(.*)', tempJsLine)
            # 含log
            if logMatch:
                # 去掉原有log
                jsLine = logMatch.group(1) + logMatch.group(2)

            # log取得
            logMatch = re.search(r'(.*)window\.debug\.log\(.*\);?(.*)',
                                 tempJsLine)
            # 含log
            if logMatch:
                # 去掉原有log
                jsLine = logMatch.group(1) + logMatch.group(2)
            else:
                logMatch = re.search(r'(.*)debug\.log\(.*\);?(.*)', tempJsLine)
                # 含log
                if logMatch:
                    # 去掉原有log
                    jsLine = logMatch.group(1) + logMatch.group(2)

            # 用于 new Function 的方式。工程内没有
            # functionBigMatch=re.search(r'(.*)Function(.*)',tempJsLine)
            # if functionBigMatch:
            #     print tempJsLine

            functionMatch = re.search(r'.*function.*\(.*\).*', tempJsLine)
            if functionMatch:
                # 工程里有/function\s*([^(]*)\(/ 这个正则表达式 规避掉这个情况
                if tempJsLine.find('match(/function\s*([^(]*)\(/)') < 0:
                    # 记录Function数量
                    _funcLineCount = _funcLineCount + 1
                    functionName = ''
                    arguments = ''
                    functionOneLine_1 = re.search(
                        r'.*function\s*(.*)\s*\(\s*.*\s*\)\s*\{.*', tempJsLine)
                    if functionOneLine_1:
                        # xx:function(xx){
                        functionOneLine_2 = re.search(
                            r'\s*(.*)\s*:\s*function\s*\(\s*(.*)\s*\)\s*\{.*',
                            tempJsLine)
                        if functionOneLine_2:
                            functionName = functionOneLine_2.group(1)
                            arguments = functionOneLine_2.group(2)
                        else:
                            # * (function(){
                            functionOneLine_3 = re.search(
                                r'.*\(\s*function\s*\(\s*(.*)\s*\)\s*\{.*',
                                tempJsLine)
                            if functionOneLine_3:
                                if tempJsLine.strip() == '(function(){':
                                    # 就是初始化用的
                                    functionName = "__init__"
                                    arguments = functionOneLine_3.group(1)
                                else:
                                    # ty.PublishersManager = (function(){
                                    functionOneLine_4 = re.search(
                                        r'\s*(.*)\s*=\s*\(\s*function\s*\(\s*(.*)\s*\)\s*\{.*',
                                        tempJsLine)
                                    if functionOneLine_4:
                                        functionName = functionOneLine_4.group(
                                            1)
                                        arguments = functionOneLine_4.group(2)
                                    else:
                                        #       this.view.ccbRootNode.setOnExitCallback(function(){
                                        functionOneLine_5 = re.search(
                                            r'\s*(.*)\(\s*function\s*\(\s*(.*)\s*\)\s*\{.*',
                                            tempJsLine)
                                        if functionOneLine_5:
                                            functionName = functionOneLine_5.group(
                                                1)
                                            arguments = functionOneLine_5.group(
                                                2)
                            else:
                                # ty.PublishersManager = function(){
                                functionOneLine_6 = re.search(
                                    r'\s*(.*)\s*=\s*function\s*\(\s*(.*)\s*\)\s*\{.*',
                                    tempJsLine)
                                if functionOneLine_6:
                                    # var sss = function(){
                                    functionOneLine_7 = re.search(
                                        r'\s*var\s*(.*)\s*=\s*function\s*\(\s*(.*)\s*\)\s*\{.*',
                                        tempJsLine)
                                    if functionOneLine_7:
                                        functionName = "var_" + functionOneLine_7.group(
                                            1)
                                        arguments = functionOneLine_7.group(2)
                                    else:
                                        functionName = functionOneLine_6.group(
                                            1)
                                        arguments = functionOneLine_6.group(2)
                    else:
                        functionOneLine_11 = re.search(
                            r'\s*function\s*(.*)\s*\(\s*(.*)\s*\)\s*\{.*',
                            tempJsLine)
                        if functionOneLine_11:
                            functionName = functionOneLine_11.group(1)
                            arguments = functionOneLine_11.group(2)
                    if functionName.strip() == '':
                        # function xx(){ 这样的全局函数。
                        jsLines.append(jsLine)
                        print("{0} _ {1} _ 类似全局函数,或者特殊写法,未添加log".format(
                            fileShowName, jsLine.split('\n'[0])))
                    else:
                        # 去掉没过滤好的空格
                        functionName = functionName.strip()
                        # 拆分模式
                        replace = re.search(r'(.*function.*\(.*\).*\{)(.*)',
                                            jsLine)

                        # 整理参数-让参数 得以在运行时输出成对应值
                        argumentsStr = '{'
                        argumentsList = arguments.split(",")
                        for arg_i in range(len(argumentsList)):
                            argument = argumentsList[arg_i].strip()
                            if argument == '':
                                continue
                            else:
                                argumentsStr += '"' + argument + '":' + argument + ','
                        argumentsStr += '}'

                        # 折射全局对象名-全局函数的文件不输出js路径,而是输出自己的全局类名
                        className = ''
                        if self._fileNameToObjNameBoo:
                            # 存在对应关系就转换
                            if fileShowName in self._fileNameToObjName:
                                className = self._fileNameToObjName[
                                    fileShowName]
                        # 函数名有 ' 的话,把 ' 转意了.
                        if functionName.find("\'") > 0:
                            functionName = "\\\'".join(functionName.split("'"))

                        # 是否需要过滤-运行时,取得这个作为参数,决定是否显示log
                        passBooStr = 'false'
                        if self._justFilterLogsBoo:
                            # 只过滤
                            passBooStr = 'true'
                            if fileShowName in self._filterLogsDict:
                                passBooStr = 'false'
                                print("{0} _ {1} _会输出".format(
                                    fileShowName, functionName))
                        else:
                            # 只显示
                            if passBooStr == 'false':
                                changeBoo = True
                                if fileShowName in self._filterLogsDict:
                                    if functionName in self._filterLogsDict[
                                            fileShowName]:
                                        changeBoo = False
                                if changeBoo == False:
                                    passBooStr = 'true'
                                    print("{0} _ {1} _输出被过滤".format(
                                        fileShowName, functionName))
                            if (fileShowName + ' -> ' +
                                    functionName) in self._specialFuncLogs:
                                functionName = self._specialFuncLogs[
                                    fileShowName + ' -> ' + functionName]
                        newJsLine = replace.group(
                            1
                        ) + '\n' + '_global.log(' + passBooStr + ',\'' + fileShowName.ljust(
                            45
                        ) + '\',\'' + className.rjust(
                            25
                        ) + '\',\'' + functionName + '\',' + argumentsStr + ');\n' + replace.group(
                            2)
                        # 修改后的
                        jsLines.append(newJsLine)
                else:
                    # 使用Function做正则表达式的行
                    jsLines.append(jsLine)
            else:
                # 非function行
                jsLines.append(jsLine)

        if (len(jsLines) != lineCount):
            print('识别行数与给定行数不一致 : {0} {1} - {2}'.format(
                fileShowName, len(jsLines), lineCount))
        else:
            # 如果存在任意一行的话
            if len(jsLines) > 0:
                jsLines[0] = jsLines[0].split('\n')[0] + '\n'
                jsLines.insert(
                    0, addLogFun(self._startLogCount, self._endLogCount))
                jsCodeStr = "".join(jsLines)
                # 写一个新的
                fileUtils.writeFileWithStr(filePath_, jsCodeStr)

        return _funcLineCount
    def toDotDict(self, dotPicFolder_: str):

        _relationFileColorDict = {}
        _relationFolderColorDict = {}
        _colorCurrentIdx = -1

        _colorList = [
            "blue",
            "brown",
            "orange",
            "cadetblue4",
            "chartreuse4",
            "chocolate4",
            "dodgerblue4",
            "red",
            "purple3",
            "green",
            "crimson",
            "lightsteelblue4",
            "aquamarine4",
        ]

        _filterFolderList = ["Message", "WeChat", "Common"]
        _filterFileList = []

        _foldAndFileDict = {}
        for _key in self._jsAllShortNameList:
            _keyArr = _key.split("/")
            if len(_keyArr) != 2:
                continue
            # 文件夹 ,文件
            _folder = _keyArr[0]
            _file = _keyArr[1]
            # 跳过某些文件夹
            if _folder in _filterFolderList:
                if not _file in _filterFileList:
                    _filterFileList.append(_file)
                continue
            else:
                if not (_folder in _foldAndFileDict):
                    _relationFolderColorDict[_folder] = _colorList[
                        _colorCurrentIdx]
                    _foldAndFileDict[_folder] = []
                    _colorCurrentIdx += 1
                    # 同一个文件夹内都是同色
                    if _colorCurrentIdx == len(_colorList):
                        _colorCurrentIdx = 0
                if not (_file in _foldAndFileDict[_folder]):
                    _foldAndFileDict[_folder].append(_file)
                    _relationFileColorDict[_file] = _colorList[_colorCurrentIdx
                                                               - 1]

        _mapName = "jsRelation"
        # 构成 dot 文件
        _dotStr = "digraph " + _mapName + " {\n"
        _dotStr += '  rankdir = LR;\n'
        # _dotStr += '  splines = polyline;\n'
        _dotStr += 'size="50,50"; ratio=fill; node[fontsize=24];\n'

        for _folder, _fileList in _foldAndFileDict.items():
            _fileListStr = ""
            for _baseName in _fileList:
                _fileListStr += '"' + _baseName + '" [shape = note, color = "' + _relationFolderColorDict[
                    _folder] + '", fontcolor = "' + _relationFolderColorDict[
                        _folder] + '", fontcolor = "white"];'
            _dotStr += 'subgraph "cluster_' + _folder + '" { node [style=filled]; label="' + _folder + '"; ' + _fileListStr + ' };\n'

        for _file, _requireList in self._requireDict.items():
            _nameArr = _file.split("/")
            _folder = _nameArr[0]
            if _folder in _filterFolderList:
                continue
            _baseName = _nameArr.pop()
            for _require in _requireList:
                _requireJs = _require + ".js"
                if not _requireJs in _filterFileList:
                    if _requireJs in _relationFileColorDict:
                        _color = _relationFileColorDict[_requireJs]
                        _dotStr += '  "' + _baseName + '" -> "' + _requireJs + '" [color = ' + _color + '];\n'
                    else:
                        _dotStr += '  "' + _baseName + '" -> "' + _requireJs + '";\n'
        _dotStr += "}\n"

        _dotFilePath = dotPicFolder_ + _mapName + ".dot"
        fileUtils.writeFileWithStr(_dotFilePath, _dotStr)
        _cmd = 'dot ' + _mapName + '.dot -T png -o ' + _mapName + '.png'
        print(_cmd)
        subprocess.Popen(_cmd, shell=True, cwd=dotPicFolder_)
    _reportJsonFilePath = "/Users/jiasy/Downloads/project-auditor-report.json"
    _reportAnalyseFilePath = "/Users/jiasy/Downloads/project-auditor-report_analyse"
    _reportDict = fileUtils.dictFromJsonFile(_reportJsonFilePath)
    _m_Issues = _reportDict["m_Issues"]
    _codeIssuesDict = CodeIssuesDict()
    _areaList = []
    for _i in range(len(_m_Issues)):
        _descriptor = _m_Issues[_i]["descriptor"]
        _location = _m_Issues[_i]["location"]
        # 类目不止一个的时候提示一下
        if len(_descriptor["areas"]) > 1:
            print("areas > 1 : " + str(
                json.dumps(
                    _descriptor, indent=4, sort_keys=False,
                    ensure_ascii=False)))
        # 记录出现的 area 类型
        _area = _descriptor["areas"][0]
        if _area not in _areaList:
            _areaList.append(_area)
        # 记录这个描述信息
        _codeIssuesDict.addIssueDescriptor(_descriptor, _location)

    # 分类目打印主要问题
    _printStr = ""
    for _i in range(len(_areaList)):
        _printStr += printIssueByArea(_codeIssuesDict.issuesDict,
                                      _areaList[_i])

    # 写入文件
    fileUtils.writeFileWithStr(_reportAnalyseFilePath, _printStr)