Use Abstract Base Classes to ensure Problem is not instantiated
- Problem() is a parent abstract class that should only be used for subclassing. - With the help of ABC, implement abstract methods that force subclasses to implement quiet and verbose outputs. - The repeated logic of "if self.quiet" is consolidated in Problem. Signed-off-by: Yuto Takano <yuto.takano@arm.com>
This commit is contained in:
parent
5f83171999
commit
fc1e9ffcb2
1 changed files with 43 additions and 17 deletions
|
@ -42,6 +42,7 @@ The script returns 0 on success, 1 on test failure, and 2 if there is a script
|
||||||
error. It must be run from Mbed TLS root.
|
error. It must be run from Mbed TLS root.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import abc
|
||||||
import argparse
|
import argparse
|
||||||
import glob
|
import glob
|
||||||
import textwrap
|
import textwrap
|
||||||
|
@ -92,9 +93,11 @@ class Match(): # pylint: disable=too-few-public-methods
|
||||||
" {0} | {1}\n".format(" " * len(gutter), underline)
|
" {0} | {1}\n".format(" " * len(gutter), underline)
|
||||||
)
|
)
|
||||||
|
|
||||||
class Problem(): # pylint: disable=too-few-public-methods
|
class Problem(abc.ABC): # pylint: disable=too-few-public-methods
|
||||||
"""
|
"""
|
||||||
A parent class representing a form of static analysis error.
|
An abstract parent class representing a form of static analysis error.
|
||||||
|
It extends an Abstract Base Class, which means it is not instantiable, and
|
||||||
|
it also mandates certain abstract methods to be implemented in subclasses.
|
||||||
"""
|
"""
|
||||||
# Class variable to control the quietness of all problems
|
# Class variable to control the quietness of all problems
|
||||||
quiet = False
|
quiet = False
|
||||||
|
@ -104,6 +107,28 @@ class Problem(): # pylint: disable=too-few-public-methods
|
||||||
self.textwrapper.initial_indent = " > "
|
self.textwrapper.initial_indent = " > "
|
||||||
self.textwrapper.subsequent_indent = " "
|
self.textwrapper.subsequent_indent = " "
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""
|
||||||
|
Unified string representation method for all Problems.
|
||||||
|
"""
|
||||||
|
if self.__class__.quiet:
|
||||||
|
return self.quiet_output()
|
||||||
|
return self.verbose_output()
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def quiet_output(self):
|
||||||
|
"""
|
||||||
|
The output when --quiet is enabled.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def verbose_output(self):
|
||||||
|
"""
|
||||||
|
The default output with explanation and code snippet if appropriate.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
class SymbolNotInHeader(Problem): # pylint: disable=too-few-public-methods
|
class SymbolNotInHeader(Problem): # pylint: disable=too-few-public-methods
|
||||||
"""
|
"""
|
||||||
A problem that occurs when an exported/available symbol in the object file
|
A problem that occurs when an exported/available symbol in the object file
|
||||||
|
@ -117,10 +142,10 @@ class SymbolNotInHeader(Problem): # pylint: disable=too-few-public-methods
|
||||||
self.symbol_name = symbol_name
|
self.symbol_name = symbol_name
|
||||||
Problem.__init__(self)
|
Problem.__init__(self)
|
||||||
|
|
||||||
def __str__(self):
|
def quiet_output(self):
|
||||||
if self.quiet:
|
return "{0}".format(self.symbol_name)
|
||||||
return "{0}".format(self.symbol_name)
|
|
||||||
|
|
||||||
|
def verbose_output(self):
|
||||||
return self.textwrapper.fill(
|
return self.textwrapper.fill(
|
||||||
"'{0}' was found as an available symbol in the output of nm, "
|
"'{0}' was found as an available symbol in the output of nm, "
|
||||||
"however it was not declared in any header files."
|
"however it was not declared in any header files."
|
||||||
|
@ -140,13 +165,14 @@ class PatternMismatch(Problem): # pylint: disable=too-few-public-methods
|
||||||
self.match = match
|
self.match = match
|
||||||
Problem.__init__(self)
|
Problem.__init__(self)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.quiet:
|
|
||||||
return (
|
|
||||||
"{0}:{1}:{2}"
|
|
||||||
.format(self.match.filename, self.match.line_no, self.match.name)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
def quiet_output(self):
|
||||||
|
return (
|
||||||
|
"{0}:{1}:{2}"
|
||||||
|
.format(self.match.filename, self.match.line_no, self.match.name)
|
||||||
|
)
|
||||||
|
|
||||||
|
def verbose_output(self):
|
||||||
return self.textwrapper.fill(
|
return self.textwrapper.fill(
|
||||||
"{0}:{1}: '{2}' does not match the required pattern '{3}'."
|
"{0}:{1}: '{2}' does not match the required pattern '{3}'."
|
||||||
.format(
|
.format(
|
||||||
|
@ -169,13 +195,13 @@ class Typo(Problem): # pylint: disable=too-few-public-methods
|
||||||
self.match = match
|
self.match = match
|
||||||
Problem.__init__(self)
|
Problem.__init__(self)
|
||||||
|
|
||||||
def __str__(self):
|
def quiet_output(self):
|
||||||
if self.quiet:
|
return (
|
||||||
return (
|
"{0}:{1}:{2}"
|
||||||
"{0}:{1}:{2}"
|
.format(self.match.filename, self.match.line_no, self.match.name)
|
||||||
.format(self.match.filename, self.match.line_no, self.match.name)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
def verbose_output(self):
|
||||||
return self.textwrapper.fill(
|
return self.textwrapper.fill(
|
||||||
"{0}:{1}: '{2}' looks like a typo. It was not found in any "
|
"{0}:{1}: '{2}' looks like a typo. It was not found in any "
|
||||||
"macros or any enums. If this is not a typo, put "
|
"macros or any enums. If this is not a typo, put "
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue