|
From: <xf...@us...> - 2011-11-24 02:51:44
|
Revision: 2428
http://edk2-buildtools.svn.sourceforge.net/edk2-buildtools/?rev=2428&view=rev
Author: xfzyr
Date: 2011-11-24 02:51:37 +0000 (Thu, 24 Nov 2011)
Log Message:
-----------
Since Coding style spec has added chapter 7.3.2 for copyright notice format. So add check for copyright notice according to coding style spec chapter 7.3.2(Revision 1.0, March, 2010).
Signed-off-by: yzeng15
Reviewed-by: hchen30
Revision Links:
--------------
http://edk2-buildtools.svn.sourceforge.net/edk2-buildtools/?rev=1&view=rev
Modified Paths:
--------------
trunk/BaseTools/Source/Python/Ecc/Check.py
trunk/BaseTools/Source/Python/Ecc/MetaDataParser.py
trunk/BaseTools/Source/Python/Ecc/c.py
Modified: trunk/BaseTools/Source/Python/Ecc/Check.py
===================================================================
--- trunk/BaseTools/Source/Python/Ecc/Check.py 2011-11-23 09:38:15 UTC (rev 2427)
+++ trunk/BaseTools/Source/Python/Ecc/Check.py 2011-11-24 02:51:37 UTC (rev 2428)
@@ -15,6 +15,7 @@
from CommonDataClass.DataClass import *
from Common.DataType import SUP_MODULE_LIST_STRING, TAB_VALUE_SPLIT
from EccToolError import *
+from MetaDataParser import ParseHeaderCommentSection
import EccGlobalData
import c
@@ -415,13 +416,79 @@
elif Ext in ('.inf', '.dec', '.dsc', '.fdf'):
FullName = os.path.join(Dirpath, F)
op = open(FullName).readlines()
- if not op[0].startswith('## @file') and op[6].startswith('## @file') and op[7].startswith('## @file'):
+ FileLinesList = op
+ LineNo = 0
+ CurrentSection = MODEL_UNKNOWN
+ HeaderSectionLines = []
+ HeaderCommentStart = False
+ HeaderCommentEnd = False
+
+ for Line in FileLinesList:
+ LineNo = LineNo + 1
+ Line = Line.strip()
+ if (LineNo < len(FileLinesList) - 1):
+ NextLine = FileLinesList[LineNo].strip()
+
+ #
+ # blank line
+ #
+ if (Line == '' or not Line) and LineNo == len(FileLinesList):
+ LastSectionFalg = True
+
+ #
+ # check whether file header comment section started
+ #
+ if Line.startswith('##') and \
+ (Line.find('@file') > -1) and \
+ not HeaderCommentStart:
+ if CurrentSection != MODEL_UNKNOWN:
+ SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName
+ ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
+ for Result in ResultSet:
+ Msg = 'INF/DEC/DSC/FDF file header comment should begin with ""## @file"" at the very top file'
+ EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
+
+ else:
+ CurrentSection = MODEL_IDENTIFIER_FILE_HEADER
+ #
+ # Append the first line to section lines.
+ #
+ HeaderSectionLines.append((Line, LineNo))
+ HeaderCommentStart = True
+ continue
+
+ #
+ # Collect Header content.
+ #
+ if (Line.startswith('#') and CurrentSection == MODEL_IDENTIFIER_FILE_HEADER) and\
+ HeaderCommentStart and not Line.startswith('##') and not\
+ HeaderCommentEnd and NextLine != '':
+ HeaderSectionLines.append((Line, LineNo))
+ continue
+ #
+ # Header content end
+ #
+ if (Line.startswith('##') or not Line.strip().startswith("#")) and HeaderCommentStart \
+ and not HeaderCommentEnd:
+ if Line.startswith('##'):
+ HeaderCommentEnd = True
+ HeaderSectionLines.append((Line, LineNo))
+ ParseHeaderCommentSection(HeaderSectionLines, FullName)
+ break
+ if HeaderCommentStart == False:
SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName
ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
for Result in ResultSet:
- Msg = 'INF/DEC/DSC/FDF file header comment should begin with ""## @file""'
+ Msg = 'INF/DEC/DSC/FDF file header comment should begin with ""## @file"" at the very top file'
EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
+ if HeaderCommentEnd == False:
+ SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName
+ ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
+ for Result in ResultSet:
+ Msg = 'INF/DEC/DSC/FDF file header comment should end with ""##"" at the end of file header comment block'
+ EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
+
# Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5
def DoxygenCheckFunctionHeader(self):
Modified: trunk/BaseTools/Source/Python/Ecc/MetaDataParser.py
===================================================================
--- trunk/BaseTools/Source/Python/Ecc/MetaDataParser.py 2011-11-23 09:38:15 UTC (rev 2427)
+++ trunk/BaseTools/Source/Python/Ecc/MetaDataParser.py 2011-11-24 02:51:37 UTC (rev 2428)
@@ -13,8 +13,9 @@
import os
from CommonDataClass.DataClass import *
-
-
+from EccToolError import *
+import EccGlobalData
+import re
## Get the inlcude path list for a source file
#
# 1. Find the source file belongs to which inf file
@@ -76,3 +77,188 @@
return TableList
+## ParseHeaderCommentSection
+#
+# Parse Header comment section lines, extract Abstract, Description, Copyright
+# , License lines
+#
+# @param CommentList: List of (Comment, LineNumber)
+# @param FileName: FileName of the comment
+#
+def ParseHeaderCommentSection(CommentList, FileName = None):
+
+ Abstract = ''
+ Description = ''
+ Copyright = ''
+ License = ''
+ EndOfLine = "\n"
+ STR_HEADER_COMMENT_START = "@file"
+
+ #
+ # used to indicate the state of processing header comment section of dec,
+ # inf files
+ #
+ HEADER_COMMENT_NOT_STARTED = -1
+ HEADER_COMMENT_STARTED = 0
+ HEADER_COMMENT_FILE = 1
+ HEADER_COMMENT_ABSTRACT = 2
+ HEADER_COMMENT_DESCRIPTION = 3
+ HEADER_COMMENT_COPYRIGHT = 4
+ HEADER_COMMENT_LICENSE = 5
+ HEADER_COMMENT_END = 6
+ #
+ # first find the last copyright line
+ #
+ Last = 0
+ HeaderCommentStage = HEADER_COMMENT_NOT_STARTED
+ for Index in xrange(len(CommentList)-1, 0, -1):
+ Line = CommentList[Index][0]
+ if _IsCopyrightLine(Line):
+ Last = Index
+ break
+
+ for Item in CommentList:
+ Line = Item[0]
+ LineNo = Item[1]
+
+ if not Line.startswith('#') and Line:
+ SqlStatement = """ select ID from File where FullPath like '%s'""" % FileName
+ ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
+ for Result in ResultSet:
+ Msg = 'Comment must start with #'
+ EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
+ Comment = CleanString2(Line)[1]
+ Comment = Comment.strip()
+ #
+ # if there are blank lines between License or Description, keep them as they would be
+ # indication of different block; or in the position that Abstract should be, also keep it
+ # as it indicates that no abstract
+ #
+ if not Comment and HeaderCommentStage not in [HEADER_COMMENT_LICENSE, \
+ HEADER_COMMENT_DESCRIPTION, HEADER_COMMENT_ABSTRACT]:
+ continue
+
+ if HeaderCommentStage == HEADER_COMMENT_NOT_STARTED:
+ if Comment.startswith(STR_HEADER_COMMENT_START):
+ HeaderCommentStage = HEADER_COMMENT_ABSTRACT
+ else:
+ License += Comment + EndOfLine
+ else:
+ if HeaderCommentStage == HEADER_COMMENT_ABSTRACT:
+ #
+ # in case there is no abstract and description
+ #
+ if not Comment:
+ Abstract = ''
+ HeaderCommentStage = HEADER_COMMENT_DESCRIPTION
+ elif _IsCopyrightLine(Comment):
+ Copyright += Comment + EndOfLine
+ HeaderCommentStage = HEADER_COMMENT_COPYRIGHT
+ else:
+ Abstract += Comment + EndOfLine
+ HeaderCommentStage = HEADER_COMMENT_DESCRIPTION
+ elif HeaderCommentStage == HEADER_COMMENT_DESCRIPTION:
+ #
+ # in case there is no description
+ #
+ if _IsCopyrightLine(Comment):
+ Copyright += Comment + EndOfLine
+ HeaderCommentStage = HEADER_COMMENT_COPYRIGHT
+ else:
+ Description += Comment + EndOfLine
+ elif HeaderCommentStage == HEADER_COMMENT_COPYRIGHT:
+ if _IsCopyrightLine(Comment):
+ Copyright += Comment + EndOfLine
+ else:
+ #
+ # Contents after copyright line are license, those non-copyright lines in between
+ # copyright line will be discarded
+ #
+ if LineNo > Last:
+ if License:
+ License += EndOfLine
+ License += Comment + EndOfLine
+ HeaderCommentStage = HEADER_COMMENT_LICENSE
+ else:
+ if not Comment and not License:
+ continue
+ License += Comment + EndOfLine
+
+ if not Copyright:
+ SqlStatement = """ select ID from File where FullPath like '%s'""" % FileName
+ ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
+ for Result in ResultSet:
+ Msg = 'Header comment section must have copyright information'
+ EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
+
+ if not License:
+ SqlStatement = """ select ID from File where FullPath like '%s'""" % FileName
+ ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
+ for Result in ResultSet:
+ Msg = 'Header comment section must have license information'
+ EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
+
+ return Abstract.strip(), Description.strip(), Copyright.strip(), License.strip()
+
+## _IsCopyrightLine
+# check whether current line is copyright line, the criteria is whether there is case insensitive keyword "Copyright"
+# followed by zero or more white space characters followed by a "(" character
+#
+# @param LineContent: the line need to be checked
+# @return: True if current line is copyright line, False else
+#
+def _IsCopyrightLine (LineContent):
+ LineContent = LineContent.upper()
+ Result = False
+
+ ReIsCopyrightRe = re.compile(r"""(^|\s)COPYRIGHT *\(""", re.DOTALL)
+ if ReIsCopyrightRe.search(LineContent):
+ Result = True
+
+ return Result
+
+
+## CleanString2
+#
+# Split comments in a string
+# Remove spaces
+#
+# @param Line: The string to be cleaned
+# @param CommentCharacter: Comment char, used to ignore comment content,
+# default is DataType.TAB_COMMENT_SPLIT
+#
+def CleanString2(Line, CommentCharacter='#', AllowCppStyleComment=False):
+ #
+ # remove whitespace
+ #
+ Line = Line.strip()
+ #
+ # Replace EDK1's comment character
+ #
+ if AllowCppStyleComment:
+ Line = Line.replace('//', CommentCharacter)
+ #
+ # separate comments and statements
+ #
+ LineParts = Line.split(CommentCharacter, 1)
+ #
+ # remove whitespace again
+ #
+ Line = LineParts[0].strip()
+ if len(LineParts) > 1:
+ Comment = LineParts[1].strip()
+ #
+ # Remove prefixed and trailing comment characters
+ #
+ Start = 0
+ End = len(Comment)
+ while Start < End and Comment.startswith(CommentCharacter, Start, End):
+ Start += 1
+ while End >= 0 and Comment.endswith(CommentCharacter, Start, End):
+ End -= 1
+ Comment = Comment[Start:End]
+ Comment = Comment.strip()
+ else:
+ Comment = ''
+
+ return Line, Comment
Modified: trunk/BaseTools/Source/Python/Ecc/c.py
===================================================================
--- trunk/BaseTools/Source/Python/Ecc/c.py 2011-11-23 09:38:15 UTC (rev 2427)
+++ trunk/BaseTools/Source/Python/Ecc/c.py 2011-11-24 02:51:37 UTC (rev 2428)
@@ -2301,32 +2301,75 @@
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, ID
from %s
- where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
+ where Model = %d and StartLine = 1 and StartColumn = 0
""" % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
- PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No Comment appear at the very beginning of file.', 'File', FileID)
+ PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No File License header appear at the very beginning of file.', 'File', FileID)
return ErrorMsgList
- IsFoundError1 = True
- IsFoundError2 = True
- IsFoundError3 = True
+ NoHeaderCommentStartFlag = True
+ NoHeaderCommentEndFlag = True
+ NoHeaderCommentPeriodFlag = True
+ NoCopyrightFlag = True
+ NoLicenseFlag = True
+ NoRevReferFlag = True
+ NextLineIndex = 0
for Result in ResultSet:
CommentStr = Result[0].strip()
+ CommentStrList = CommentStr.split('\r\n')
ID = Result[1]
+ Index = 0
if CommentStr.startswith('/** @file'):
- IsFoundError1 = False
+ NoHeaderCommentStartFlag = False
+ else:
+ continue
if CommentStr.endswith('**/'):
- IsFoundError2 = False
- if CommentStr.find('.') != -1:
- IsFoundError3 = False
+ NoHeaderCommentEndFlag = False
+ else:
+ continue
- if IsFoundError1:
+ for CommentLine in CommentStrList:
+ Index = Index + 1
+ NextLineIndex = Index
+ if CommentLine.startswith('/** @file'):
+ continue
+ if CommentLine.startswith('**/'):
+ break
+ if CommentLine.startswith('/** @file') == False and CommentLine.startswith('**/') == False and CommentLine.strip() and CommentLine.startswith(' ') == False:
+ PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment content should start with two spaces at each line', FileTable, ID)
+
+ CommentLine = CommentLine.strip()
+ if CommentLine.startswith('Copyright'):
+ NoCopyrightFlag = False
+ if CommentLine.find('All rights reserved') == -1:
+ PrintErrorMsg(ERROR_HEADER_CHECK_FILE, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable, ID)
+ if CommentLine.endswith('<BR>') == -1:
+ PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'The ""<BR>"" at the end of the Copyright line is required', FileTable, ID)
+ if NextLineIndex < len(CommentStrList) and CommentStrList[NextLineIndex].strip().startswith('Copyright') == False and CommentStrList[NextLineIndex].strip():
+ NoLicenseFlag = False
+ if CommentLine.startswith('@par Revision Reference:'):
+ NoRevReferFlag = False
+ RefListFlag = False
+ for RefLine in CommentStrList[NextLineIndex:]:
+ if RefLine.strip() and (NextLineIndex + 1) < len(CommentStrList) and CommentStrList[NextLineIndex+1].strip() and CommentStrList[NextLineIndex+1].strip().startswith('**/') == False:
+ RefListFlag = True
+ if RefLine.strip() == False or RefLine.strip().startswith('**/'):
+ RefListFlag = False
+ break
+ if RefListFlag == True:
+ if RefLine.strip() and RefLine.strip().startswith('**/') == False and RefLine.startswith(' -') == False:
+ PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable, ID)
+ if NoHeaderCommentStartFlag:
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, ID)
- if IsFoundError2:
+ return
+ if NoHeaderCommentEndFlag:
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with ""**/""', FileTable, ID)
- if IsFoundError3:
- PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period "".""', FileTable, ID)
+ return
+ if NoCopyrightFlag:
+ PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment missing the ""Copyright""', FileTable, ID)
+ if NoLicenseFlag:
+ PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable, ID)
def CheckFuncHeaderDoxygenComments(FullFileName):
ErrorMsgList = []
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|