au.com.integradev.delphi.checks.verifier.Expectations Maven / Gradle / Ivy
The newest version!
/*
* Sonar Delphi Plugin
* Copyright (C) 2024 Integrated Application Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package au.com.integradev.delphi.checks.verifier;
import au.com.integradev.delphi.file.DelphiFile.DelphiInputFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.sonar.plugins.communitydelphi.api.token.DelphiToken;
class Expectations {
private static final Pattern NONCOMPLIANT_PATTERN =
Pattern.compile("(?i)^//\\s*Noncompliant(?:@([-+]\\d+))?\\b");
private static final Pattern QUICK_FIX_RANGE_PATTERN =
Pattern.compile("^([+-]\\d+):(\\d*) to ([+-]\\d+):(\\d*)$");
private static final Pattern QUICK_FIX_PATTERN =
Pattern.compile("(?i)^//\\s*Fix\\s*(\\w+)?@\\s*\\[([^]]*)]\\s*(?:<<(.*?)>>)?");
private final List expectedIssues;
private final List expectedQuickFixes;
private Expectations(List issues, List quickFixes) {
this.expectedIssues = issues;
this.expectedQuickFixes = quickFixes;
}
public List issues() {
return Collections.unmodifiableList(expectedIssues);
}
public List quickFixes() {
return Collections.unmodifiableList(expectedQuickFixes);
}
public static Expectations fromComments(DelphiInputFile delphiFile) {
return parse(delphiFile.getComments());
}
private static Expectations parse(List comments) {
List noncompliantComments = new ArrayList<>();
List fixComments = new ArrayList<>();
for (DelphiToken comment : comments) {
var matcher = NONCOMPLIANT_PATTERN.matcher(comment.getImage());
if (matcher.matches()) {
noncompliantComments.add(
new MatchResultOnLine(matcher.toMatchResult(), comment.getBeginLine()));
} else {
matcher = QUICK_FIX_PATTERN.matcher(comment.getImage());
if (matcher.matches()) {
fixComments.add(new MatchResultOnLine(matcher.toMatchResult(), comment.getBeginLine()));
}
}
}
List issues =
noncompliantComments.stream()
.map(r -> parseNoncompliantComment(r.getLine(), r.getMatchResult()))
.collect(Collectors.toList());
List quickFixes =
fixComments.stream()
.map(r -> parseFixComment(r.getLine(), r.getMatchResult()))
.collect(Collectors.groupingBy(TextEditExpectation::getFixId))
.entrySet()
.stream()
.map(entry -> new QuickFixExpectation(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
return new Expectations(issues, quickFixes);
}
private static TextEditExpectation parseFixComment(int offset, MatchResult matchResult) {
String fixId = matchResult.group(1);
String rangeStr = matchResult.group(2);
String replacementStr = matchResult.group(3);
if (replacementStr == null) {
throw new AssertionError(
String.format(
"Replacement text must be specified for quick fix edit on line %d", offset));
}
var rangeMatcher = QUICK_FIX_RANGE_PATTERN.matcher(rangeStr);
if (!rangeMatcher.matches()) {
throw new AssertionError(
String.format("Invalid range '%s' for quick fix edit on line %d", rangeStr, offset));
}
String beginLineStr = rangeMatcher.group(1);
String beginColumnStr = rangeMatcher.group(2);
String endLineStr = rangeMatcher.group(3);
String endColumnStr = rangeMatcher.group(4);
int beginLine = beginLineStr != null ? Integer.parseInt(beginLineStr) : 0;
int endLine = endLineStr != null ? Integer.parseInt(endLineStr) : 0;
return new TextEditExpectation(
fixId == null ? "(unnamed)" : fixId,
replacementStr.replace("\\n", "\n").replace("\\r", "\r"),
beginLine + offset,
endLine + offset,
Integer.parseInt(beginColumnStr),
Integer.parseInt(endColumnStr));
}
private static IssueExpectation parseNoncompliantComment(int beginLine, MatchResult matchResult) {
String offset = matchResult.group(1);
if (offset == null) {
return new IssueExpectation(beginLine);
}
try {
return new IssueExpectation(beginLine + Integer.parseInt(offset));
} catch (NumberFormatException e) {
throw new AssertionError(
String.format(
"Failed to parse 'Noncompliant' comment line offset '%s' as an integer.", offset));
}
}
private static class MatchResultOnLine {
private final MatchResult matchResult;
private final int line;
public MatchResultOnLine(MatchResult result, int line) {
this.matchResult = result;
this.line = line;
}
public MatchResult getMatchResult() {
return matchResult;
}
public int getLine() {
return line;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy