Plugins/CheckerPlugins/CodeStyleChecker/DocStyleChecker.py

changeset 5732
34041e56ec42
parent 5588
6ba512d9f46a
child 5812
ffc31e1cff4e
equal deleted inserted replaced
5729:e67c1c4f4abb 5732:34041e56ec42
120 120
121 "D203", "D205", 121 "D203", "D205",
122 "D221", "D222", 122 "D221", "D222",
123 "D231", "D232", "D234", "D235", "D236", "D237", "D238", "D239", 123 "D231", "D232", "D234", "D235", "D236", "D237", "D238", "D239",
124 "D242", "D243", "D244", "D245", "D246", "D247", 124 "D242", "D243", "D244", "D245", "D246", "D247",
125 "D250", "D251", 125 "D250", "D251", "D252", "D253",
126 "D260", "D261", "D262", "D263",
126 127
127 "D901", 128 "D901",
128 ] 129 ]
129 130
130 def __init__(self, source, filename, select, ignore, expected, repeat, 131 def __init__(self, source, filename, select, ignore, expected, repeat,
213 ], 214 ],
214 "classDocstring": [ 215 "classDocstring": [
215 (self.__checkClassDocstring, ("D104", "D205")), 216 (self.__checkClassDocstring, ("D104", "D205")),
216 (self.__checkEricNoBlankBeforeAndAfterClassOrFunction, 217 (self.__checkEricNoBlankBeforeAndAfterClassOrFunction,
217 ("D242", "D243")), 218 ("D242", "D243")),
219 (self.__checkEricSignal, ("D260", "D261", "D262", "D263")),
218 ], 220 ],
219 "methodDocstring": [ 221 "methodDocstring": [
220 (self.__checkEricSummary, ("D232")), 222 (self.__checkEricSummary, ("D232")),
221 ], 223 ],
222 "defDocstring": [ 224 "defDocstring": [
226 (self.__checkEricReturn, ("D234", "D235")), 228 (self.__checkEricReturn, ("D234", "D235")),
227 (self.__checkEricFunctionArguments, 229 (self.__checkEricFunctionArguments,
228 ("D236", "D237", "D238", "D239")), 230 ("D236", "D237", "D238", "D239")),
229 (self.__checkEricNoBlankBeforeAndAfterClassOrFunction, 231 (self.__checkEricNoBlankBeforeAndAfterClassOrFunction,
230 ("D244", "D245")), 232 ("D244", "D245")),
231 (self.__checkEricException, ("D250", "D251")), 233 (self.__checkEricException,
234 ("D250", "D251", "D252", "D253")),
232 ], 235 ],
233 "docstring": [ 236 "docstring": [
234 (self.__checkTripleDoubleQuotes, ("D111",)), 237 (self.__checkTripleDoubleQuotes, ("D111",)),
235 (self.__checkBackslashes, ("D112",)), 238 (self.__checkBackslashes, ("D112",)),
236 (self.__checkUnicode, ("D113",)), 239 (self.__checkUnicode, ("D113",)),
1125 def __checkEricException(self, docstringContext, context): 1128 def __checkEricException(self, docstringContext, context):
1126 """ 1129 """
1127 Private method to check, that docstrings contain an @exception line 1130 Private method to check, that docstrings contain an @exception line
1128 if they raise an exception and don't otherwise. 1131 if they raise an exception and don't otherwise.
1129 1132
1133 Note: This method also checks the raised and documented exceptions for
1134 completeness (i.e. raised exceptions that are not documented or
1135 documented exceptions that are not raised)
1136
1130 @param docstringContext docstring context (DocStyleContext) 1137 @param docstringContext docstring context (DocStyleContext)
1131 @param context context of the docstring (DocStyleContext) 1138 @param context context of the docstring (DocStyleContext)
1132 """ 1139 """
1133 if docstringContext is None: 1140 if docstringContext is None:
1134 return 1141 return
1135 1142
1136 tokens = list( 1143 tokens = list(
1137 tokenize.generate_tokens(StringIO(context.ssource()).readline)) 1144 tokenize.generate_tokens(StringIO(context.ssource()).readline))
1138 exception = [tokens[i + 1][0] for i, token in enumerate(tokens) 1145 exceptions = set()
1139 if token[1] == "raise"] 1146 raisedExceptions = set()
1147 tokensLen = len(tokens)
1148 for i, token in enumerate(tokens):
1149 if token[1] == "raise":
1150 exceptions.add(tokens[i + 1][0])
1151 if tokens[i + 1][0] == tokenize.NAME:
1152 if tokensLen > (i + 2) and \
1153 tokens[i + 2][1] == ".":
1154 raisedExceptions.add("{0}.{1}".format(
1155 tokens[i + 1][1], tokens[i + 3][1]))
1156 else:
1157 raisedExceptions.add(tokens[i + 1][1])
1158
1140 if "@exception" not in docstringContext.ssource() and \ 1159 if "@exception" not in docstringContext.ssource() and \
1141 "@throws" not in docstringContext.ssource() and \ 1160 "@throws" not in docstringContext.ssource() and \
1142 "@raise" not in docstringContext.ssource(): 1161 "@raise" not in docstringContext.ssource():
1143 if (set(exception) - 1162 if (exceptions -
1144 {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE} != 1163 {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE} !=
1145 set()): 1164 set()):
1146 self.__error(docstringContext.end(), 0, "D250") 1165 self.__error(docstringContext.end(), 0, "D250")
1147 else: 1166 else:
1148 if (set(exception) - 1167 if (exceptions -
1149 {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE} == 1168 {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE} ==
1150 set()): 1169 set()):
1151 self.__error(docstringContext.end(), 0, "D251") 1170 self.__error(docstringContext.end(), 0, "D251")
1171 else:
1172 # step 1: extract documented exceptions
1173 documentedExceptions = set()
1174 for line in docstringContext.source():
1175 line = line.strip()
1176 if line.startswith(("@exception", "@throws", "@raise")):
1177 exceptionTokens = line.split(None, 2)
1178 if len(exceptionTokens) >= 2:
1179 documentedExceptions.add(exceptionTokens[1])
1180
1181 # step 2: report undocumented exceptions
1182 for exception in raisedExceptions:
1183 if exception not in documentedExceptions:
1184 self.__error(docstringContext.end(), 0, "D252",
1185 exception)
1186
1187 # step 3: report undefined signals
1188 for exception in documentedExceptions:
1189 if exception not in raisedExceptions:
1190 self.__error(docstringContext.end(), 0, "D253",
1191 exception)
1192
1193 def __checkEricSignal(self, docstringContext, context):
1194 """
1195 Private method to check, that docstrings contain an @signal line
1196 if they define signals and don't otherwise.
1197
1198 Note: This method also checks the defined and documented signals for
1199 completeness (i.e. defined signals that are not documented or
1200 documented signals that are not defined)
1201
1202 @param docstringContext docstring context (DocStyleContext)
1203 @param context context of the docstring (DocStyleContext)
1204 """
1205 if docstringContext is None:
1206 return
1207
1208 tokens = list(
1209 tokenize.generate_tokens(StringIO(context.ssource()).readline))
1210 definedSignals = set()
1211 for i, token in enumerate(tokens):
1212 if token[1] in ("pyqtSignal", "Signal"):
1213 if tokens[i - 1][1] == "." and tokens[i - 2][1] == "QtCore":
1214 definedSignals.add(tokens[i - 4][1])
1215 elif tokens[i - 1][1] == "=":
1216 definedSignals.add(tokens[i - 2][1])
1217
1218 if "@signal" not in docstringContext.ssource() and definedSignals:
1219 self.__error(docstringContext.end(), 0, "D260")
1220 elif "@signal" in docstringContext.ssource():
1221 if not definedSignals:
1222 self.__error(docstringContext.end(), 0, "D261")
1223 else:
1224 # step 1: extract documented signals
1225 documentedSignals = set()
1226 for line in docstringContext.source():
1227 line = line.strip()
1228 if line.startswith("@signal"):
1229 signalTokens = line.split(None, 2)
1230 if len(signalTokens) >= 2:
1231 signal = signalTokens[1]
1232 if "(" in signal:
1233 signal = signal.split("(", 1)[0]
1234 documentedSignals.add(signal)
1235
1236 # step 2: report undocumented signals
1237 for signal in definedSignals:
1238 if signal not in documentedSignals:
1239 self.__error(docstringContext.end(), 0, "D262", signal)
1240
1241 # step 3: report undefined signals
1242 for signal in documentedSignals:
1243 if signal not in definedSignals:
1244 self.__error(docstringContext.end(), 0, "D263", signal)
1152 1245
1153 def __checkEricBlankAfterSummary(self, docstringContext, context): 1246 def __checkEricBlankAfterSummary(self, docstringContext, context):
1154 """ 1247 """
1155 Private method to check, that docstring summaries are followed 1248 Private method to check, that docstring summaries are followed
1156 by a blank line. 1249 by a blank line.

eric ide

mercurial