📄 sainity
字号:
#!/bin/ruby# This file is part of the aMule project.## Copyright (c) 2003-2005 aMule Project ( admin@amule.org / http://www.amule.org )## This program is free software; you can redistribute it and/or# modify it under the terms of the GNU General Public License# as published by the Free Software Foundation; either# version 2 of the License, or (at your option) any later version.# # This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.# # You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.## This class represents lines of code, with line-number and text# It is used to store the source-files once they have been read# and afterwards to store the lines returned by the filters.class Line def initialize( number, text ) @number = number @text = text end attr_reader :number attr_reader :textendclass Result def initialize( type, file, line = nil ) @type = type @file = file @line = line end def file_name @file.slice( /[^\/]+$/ ) end def file_path @file.slice( /^.*\// ) end attr_reader :type attr_reader :file attr_reader :lineend# Base class for Sainity Checkers## This class represents the basic sainity-check, which returns all# files as positive results, regardless of the contents.class SainityCheck def initialize @name = "None" @title = nil @type = "None" @desc = "None" @results = Array.new end attr_reader :name attr_reader :type attr_reader :desc def title if @title then @title else @name end end def results @results end # This function will be called for each file, with the argument "file" as the # name of the file and the argument "lines" being an array of Line objects for # each line of the file. # def parse_file(file, lines) raise "Missing parse_file() implementation for Filter: #{@name}" end private def add_results( file, lines = [nil] ) lines.each do |line| @results << Result.new( self, file, line ) end endendclass CompareAgainstEmptyString < SainityCheck def initialize super @name = "CmpEmptyString" @title = "Comparing With Empty String" @type = "Good Practice" @desc = "Comparisons with empty strings, such as wxT(\"\"), wxEmptyString and " @desc += "_(\"\") should be avoided since they force the creation of a temporary " @desc += "string object. The proper method is to use the IsEmpty() member-function " @desc += "of wxString." end def parse_file(file, lines) results = lines.select do |line| line.text =~ /[!=]=\s*(wxEmptyString|wxT\(""\)|_\(""\))/ or line.text =~ /(wxEmptyString|wxT\(""\)|_\(""\))\s*[!=]=/ end add_results( file, results ) endendclass AssignmentToEmptyString < SainityCheck def initialize super @name = "EmptyStringAssignment" @title = "Assignment To Empty String" @type = "Good Practice" @desc = "Assigning an empty string such as wxT(\"\"), wxEmptyString and _(\"\") " @desc += "to a wxString should be avoided, since it forces the creation of a " @desc += "temporary object which is assigned to the string. The proper way to " @desc += "clear a string is to use the Clear() member-function of wxString." end def parse_file(file, lines) if file =~ /\.cpp$/ results = lines.select do |line| line.text =~ /[^=!]=\s*(wxEmptyString|wxT\(""\)|_\(""\))/ end add_results( file, results ) end endendclass NoIfNDef < SainityCheck def initialize super @name = "NoIfNDef" @title = "No #ifndef in headerfile" @type = "Good Practice" @desc = "All header files should contain a #ifndef __<FILENAME>__. The purpuse is to ensure " @desc += "that the header can't be included twice, which would introduce a number of problems." end def parse_file(file, lines) if file =~ /\.h$/ then if not lines.find { |x| x.text =~ /^#ifndef.*_H/ } then add_results( file ) end end endendclass ThisDeference < SainityCheck def initialize super @name = "ThisDeference" @title = "Dereference of \"this\"" @type = "Good Practice" @desc = "In all but the case of templates, using \"this->\" is unnescesarry and " @desc += "only decreases the readability of the code." end def parse_file(file, lines) results = lines.select do |line| line.text =~ /\bthis->/ end add_results( file, results ) endendclass Assert < SainityCheck def initialize super @name = "Assert" @type = "Consistancy" @desc = "wxASSERT()s should be used rather than normal assert()s " @desc += "for the sake of consistancy." end def parse_file(file, lines) results = lines.select do |line| line.text =~ /assert\s*\(/ end add_results( file, results ) endendclass PassByValue < SainityCheck def initialize super @name = "PassByValue" @title = "Pass By Value" @type = "Good Practice" @desc = "Passing objects by value means an extra overhead for large datatypes. " @desc += "Therefore should these always be passed by const reference when possible." @desc += "Non-const references should only be used for functions where the function is " @desc += "supposed to change the actual value of the argument and return another or no value." end def parse_file(file, lines) results = Array.new # Only handle header files if file =~ /\.h$/ # Items that should be passed by const-ref items = [ "wxString", "wxRect", "wxPoint", "CMD4Hash" ] lines.each do |line| # Try to identify function definitions if line.text =~ /^\s*(virtual|static|inline|)\s*\w+\s+\w+\s*\(.*\)/ # Split by arguments line.text.match(/\(.*\)/)[0].split(",").each do |str| items.each do |item| if str =~ /#{item}\s*[^\s\*]/ and not str =~ /const/ results.push( line ) end end end end end end add_results( file, results ) endendclass CStr < SainityCheck def initialize super @name = "CStr" @title = "C_Str or GetData" @type = "Unicoding" @desc = "Checks for usage of c_str() or GetData(). Using c_str will often result in " @desc += "problems on Unicoded builds and should therefore be avoided. " @desc += "Please note that the GetData check isn't that precise, because many other " @desc += "classes have GetData members, so it does some crude filtering." end def parse_file(file, lines) results = lines.select do |line| if line.text =~ /c_str\(\)/ true else line.text =~ /GetData\(\)/ and line.text =~ /(wxT\(|wxString|_\()/ end end add_results( file, results ) endendclass IfNotDefined < SainityCheck def initialize super @name = "IfDefined" @title = "#if (!)defined" @type = "Consistancy" @desc = "Use #ifndef or #ifdef instead for reasons of simplicity." end def parse_file(file, lines) results = lines.select do |line| if line.text =~ /^#if.*[\!]?defined\(/ not line.text =~ /(\&\&|\|\|)/ end end add_results( file, results ) endendclass GPLLicense < SainityCheck def initialize super @name = "MissingGPL" @title = "Missing GPL License" @type = "License" @desc = "All header files should contain the proper GPL blorb." end def parse_file(file, lines) if file =~ /\.h$/ if lines.find { |x| x.text =~ /This program is free software;/ } == nil add_results( file ) end end endendclass Copyright < SainityCheck def initialize super @name = "MissingCopyright" @title = "Missing Copyright Notice" @type = "License" @desc = "All files should contain the proper Copyright notice." end def parse_file(file, lines) if file =~ /\.h$/ found = lines.select do |line| line.text =~ /Copyright\s*\([cC]\)\s*[-\d,]+ aMule (Project|Team)/ end if found.empty? then add_results( file ) end end endendclass PartOfAmule < SainityCheck def initialize super @name = "aMuleNotice" @title = "Missing aMule notice" @type = "License" @desc = "All files should contain a notice that they are part of the aMule project." end def parse_file(file, lines) if file =~ /\.h$/ found = lines.select do |line| line.text =~ /This file is part of the aMule Project/ end if found.empty? then add_results( file ) end end endendclass MissingBody < SainityCheck def initialize super @name = "MissingBody" @title = "Missing Body in Loop" @type = "Garbage" @desc = "This checks looks for loops without any body. For example \"while(true);\" " @desc += "In most cases this is a sign of either useless code or bugs. Only in a few " @desc += "cases is it valid code, and in those it can often be represented clearer " @desc += "in other ways." end def parse_file(file, lines) results = lines.select do |line| if line.text =~ /^[^}]*while\s*\(.*\)\s*;/ or line.text =~ /^\s*for\s*\(.*\)\s*;[^\)]*$/ # Avoid returning "for" spanning multiple lines # TODO A better way to count instances line.text.split("(").size == line.text.split(")").size else false end end add_results( file, results ) endendclass Translation < SainityCheck def initialize super @name = "Translation" @type = "Consistancy" @desc = "Calls to AddLogLineM should translate the message, whereas " @desc += "calls to AddDebugLogLine shouldn't. This is because the user " @desc += "is meant to see normal log lines, whereas the the debug-lines " @desc += "are only meant for the developers and I dont know about you, but " @desc += "I dont plan on learning every language we choose to translate " @desc += "aMule to. :P" end def parse_file(file, lines) results = lines.select do |line| if line.text =~ /\"/ line.text =~ /AddLogLine(M|)\(.*wxT\(/ or line.text =~ /AddDebugLogLine(M|)\(.*_\(/ else false end end add_results( file, results ) endendclass IfZero < SainityCheck def initialize super @name = "PreIfConstant" @title = "#if 0-9" @type = "Garbage" @desc = "Disabled code should be removed as soon as possible. If you wish to disable code " @desc += "for only a short period, then please add a comment before the #if. Code with #if [1-9] " @desc += "should be left, but the #ifs removed unless there is a pressing need for them." end def parse_file(file, lines) results = lines.select do |line| line.text =~ /#if\s+[0-9]/ end add_results( file, results ) endendclass InlinedIfTrue < SainityCheck def initialize super @name = "InlinedIf" @name = "Inlined If true/false" @type = "Garbage"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -