adlint-postfilter 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|