0

我有很多代码,其中有时编写了 if 语句,但没有匹配的 else 语句。在某些地方,这是一个问题,因为当某些事情发生故障时,故障没有得到正确处理。我想手动确认所有出现 if-without-an-else 的地方。

我试过使用正则表达式,但我没有成功找到匹配右括号的方法,因为正则表达式不能真正处理嵌套括号

我要查找的代码如下所示:

if( ... ) {

...

}

我不想找到的代码如下所示:

if( ... ) {

...

} 
else {

... 

}

我怎样才能列出所有这些地方,以便我可以浏览它们?

4

1 回答 1

1

正如您自己注意到的那样,通常这必须使用某种解析器来完成。使用正则表达式只是很痛苦,并且那里有很多解析器/语法模块。

我创建了一个一次性解决方案脚本(在 nodejs 中),它使用正则表达式和缩进数来匹配开始到结束if / else语句。如果满足以下条件,它将起作用:

  • 文件格式正确,开头if的缩进数与结尾的缩进数相同else

这有效:

if(a) {
   if(b) {
      
   } else { // i have same amount of indents as my matching if, works!
     
   }
}

这不起作用:

if(a) {
    if(b) {
        } else { // i have to many indents.
           
        }
  
}

  • 不能有ifelse在同一条线上!(通常不应该..)

这是我想出的脚本,它存储所有行号,if其中没有else. 您可以检查行号并单击给定的if,然后 vs 代码突出显示结束括号,您可以添加else. 它使用 lodash 但最终仅用于展平结果。这不是真正的依赖..

import { EOL } from 'os'
import * as fs from 'fs'
import { flatten } from 'lodash'

// Import your code file:
const code = fs.readFileSync('code.js').toString()

// Regex for matching lines holding if's..
// if(...)
// if() {
// if
const match_if = /if\s?\([^)]+\)\s+?/

// Regex for matching lines holding else:
// }else
// } else
// else {
// }else{
// ...
const match_else = /(\n|})\s?else({|\s|$)/


// small helper fpr calculating indents for first character appearing..
const calculate_indent = (line: string) => {
    let spaces = 0
    while(line.charAt(spaces) === ' ') {
        spaces++
    }
    return spaces
}

// split up the lines by system operator
const lines = code.split(EOL)
const indexes = []

// iterate all lines.
for(let i =0; i < lines.length; i++) {
    const line = lines[i]

    // do not process empty lines..
    if(!line || line.trim().length < 2) {
        continue
    }


    // Match the line against if regex
    const if_match = line.match(match_if)

    // process the match if there is an if found!
    if(if_match && if_match.length > 0) {

        // Count the indents, we need this latere
        // to match any found "else" to the correct if.
        // make sure your code is properly formatted and indent levels are correct!!
        const level = calculate_indent(line)


        // Make sure under given level is an array
        if(Array.isArray(indexes[level]) === false) {
            indexes[level] = []
        }

        // store line number to the given level. 
        // For a human the line number is index + 1
        indexes[level].push(i+1)
    }


    // We check the line for else. Note:
    // The whole function won't work for any if() else combinations on the same line..
    const else_match = line.match(match_else)
    if(else_match && else_match.length > 0) {
        
    
        // count index to identify level for matching the correct if.
        const level = calculate_indent(line)

        if(Array.isArray(indexes[level])) {
            // remove the last stored if. We know it ended here!
            indexes[level].splice(indexes[level].length-1, 1)
        } 

    }

}

console.log('lines:', lines.length)
console.log('results:', indexes)

// flatten / remove empty items / sort
const line_numbers = flatten(indexes).filter(d => !!d).sort((a,b) => a-b)

console.log('final lines:', line_numbers)

我用这段代码测试了它:

if(sdf) {

    if(sdf) {
            
    }
}



if(asdf) {

    if(sdfsdf) {


        if(sdfsdf) {

        } else {

        }
    } else {

    }
} else {
    
}


if(asdf) {

    if(sdfsdf) {

    } else {
        if(sdf) {

        }

        if(sdf) {
            
        } else {

        }


        if(sdf) {

        }
    }
}

结果 =>final lines: [ 2, 4, 29, 34, 45 ] 您可能想在使用前多测试一下!但是当缩进正确时它应该可以工作。这篇文章也是相关的,很好读!=>为什么你不应该使用正则表达式来解析树结构......

于 2021-07-08T11:44:17.337 回答