adlint-postfilter 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +24 -0
- data/COPYING +674 -0
- data/ChangeLog +9 -0
- data/INSTALL +61 -0
- data/MANIFEST +20 -0
- data/NEWS +35 -0
- data/README +192 -0
- data/Rakefile +86 -0
- data/bin/adlint_flt +154 -0
- data/etc/conf.d/adlint_postfilter.yml +21 -0
- data/lib/adlint/postfilter/annotate.rb +143 -0
- data/lib/adlint/postfilter/command.rb +184 -0
- data/lib/adlint/postfilter/config.rb +266 -0
- data/lib/adlint/postfilter/content.rb +128 -0
- data/lib/adlint/postfilter/driver.rb +76 -0
- data/lib/adlint/postfilter/filter.rb +52 -0
- data/lib/adlint/postfilter/path.rb +68 -0
- data/lib/adlint/postfilter/suppress.rb +202 -0
- data/lib/adlint/postfilter/version.rb +73 -0
- data/lib/adlint/postfilter.rb +43 -0
- metadata +87 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
# Message control annotations.
|
2
|
+
#
|
3
|
+
# Author:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
|
4
|
+
# Copyright:: Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
|
5
|
+
# License:: GPLv3+: GNU General Public License version 3 or later
|
6
|
+
#
|
7
|
+
# Owner:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
|
8
|
+
|
9
|
+
#--
|
10
|
+
# ___ ____ __ ___ _________
|
11
|
+
# / | / _ |/ / / / | / /__ __/ Source Code Static Analyzer
|
12
|
+
# / /| | / / / / / / / |/ / / / AdLint - Advanced Lint
|
13
|
+
# / __ |/ /_/ / /___/ / /| / / /
|
14
|
+
# /_/ |_|_____/_____/_/_/ |_/ /_/ Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
|
15
|
+
#
|
16
|
+
# This file is part of adlint-postfilter.
|
17
|
+
#
|
18
|
+
# adlint-postfilter is free software: you can redistribute it and/or modify it
|
19
|
+
# under the terms of the GNU General Public License as published by the Free
|
20
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
21
|
+
# later version.
|
22
|
+
#
|
23
|
+
# adlint-postfilter is distributed in the hope that it will be useful, but
|
24
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
25
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
26
|
+
# more details.
|
27
|
+
#
|
28
|
+
# You should have received a copy of the GNU General Public License along with
|
29
|
+
# adlint-postfilter. If not, see <http://www.gnu.org/licenses/>.
|
30
|
+
#
|
31
|
+
#++
|
32
|
+
|
33
|
+
require "adlint/postfilter/suppress"
|
34
|
+
|
35
|
+
module AdLint #:nodoc:
|
36
|
+
module Postfilter #:nodoc:
|
37
|
+
|
38
|
+
class MessageControlAnnotation
|
39
|
+
def initialize(message_controller_str)
|
40
|
+
@message_controller = MessageController.new(message_controller_str)
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :message_controller
|
44
|
+
end
|
45
|
+
|
46
|
+
class TranslationUnitWideAnnotation < MessageControlAnnotation
|
47
|
+
def self.detect(str, composing_fpaths)
|
48
|
+
str =~ /ADLINT:TUNIT:\[.*\]/ ? new($&, composing_fpaths) : nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(message_controller_str, composing_fpaths)
|
52
|
+
super(message_controller_str)
|
53
|
+
@composing_fpaths = composing_fpaths
|
54
|
+
end
|
55
|
+
private_class_method :new
|
56
|
+
|
57
|
+
def generate_suppressions
|
58
|
+
message_controller.message_control_list.map { |mesg_ctrl|
|
59
|
+
@composing_fpaths.map do |fpath|
|
60
|
+
FileWiseSuppression.new(mesg_ctrl.message_id, fpath,
|
61
|
+
mesg_ctrl.suppression_activation?)
|
62
|
+
end
|
63
|
+
}.flatten
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class LineWiseAnnotation < MessageControlAnnotation
|
68
|
+
def self.detect(str, fpath, line_no)
|
69
|
+
str =~ /(?:ADLINT:LINE:|ADLINT::)\[.*\]/ ? new($&, fpath, line_no) : nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(message_controller_str, fpath, line_no)
|
73
|
+
super(message_controller_str)
|
74
|
+
@fpath, @line_no = fpath, line_no
|
75
|
+
end
|
76
|
+
private_class_method :new
|
77
|
+
|
78
|
+
def generate_suppressions
|
79
|
+
message_controller.message_control_list.map do |mesg_ctrl|
|
80
|
+
LineWiseSuppression.new(mesg_ctrl.message_id, @fpath, @line_no,
|
81
|
+
mesg_ctrl.suppression_activation?)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class MessageController
|
87
|
+
def initialize(message_controller_str)
|
88
|
+
@message_control_list = parse_message_controller(message_controller_str)
|
89
|
+
end
|
90
|
+
|
91
|
+
attr_reader :message_control_list
|
92
|
+
|
93
|
+
private
|
94
|
+
def parse_message_controller(message_controller_str)
|
95
|
+
if message_controller_str =~ /\[(.*)\]/
|
96
|
+
parse_message_control_list($1)
|
97
|
+
else
|
98
|
+
[]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def parse_message_control_list(message_control_list_str)
|
103
|
+
message_control_list_str.scan(/([+-])([WC]\d{4})/).map do |op, mesg_id|
|
104
|
+
case op
|
105
|
+
when "-"
|
106
|
+
MessageSuppressionActivation.new(mesg_id)
|
107
|
+
when "+"
|
108
|
+
MessageSuppressionDeactivation.new(mesg_id)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class MessageControl
|
115
|
+
def initialize(message_id_str)
|
116
|
+
@message_id = message_id_str.to_sym
|
117
|
+
end
|
118
|
+
|
119
|
+
attr_reader :message_id
|
120
|
+
|
121
|
+
def suppression_activation?
|
122
|
+
subclass_responsibility
|
123
|
+
end
|
124
|
+
|
125
|
+
def suppression_deactivation?
|
126
|
+
!suppression_activation?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class MessageSuppressionActivation < MessageControl
|
131
|
+
def suppression_activation?
|
132
|
+
true
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class MessageSuppressionDeactivation < MessageControl
|
137
|
+
def suppression_activation?
|
138
|
+
false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# AdLint analysis commands.
|
2
|
+
#
|
3
|
+
# Author:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
|
4
|
+
# Copyright:: Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
|
5
|
+
# License:: GPLv3+: GNU General Public License version 3 or later
|
6
|
+
#
|
7
|
+
# Owner:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
|
8
|
+
|
9
|
+
#--
|
10
|
+
# ___ ____ __ ___ _________
|
11
|
+
# / | / _ |/ / / / | / /__ __/ Source Code Static Analyzer
|
12
|
+
# / /| | / / / / / / / |/ / / / AdLint - Advanced Lint
|
13
|
+
# / __ |/ /_/ / /___/ / /| / / /
|
14
|
+
# /_/ |_|_____/_____/_/_/ |_/ /_/ Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
|
15
|
+
#
|
16
|
+
# This file is part of adlint-postfilter.
|
17
|
+
#
|
18
|
+
# adlint-postfilter is free software: you can redistribute it and/or modify it
|
19
|
+
# under the terms of the GNU General Public License as published by the Free
|
20
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
21
|
+
# later version.
|
22
|
+
#
|
23
|
+
# adlint-postfilter is distributed in the hope that it will be useful, but
|
24
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
25
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
26
|
+
# more details.
|
27
|
+
#
|
28
|
+
# You should have received a copy of the GNU General Public License along with
|
29
|
+
# adlint-postfilter. If not, see <http://www.gnu.org/licenses/>.
|
30
|
+
#
|
31
|
+
#++
|
32
|
+
|
33
|
+
require "fileutils"
|
34
|
+
require "getoptlong"
|
35
|
+
require "pathname"
|
36
|
+
|
37
|
+
require "adlint/postfilter/config"
|
38
|
+
require "adlint/postfilter/content"
|
39
|
+
require "adlint/postfilter/filter"
|
40
|
+
|
41
|
+
module AdLint #:nodoc:
|
42
|
+
module Postfilter #:nodoc:
|
43
|
+
|
44
|
+
class AnalysisCommand
|
45
|
+
def self.for(command_line, config_fpath, src_vpath = nil)
|
46
|
+
case name = command_line.split.first
|
47
|
+
when "adlint"
|
48
|
+
ADLINT.new(command_line, config_fpath, src_vpath)
|
49
|
+
when "adlint_sma"
|
50
|
+
ADLINT_SMA.new(command_line, config_fpath, src_vpath)
|
51
|
+
when "adlint_cma"
|
52
|
+
ADLINT_CMA.new(command_line, config_fpath, src_vpath)
|
53
|
+
when "adlint_chk"
|
54
|
+
ADLINT_CHK.new(command_line, config_fpath, src_vpath)
|
55
|
+
else
|
56
|
+
raise "unknown command `#{name}'"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize(command_line, config_fpath, src_vpath = nil)
|
61
|
+
@command_line = command_line
|
62
|
+
@config_fpath = config_fpath
|
63
|
+
@src_vpath = src_vpath
|
64
|
+
|
65
|
+
@traits_fpath, @strip_num, @output_dpath, @src_fpaths =
|
66
|
+
parse_adlint_command_line(@command_line, @src_vpath)
|
67
|
+
end
|
68
|
+
|
69
|
+
def execute
|
70
|
+
status, stderr_content = exec_adlint_command(@command_line)
|
71
|
+
filter_results(create_filters, stderr_content)
|
72
|
+
status
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def exec_adlint_command(command_line)
|
77
|
+
system("#{command_line} 2>#{stderr_fpath}")
|
78
|
+
return $?, StderrContent.new(File.read(stderr_fpath))
|
79
|
+
ensure
|
80
|
+
FileUtils.rm_f(stderr_fpath)
|
81
|
+
end
|
82
|
+
|
83
|
+
def filter_results(filters, stderr_content)
|
84
|
+
filters.each { |filter| filter.execute(stderr_content) }
|
85
|
+
stderr_content.overwrite!
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_filters
|
89
|
+
subclass_responsibility
|
90
|
+
end
|
91
|
+
|
92
|
+
def parse_adlint_command_line(command_line, src_vpath = nil)
|
93
|
+
parser = GetoptLong.new(
|
94
|
+
["--traits", "-t", GetoptLong::REQUIRED_ARGUMENT],
|
95
|
+
["--list-file", "-l", GetoptLong::REQUIRED_ARGUMENT],
|
96
|
+
["--output-dir", "-o", GetoptLong::REQUIRED_ARGUMENT],
|
97
|
+
["--strip", "-p", GetoptLong::REQUIRED_ARGUMENT],
|
98
|
+
["--verbose", "-v", GetoptLong::NO_ARGUMENT])
|
99
|
+
parser.quiet = true
|
100
|
+
|
101
|
+
begin
|
102
|
+
traits_fpath = nil
|
103
|
+
output_dpath = nil
|
104
|
+
strip_num = src_vpath ? src_vpath.components.size : 0
|
105
|
+
|
106
|
+
ARGV.replace(command_line.split).shift
|
107
|
+
|
108
|
+
parser.each_option do |optname, optarg|
|
109
|
+
case optname
|
110
|
+
when "--traits"
|
111
|
+
traits_fpath = Pathname.new(optarg)
|
112
|
+
when "--output-dir"
|
113
|
+
output_dpath = Pathname.new(optarg)
|
114
|
+
when "--strip"
|
115
|
+
strip_num = optarg.to_i
|
116
|
+
end
|
117
|
+
end
|
118
|
+
rescue
|
119
|
+
# NOTE: If the AdLint's command line is invalid, child analysis command
|
120
|
+
# will encounter the same problem and will notice it.
|
121
|
+
# So, nothing to be done.
|
122
|
+
end
|
123
|
+
|
124
|
+
src_fpaths = ARGV.map { |str|
|
125
|
+
if str.end_with?(".c.met.csv")
|
126
|
+
@src_vpath.join(Pathname.new(str.sub(/.met.csv\z/, "")))
|
127
|
+
else
|
128
|
+
Pathname.new(str)
|
129
|
+
end
|
130
|
+
}
|
131
|
+
|
132
|
+
return traits_fpath, strip_num, output_dpath, src_fpaths
|
133
|
+
end
|
134
|
+
|
135
|
+
def create_sma_filters
|
136
|
+
create_sma_configs.map { |sma_config| MessageFilter.new(sma_config) }
|
137
|
+
end
|
138
|
+
|
139
|
+
def create_cma_filter
|
140
|
+
MessageFilter.new(create_cma_config)
|
141
|
+
end
|
142
|
+
|
143
|
+
def create_sma_configs
|
144
|
+
@src_fpaths.map do |src_fpath|
|
145
|
+
SmaConfig.new(@config_fpath, @traits_fpath, src_fpath, @strip_num,
|
146
|
+
@output_dpath)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def create_cma_config
|
151
|
+
CmaConfig.new(@config_fpath, @traits_fpath, @strip_num, @output_dpath,
|
152
|
+
create_sma_configs)
|
153
|
+
end
|
154
|
+
|
155
|
+
def stderr_fpath
|
156
|
+
Pathname.new("./adlint_postfilter.#{$$}.stderr")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class ADLINT < AnalysisCommand
|
161
|
+
private
|
162
|
+
def create_filters
|
163
|
+
create_sma_filters + [create_cma_filter]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class ADLINT_SMA < AnalysisCommand
|
168
|
+
private
|
169
|
+
def create_filters
|
170
|
+
create_sma_filters
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class ADLINT_CMA < AnalysisCommand
|
175
|
+
private
|
176
|
+
def create_filters
|
177
|
+
[create_cma_filter]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class ADLINT_CHK < ADLINT_SMA; end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
# Message suppression configuration.
|
2
|
+
#
|
3
|
+
# Author:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
|
4
|
+
# Copyright:: Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
|
5
|
+
# License:: GPLv3+: GNU General Public License version 3 or later
|
6
|
+
#
|
7
|
+
# Owner:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
|
8
|
+
|
9
|
+
#--
|
10
|
+
# ___ ____ __ ___ _________
|
11
|
+
# / | / _ |/ / / / | / /__ __/ Source Code Static Analyzer
|
12
|
+
# / /| | / / / / / / / |/ / / / AdLint - Advanced Lint
|
13
|
+
# / __ |/ /_/ / /___/ / /| / / /
|
14
|
+
# /_/ |_|_____/_____/_/_/ |_/ /_/ Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
|
15
|
+
#
|
16
|
+
# This file is part of adlint-postfilter.
|
17
|
+
#
|
18
|
+
# adlint-postfilter is free software: you can redistribute it and/or modify it
|
19
|
+
# under the terms of the GNU General Public License as published by the Free
|
20
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
21
|
+
# later version.
|
22
|
+
#
|
23
|
+
# adlint-postfilter is distributed in the hope that it will be useful, but
|
24
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
25
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
26
|
+
# more details.
|
27
|
+
#
|
28
|
+
# You should have received a copy of the GNU General Public License along with
|
29
|
+
# adlint-postfilter. If not, see <http://www.gnu.org/licenses/>.
|
30
|
+
#
|
31
|
+
#++
|
32
|
+
|
33
|
+
require "yaml"
|
34
|
+
require "pathname"
|
35
|
+
|
36
|
+
require "adlint/postfilter/suppress"
|
37
|
+
require "adlint/postfilter/annotate"
|
38
|
+
require "adlint/postfilter/path"
|
39
|
+
|
40
|
+
module AdLint #:nodoc:
|
41
|
+
module Postfilter #:nodoc:
|
42
|
+
|
43
|
+
class Config
|
44
|
+
def initialize(config_fpath, traits_fpath, strip_num)
|
45
|
+
load_postfilter_config(config_fpath)
|
46
|
+
load_adlint_traits(traits_fpath)
|
47
|
+
|
48
|
+
@initial_header_suppression =
|
49
|
+
create_adlint_initial_header_suppression
|
50
|
+
@platform_header_suppression =
|
51
|
+
create_platform_header_supression(strip_num)
|
52
|
+
@project_wide_suppressions = create_project_wide_suppressions
|
53
|
+
end
|
54
|
+
|
55
|
+
def individual_suppression_control_enabled?
|
56
|
+
@@config_yaml["message_traits"]["enable_individual_suppression_control"]
|
57
|
+
end
|
58
|
+
|
59
|
+
def msg_fpath
|
60
|
+
subclass_responsibility
|
61
|
+
end
|
62
|
+
|
63
|
+
def suppression_list
|
64
|
+
subclass_responsibility
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def create_adlint_initial_header_suppression
|
69
|
+
AdLintInitialHeaderSuppression.new(
|
70
|
+
Pathname.new(adlint_traits.of_compiler.initial_header).realpath,
|
71
|
+
Pathname.new(adlint_traits.of_project.initial_header).realpath)
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_platform_header_supression(strip_num)
|
75
|
+
root_dpath = Pathname.getwd.realpath
|
76
|
+
strip_num.times { root_dpath = root_dpath.parent }
|
77
|
+
PlatformHeaderSuppression.new(root_dpath)
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_project_wide_suppressions
|
81
|
+
list = @@config_yaml["message_traits"]["suppression_list"] || []
|
82
|
+
list.map { |mesg_id| ProjectWideSuppression.new(mesg_id.to_sym) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def adlint_traits
|
86
|
+
@@adlint_traits
|
87
|
+
end
|
88
|
+
|
89
|
+
def load_postfilter_config(config_fpath)
|
90
|
+
return if defined?(@@config_yaml)
|
91
|
+
|
92
|
+
# NOTE: Psych::SyntaxError is a subclass of the builtin ::SyntaxError.
|
93
|
+
# The rescue clause without error_type is equivalent to
|
94
|
+
# `rescue StandardError'. So, the rescue clause without error_type
|
95
|
+
# cannot catch Psych::SyntaxError.
|
96
|
+
begin
|
97
|
+
@@config_yaml = File.open(config_fpath, "r:utf-8") { |io|
|
98
|
+
case array_or_stream = YAML.load_stream(io)
|
99
|
+
when Array
|
100
|
+
# NOTE: YAML.load_stream returns Array in Ruby 1.9.3-preview1.
|
101
|
+
array_or_stream.first
|
102
|
+
when YAML::Stream
|
103
|
+
array_or_stream.documents.first
|
104
|
+
end
|
105
|
+
}
|
106
|
+
rescue SyntaxError, StandardError => ex
|
107
|
+
$stderr.puts "#{command}: Failed to read `#{config_fpath}'."
|
108
|
+
$stderr.puts
|
109
|
+
$stderr.puts "Detailed message is below;"
|
110
|
+
$stderr.puts ex.message, ex.backtrace
|
111
|
+
$stderr.puts
|
112
|
+
exit 11
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def load_adlint_traits(traits_fpath)
|
117
|
+
return if defined?(@@adlint_traits)
|
118
|
+
|
119
|
+
# NOTE: Psych::SyntaxError is a subclass of the builtin ::SyntaxError.
|
120
|
+
# The rescue clause without error_type is equivalent to
|
121
|
+
# `rescue StandardError'. So, the rescue clause without error_type
|
122
|
+
# cannot catch Psych::SyntaxError.
|
123
|
+
begin
|
124
|
+
@@adlint_traits = Traits.instance
|
125
|
+
@@adlint_traits.read_from(traits_fpath)
|
126
|
+
rescue SyntaxError, StandardError
|
127
|
+
# NOTE: If the AdLint's traits file is invalid, child analysis command
|
128
|
+
# will encounter the same problem and will notice it.
|
129
|
+
# So, nothing to be done.
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class SmaConfig < Config
|
135
|
+
include PathUtil
|
136
|
+
|
137
|
+
def initialize(config_fpath, traits_fpath,
|
138
|
+
src_fpath, strip_num, output_dpath = nil)
|
139
|
+
super(config_fpath, traits_fpath, strip_num)
|
140
|
+
|
141
|
+
@msg_fpath = sma_msg_fpath_of(src_fpath, strip_num, output_dpath)
|
142
|
+
@suppression_list =
|
143
|
+
create_suppression_list(src_fpath, strip_num, output_dpath)
|
144
|
+
end
|
145
|
+
|
146
|
+
attr_reader :msg_fpath
|
147
|
+
attr_reader :suppression_list
|
148
|
+
attr_reader :tunit_wide_suppressions
|
149
|
+
attr_reader :line_wise_suppressions
|
150
|
+
|
151
|
+
private
|
152
|
+
def create_suppression_list(src_fpath, strip_num, output_dpath)
|
153
|
+
@tunit_wide_suppressions =
|
154
|
+
create_tunit_wide_suppressions(src_fpath, strip_num, output_dpath)
|
155
|
+
@line_wise_suppressions =
|
156
|
+
create_line_wise_suppressions(src_fpath, strip_num, output_dpath)
|
157
|
+
|
158
|
+
MessageSuppressionList.new(@initial_header_suppression,
|
159
|
+
@platform_header_suppression,
|
160
|
+
@project_wide_suppressions,
|
161
|
+
@tunit_wide_suppressions,
|
162
|
+
@line_wise_suppressions)
|
163
|
+
end
|
164
|
+
|
165
|
+
def create_tunit_wide_suppressions(src_fpath, strip_num, output_dpath)
|
166
|
+
return [] unless individual_suppression_control_enabled?
|
167
|
+
|
168
|
+
i_fpath = i_fpath_of(src_fpath, strip_num, output_dpath)
|
169
|
+
if ann = find_effective_tunit_wide_annotation(src_fpath, i_fpath)
|
170
|
+
ann.generate_suppressions
|
171
|
+
else
|
172
|
+
[]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def create_line_wise_suppressions(src_fpath, strip_num, output_dpath)
|
177
|
+
return [] unless individual_suppression_control_enabled?
|
178
|
+
|
179
|
+
i_fpath = i_fpath_of(src_fpath, strip_num, output_dpath)
|
180
|
+
collect_composing_fpaths_in(i_fpath).each_with_object([]) do |fpath, ary|
|
181
|
+
collect_line_wise_annotations(fpath).each do |ann, line_no|
|
182
|
+
ary.concat(ann.generate_suppressions)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def find_effective_tunit_wide_annotation(src_fpath, i_fpath)
|
188
|
+
composing_fpaths = collect_composing_fpaths_in(i_fpath)
|
189
|
+
|
190
|
+
# NOTE: If multiple tunit-wide-annotations are written in the source
|
191
|
+
# file, the first one will be treated as effective.
|
192
|
+
File.open(src_fpath, "r:binary") do |io|
|
193
|
+
io.each_line do |line|
|
194
|
+
if ann = TranslationUnitWideAnnotation.detect(line, composing_fpaths)
|
195
|
+
return ann
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
|
202
|
+
def collect_composing_fpaths_in(i_fpath)
|
203
|
+
File.open(i_fpath, "r:binary") do |io|
|
204
|
+
io.each_line.with_object([]) { |line, composing_fpaths|
|
205
|
+
if line =~ /\A# \d+ "(.*)"/
|
206
|
+
composing_fpaths.push(Pathname.new($1).realpath)
|
207
|
+
end
|
208
|
+
}.uniq
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def collect_line_wise_annotations(fpath)
|
213
|
+
File.open(fpath, "r:binary") do |io|
|
214
|
+
io.each_line.with_index.with_object([]) do |(line, index), annotations|
|
215
|
+
if ann = LineWiseAnnotation.detect(line, fpath, index + 1)
|
216
|
+
annotations.push(ann)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class CmaConfig < Config
|
224
|
+
include PathUtil
|
225
|
+
|
226
|
+
def initialize(config_fpath, traits_fpath,
|
227
|
+
strip_num, output_dpath, sma_configs)
|
228
|
+
super(config_fpath, traits_fpath, strip_num)
|
229
|
+
|
230
|
+
project_name = adlint_traits.of_project.project_name
|
231
|
+
@msg_fpath = cma_msg_fpath_of(project_name, output_dpath)
|
232
|
+
@suppression_list = create_suppression_list(sma_configs)
|
233
|
+
end
|
234
|
+
|
235
|
+
attr_reader :msg_fpath
|
236
|
+
attr_reader :suppression_list
|
237
|
+
|
238
|
+
private
|
239
|
+
def create_suppression_list(sma_configs)
|
240
|
+
tunit_wide_suppressions =
|
241
|
+
collect_all_tunit_wide_suppressions(sma_configs)
|
242
|
+
line_wise_suppressions = collect_all_line_wise_suppressions(sma_configs)
|
243
|
+
|
244
|
+
MessageSuppressionList.new(@initial_header_suppression,
|
245
|
+
@platform_header_suppression,
|
246
|
+
@project_wide_suppressions,
|
247
|
+
tunit_wide_suppressions,
|
248
|
+
line_wise_suppressions)
|
249
|
+
end
|
250
|
+
|
251
|
+
def collect_all_tunit_wide_suppressions(sma_configs)
|
252
|
+
sma_configs.map { |sma_config|
|
253
|
+
sma_config.tunit_wide_suppressions
|
254
|
+
}.flatten
|
255
|
+
end
|
256
|
+
|
257
|
+
def collect_all_line_wise_suppressions(sma_configs)
|
258
|
+
sma_configs.map { |sma_config|
|
259
|
+
sma_config.line_wise_suppressions
|
260
|
+
}.flatten
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|