blob: ab1f7eb0dd1b600ea5043daa4a1240c8618878ed [file] [log] [blame]
Brian O'Connorbe95f682016-05-18 15:40:19 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Brian O'Connorbe95f682016-05-18 15:40:19 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.checkstyle;
17
Brian O'Connorbe95f682016-05-18 15:40:19 -070018import com.puppycrawl.tools.checkstyle.Checker;
19import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
20import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
21import com.puppycrawl.tools.checkstyle.PropertiesExpander;
22import com.puppycrawl.tools.checkstyle.api.AuditEvent;
23import com.puppycrawl.tools.checkstyle.api.AuditListener;
24import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
25import com.puppycrawl.tools.checkstyle.api.Configuration;
Thomas Vachuska275d2e82016-07-14 17:41:34 -070026import org.onosproject.buckdaemon.BuckTask;
27import org.onosproject.buckdaemon.BuckTaskContext;
Brian O'Connorbe95f682016-05-18 15:40:19 -070028
29import java.io.File;
Brian O'Connorbe95f682016-05-18 15:40:19 -070030import java.util.List;
31import java.util.concurrent.CountDownLatch;
32import java.util.stream.Collectors;
Brian O'Connorbe95f682016-05-18 15:40:19 -070033
Brian O'Connorfc247f42016-05-23 15:25:34 -070034import static com.google.common.base.Strings.isNullOrEmpty;
35
Thomas Vachuska275d2e82016-07-14 17:41:34 -070036/**
37 * Buck task for executing checkstyle on the specified project files.
38 */
39public class CheckstyleRunner implements BuckTask {
Brian O'Connorbe95f682016-05-18 15:40:19 -070040
41 private final Configuration config;
42
Thomas Vachuska275d2e82016-07-14 17:41:34 -070043 public CheckstyleRunner(String configLocation, String suppressionLocation) {
44 try {
45 // create a configuration
46 DefaultConfiguration config = (DefaultConfiguration) ConfigurationLoader
47 .loadConfiguration(configLocation, new PropertiesExpander(System.getProperties()));
Brian O'Connorbe95f682016-05-18 15:40:19 -070048
Thomas Vachuska275d2e82016-07-14 17:41:34 -070049 // add the suppression file to the configuration
50 DefaultConfiguration suppressions = new DefaultConfiguration("SuppressionFilter");
51 suppressions.addAttribute("file", suppressionLocation);
52 config.addChild(suppressions);
Brian O'Connorbe95f682016-05-18 15:40:19 -070053
Thomas Vachuska275d2e82016-07-14 17:41:34 -070054 this.config = config;
55 } catch (CheckstyleException e) {
56 throw new RuntimeException(e);
Brian O'Connorbe95f682016-05-18 15:40:19 -070057 }
Thomas Vachuska275d2e82016-07-14 17:41:34 -070058 }
59
60 @Override
61 public void execute(BuckTaskContext context) {
62 List<String> input = context.input();
63 if (input.size() < 3 || input.get(2).length() == 0) {
64 return;
65 }
66 String project = input.get(0);
67 String baseDir = input.get(1);
Brian O'Connorbe95f682016-05-18 15:40:19 -070068
69 // create a listener for output
Thomas Vachuska275d2e82016-07-14 17:41:34 -070070 StringAuditor listener = new StringAuditor(context);
Brian O'Connorfc247f42016-05-23 15:25:34 -070071 listener.setProjectName(project);
72 listener.setBaseDir(baseDir);
Brian O'Connorbe95f682016-05-18 15:40:19 -070073
74 // create Checker object and run it
75 final Checker checker = new Checker();
76 final ClassLoader moduleClassLoader = Checker.class.getClassLoader();
77 checker.setModuleClassLoader(moduleClassLoader);
78
79 try {
Brian O'Connorbe95f682016-05-18 15:40:19 -070080 checker.configure(config);
81 checker.addListener(listener);
82
83 // run Checker
Yuta HIGUCHI9312a802017-06-12 20:01:27 -070084 List<File> fileList = input.subList(2, input.size()).stream()
Thomas Vachuska73436b52017-03-22 19:50:47 -070085 .filter(s -> !s.contains("/:")) // Yes, fighting a hack with a hack.
Thomas Vachuska275d2e82016-07-14 17:41:34 -070086 .map(File::new)
87 .collect(Collectors.toList());
Brian O'Connorbe95f682016-05-18 15:40:19 -070088 int errorCounter = checker.process(fileList);
89 if (errorCounter > 0) {
Thomas Vachuska275d2e82016-07-14 17:41:34 -070090 context.output("CHECKSTYLE ERROR");
Brian O'Connorbe95f682016-05-18 15:40:19 -070091 }
Thomas Vachuska275d2e82016-07-14 17:41:34 -070092
93 listener.await();
94 } catch (CheckstyleException | InterruptedException e) {
Ray Milkey8df94b82016-11-16 11:03:32 -080095 e.printStackTrace(); //dump exeception to stderr
Thomas Vachuska275d2e82016-07-14 17:41:34 -070096 throw new RuntimeException(e);
Brian O'Connorbe95f682016-05-18 15:40:19 -070097 } finally {
98 checker.destroy();
99 }
100
Brian O'Connorfc247f42016-05-23 15:25:34 -0700101 }
102
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700103 static class StringAuditor implements AuditListener {
Brian O'Connorbe95f682016-05-18 15:40:19 -0700104
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700105 private final BuckTaskContext context;
106 private CountDownLatch finishedLatch = new CountDownLatch(1);
107 private String baseDir = "";
108 private String project = "";
Brian O'Connorbe95f682016-05-18 15:40:19 -0700109
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700110 StringAuditor(BuckTaskContext context) {
111 this.context = context;
112 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700113
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700114 public void setBaseDir(String base) {
115 this.baseDir = base;
116 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700117
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700118 public void setProjectName(String projectName) {
119 this.project = projectName;
120 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700121
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700122 public void await() throws InterruptedException {
123 finishedLatch.await();
124 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700125
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700126 @Override
127 public void auditStarted(AuditEvent evt) {
128 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700129
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700130 @Override
131 public void auditFinished(AuditEvent evt) {
132 finishedLatch.countDown();
133 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700134
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700135 @Override
136 public void fileStarted(AuditEvent evt) {
137 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700138
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700139 @Override
140 public void fileFinished(AuditEvent evt) {
141 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700142
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700143 @Override
144 public void addError(AuditEvent evt) {
145 switch (evt.getSeverityLevel()) {
146 case ERROR:
147 StringBuilder output = new StringBuilder();
148 String fileName = evt.getFileName();
149 if (!isNullOrEmpty(baseDir)) {
150 int index = fileName.indexOf(baseDir);
151 if (index >= 0) {
152 fileName = fileName.substring(index + baseDir.length() + 1);
153 if (!isNullOrEmpty(project)) {
154 output.append(project).append(':');
155 }
Brian O'Connorfc247f42016-05-23 15:25:34 -0700156 }
157 }
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700158 output.append(fileName).append(':').append(evt.getLine());
159 if (evt.getColumn() > 0) {
160 output.append(':').append(evt.getColumn());
161 }
162 output.append(": ").append(evt.getMessage());
163 context.output(output.toString());
164 break;
165 case IGNORE:
166 case INFO:
167 case WARNING:
168 default:
169 break;
170 }
171 }
172
173 @Override
174 public void addException(AuditEvent evt, Throwable throwable) {
175 addError(evt);
176 context.output(throwable.getMessage());
Brian O'Connorbe95f682016-05-18 15:40:19 -0700177 }
178 }
179
Thomas Vachuska275d2e82016-07-14 17:41:34 -0700180}