头歌质量分析

quality-analyse
youys 2 years ago
parent e2a38bec7f
commit 6fde10384e

@ -109,6 +109,29 @@
</dependency> </dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.21.6</version>
</dependency>
<dependency>
<groupId>net.jpountz.lz4</groupId>
<artifactId>lz4</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

@ -6,14 +6,17 @@ import net.educoder.ecsonar.model.RollPage;
import net.educoder.ecsonar.model.api.QualityInspect; import net.educoder.ecsonar.model.api.QualityInspect;
import net.educoder.ecsonar.model.api.QualityInspectIsCompleted; import net.educoder.ecsonar.model.api.QualityInspectIsCompleted;
import net.educoder.ecsonar.model.api.QualityInspectResultData; import net.educoder.ecsonar.model.api.QualityInspectResultData;
import net.educoder.ecsonar.model.vo.QualityInspectUserDataVO; import net.educoder.ecsonar.model.dto.AnalyseDetailDTO;
import net.educoder.ecsonar.model.vo.QualityInspectVO; import net.educoder.ecsonar.model.dto.AnalyseDetailListDTO;
import net.educoder.ecsonar.model.dto.CodeDetailDTO;
import net.educoder.ecsonar.model.vo.*;
import net.educoder.ecsonar.services.QualityInspectService; import net.educoder.ecsonar.services.QualityInspectService;
import net.educoder.ecsonar.utils.ResponseResult; import net.educoder.ecsonar.utils.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List; import java.util.List;
/** /**
@ -31,18 +34,19 @@ public class QualityInspectController {
/** /**
* *
* @param language *
* @param language
* @param homeworkId id * @param homeworkId id
* @param userDatas * @param userDatas
* @return * @return
*/ */
@RequestMapping(value = "qualityInspect", method = RequestMethod.POST) @RequestMapping(value = "qualityInspect", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public ResponseResult<String> qualityInspect(@RequestParam String language, public ResponseResult<String> qualityInspect(@RequestParam String language,
@RequestParam String homeworkId, @RequestParam String homeworkId,
@RequestParam String userDatas){ @RequestParam String userDatas) {
List<QualityInspectUserDataVO> userDataVOList = JSONArray.parseArray(userDatas,QualityInspectUserDataVO.class); List<QualityInspectUserDataVO> userDataVOList = JSONArray.parseArray(userDatas, QualityInspectUserDataVO.class);
QualityInspectVO qualityInspectVO = new QualityInspectVO(language, homeworkId, userDataVOList); QualityInspectVO qualityInspectVO = new QualityInspectVO(language, homeworkId, userDataVOList);
if (!Constant.language.contains(qualityInspectVO.getLanguage())) { if (!Constant.language.contains(qualityInspectVO.getLanguage())) {
@ -55,12 +59,13 @@ public class QualityInspectController {
/** /**
* *
*
* @param taskId * @param taskId
* @return * @return
*/ */
@RequestMapping(value = "qualityInspectIsCompleted", method = RequestMethod.GET) @RequestMapping(value = "qualityInspectIsCompleted", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public ResponseResult<QualityInspectIsCompleted> qualityInspectIsCompleted(@RequestParam String taskId){ public ResponseResult<QualityInspectIsCompleted> qualityInspectIsCompleted(@RequestParam String taskId) {
QualityInspectIsCompleted result = qualityInspectService.qualityInspectIsCompleted(taskId); QualityInspectIsCompleted result = qualityInspectService.qualityInspectIsCompleted(taskId);
return ResponseResult.success(result); return ResponseResult.success(result);
} }
@ -68,6 +73,7 @@ public class QualityInspectController {
/** /**
* *
*
* @param taskId * @param taskId
* @return * @return
*/ */
@ -76,19 +82,71 @@ public class QualityInspectController {
public ResponseResult<RollPage<QualityInspectResultData>> qualityInspectResultQuery( public ResponseResult<RollPage<QualityInspectResultData>> qualityInspectResultQuery(
@RequestParam(defaultValue = "50") Integer pageSize, @RequestParam(defaultValue = "50") Integer pageSize,
@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam String taskId){ @RequestParam String taskId) {
if (pageNum <= 1) { if (pageNum <= 1) {
pageNum = 1; pageNum = 1;
} }
QualityInspectIsCompleted isCompleted = qualityInspectService.qualityInspectIsCompleted(taskId); QualityInspectIsCompleted isCompleted = qualityInspectService.qualityInspectIsCompleted(taskId);
if(isCompleted.getCompleted() != 1){ if (isCompleted.getCompleted() != 1) {
return ResponseResult.error("质量检测正在处理中"); return ResponseResult.error("质量检测正在处理中");
} }
RollPage<QualityInspectResultData> result = qualityInspectService.qualityInspectResultQuery(pageNum, pageSize,taskId); RollPage<QualityInspectResultData> result = qualityInspectService.qualityInspectResultQuery(pageNum, pageSize, taskId);
return ResponseResult.success(result); return ResponseResult.success(result);
} }
/**
*
*
* @return
*/
@GetMapping("/analyseDetail")
@ResponseBody
public ResponseResult<AnalyseDetailDTO> analyseDetail(@Valid AnalyseDetailVO analyseDetailVO) {
AnalyseDetailDTO analyseDetailDTO = qualityInspectService.getAnalyseDetail(analyseDetailVO);
return ResponseResult.success(analyseDetailDTO);
}
/**
*
*
* @return
*/
@GetMapping("/analyseDetailList")
@ResponseBody
public ResponseResult<RollPage> analyseDetailList(@Valid AnalyseDetailListVO analyseDetailListVO) {
RollPage<AnalyseDetailListDTO> rollPage = qualityInspectService.getAnalyseDetailList(analyseDetailListVO);
return ResponseResult.success(rollPage);
}
/**
*
*
* @return
*/
@GetMapping("/problemAnalysis")
@ResponseBody
public ResponseResult<String> problemAnalysis(@RequestParam Integer ruleId) {
String description = qualityInspectService.getProblemAnalysis(ruleId);
return ResponseResult.success(description);
}
/**
*
*
* @return
*/
@GetMapping("/codeDetail")
@ResponseBody
public ResponseResult<CodeDetailDTO> codeDetail(@Valid CodeDetailVO codeDetailVO) {
CodeDetailDTO codeDetail = qualityInspectService.getCodeDetail(codeDetailVO);
return ResponseResult.success(codeDetail);
}
} }

@ -0,0 +1,19 @@
package net.educoder.ecsonar.dao;
import net.educoder.ecsonar.model.FileSource;
import org.apache.ibatis.annotations.Param;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
public interface FileSourceDao {
/**
* file_uuid
* @param fileUuid
* @return
*/
FileSource findFileSourceFileUuid(@Param("fileUuid") String fileUuid);
}

@ -0,0 +1,44 @@
package net.educoder.ecsonar.dao;
import net.educoder.ecsonar.model.Issues;
import net.educoder.ecsonar.model.dto.DegreeDTO;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
public interface IssuesDao {
/**
* issue
* @param projectUuid
* @param issueType
* @param severity
* @return
*/
Integer getPageIssuesCount(String projectUuid,Integer issueType, String severity);
/**
* issue
* @param projectUuid
* @param issueType
* @param severity
* @param start
* @param pageSize
* @return
*/
List<Issues> getPageIssues(String projectUuid,Integer issueType, String severity, Integer start, Integer pageSize);
/**
*
* @param projectUuid
* @param issueType
* @return
*/
DegreeDTO queryDegree(String projectUuid, Integer issueType);
}

@ -3,6 +3,7 @@ package net.educoder.ecsonar.dao;
import net.educoder.ecsonar.model.IssuesMetrics; import net.educoder.ecsonar.model.IssuesMetrics;
import net.educoder.ecsonar.model.Metrics; import net.educoder.ecsonar.model.Metrics;
import net.educoder.ecsonar.model.Project; import net.educoder.ecsonar.model.Project;
import net.educoder.ecsonar.model.Rule;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Select;
@ -58,4 +59,11 @@ public interface ProjectDao {
"(select count(1) from issues where project_uuid=#{projectUuid} and issue_type=3) vulnerability," + "(select count(1) from issues where project_uuid=#{projectUuid} and issue_type=3) vulnerability," +
"(select value from project_measures pm where component_uuid=#{projectUuid} and metric_id=3) codeLines") "(select value from project_measures pm where component_uuid=#{projectUuid} and metric_id=3) codeLines")
IssuesMetrics selectIssuesMetrics(String projectUuid); IssuesMetrics selectIssuesMetrics(String projectUuid);
/**
* rule
* @param id
* @return
*/
Rule findRuleById(@Param("id") Integer id);
} }

@ -0,0 +1,36 @@
package net.educoder.ecsonar.enums;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
public enum AnalyseTypeEnum {
CodeSmell(1),
BUG(2),
Vulnerability(3);
private Integer type;
AnalyseTypeEnum(Integer type) {
this.type = type;
}
public Integer getType() {
return type;
}
public static AnalyseTypeEnum getAnalyseTypeEnum(Integer type) {
for (AnalyseTypeEnum analyseType : values()) {
if (analyseType.type.equals(type)) {
return analyseType;
}
}
throw new RuntimeException("Not Found AnalyseTypeEnum by type=" + type);
}
}

@ -0,0 +1,59 @@
package net.educoder.ecsonar.enums;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
public enum DegreeEnum {
All(0, "ALL", "全部"),
Blocker(1, "BLOCKER", "阻断"),
Critical(2, "CRITICAL", "严重"),
Major(3, "MAJOR", "主要"),
Minor(4, "MINOR", "次要"),
Info(5, "INFO", "提示");
/**
*
*/
private Integer type;
/**
*
*/
private String value;
/**
*
*/
private String desc;
DegreeEnum(Integer type, String value, String desc) {
this.type = type;
this.value = value;
this.desc = desc;
}
public static DegreeEnum getDegreeEnum(Integer type) {
for (DegreeEnum de : values()) {
if (de.type.equals(type)) {
return de;
}
}
throw new RuntimeException("Not Found DegreeEnum by type=" + type);
}
public Integer getType() {
return type;
}
public String getValue() {
return value;
}
public String getDesc() {
return desc;
}
}

@ -0,0 +1,62 @@
package net.educoder.ecsonar.model;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.InvalidProtocolBufferException;
import lombok.Data;
import net.educoder.ecsonar.protobuf.DbFileSources;
import net.jpountz.lz4.LZ4BlockInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import static java.lang.String.format;
/**
* @Author: youys
* @Date: 2022/9/27
* @Description:
*/
@Data
public class FileSource {
private static final String SIZE_LIMIT_EXCEEDED_EXCEPTION_MESSAGE = "Protocol message was too large. May be malicious. " +
"Use CodedInputStream.setSizeLimit() to increase the size limit.";
private Long id;
private String projectUuid;
private String fileUuid;
private String lineHashes;
private String srcHash;
private byte[] binaryData = new byte[0];
private String dataHash;
public DbFileSources.Data decodeSourceData(byte[] binaryData) {
try {
return decodeRegularSourceData(binaryData);
} catch (IOException e) {
throw new IllegalStateException(
format("Fail to decompress and deserialize source data [id=%s,fileUuid=%s,projectUuid=%s]", id, fileUuid, projectUuid),
e);
}
}
private static DbFileSources.Data decodeRegularSourceData(byte[] binaryData) throws IOException {
try (LZ4BlockInputStream lz4Input = new LZ4BlockInputStream(new ByteArrayInputStream(binaryData))) {
return DbFileSources.Data.parseFrom(lz4Input);
} catch (InvalidProtocolBufferException e) {
if (SIZE_LIMIT_EXCEEDED_EXCEPTION_MESSAGE.equals(e.getMessage())) {
return decodeHugeSourceData(binaryData);
}
throw e;
}
}
private static DbFileSources.Data decodeHugeSourceData(byte[] binaryData) throws IOException {
try (LZ4BlockInputStream lz4Input = new LZ4BlockInputStream(new ByteArrayInputStream(binaryData))) {
CodedInputStream input = CodedInputStream.newInstance(lz4Input);
input.setSizeLimit(Integer.MAX_VALUE);
return DbFileSources.Data.parseFrom(input);
}
}
}

@ -0,0 +1,144 @@
package net.educoder.ecsonar.model;
/**
* @Author: youys
* @Date: 2022/9/19
* @Description:
*/
public class Issues {
private Long id;
private String kee;
private Integer ruleId;
private String severity;
private String message;
private String status;
private String projectUuid;
private Integer issueType;
private byte[] locations = new byte[0];
/**
* bug
*/
private String name;
/**
* bug
*/
private String description;
/**
*
*/
private String path;
/**
* file_sourcesfile_uuid
* issuecomponent_uuid
*/
private String uuid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getKee() {
return kee;
}
public void setKee(String kee) {
this.kee = kee;
}
public Integer getRuleId() {
return ruleId;
}
public void setRuleId(Integer ruleId) {
this.ruleId = ruleId;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getProjectUuid() {
return projectUuid;
}
public void setProjectUuid(String projectUuid) {
this.projectUuid = projectUuid;
}
public Integer getIssueType() {
return issueType;
}
public void setIssueType(Integer issueType) {
this.issueType = issueType;
}
public byte[] getLocations() {
return locations;
}
public void setLocations(byte[] locations) {
this.locations = locations;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
}

@ -0,0 +1,16 @@
package net.educoder.ecsonar.model;
import lombok.Data;
/**
* @Author: youys
* @Date: 2022/10/17
* @Description:
*/
@Data
public class Rule {
private Long id;
private String name;
private String description;
}

@ -0,0 +1,16 @@
package net.educoder.ecsonar.model.dto;
import lombok.Data;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
@Data
public class AnalyseDetailDTO {
private DegreeDTO bug;
private DegreeDTO vulnerability;
private DegreeDTO codeSmall;
}

@ -0,0 +1,48 @@
package net.educoder.ecsonar.model.dto;
import lombok.Data;
import java.util.Date;
/**
* @Author: youys
* @Date: 2022/9/27
* @Description:
*/
@Data
public class AnalyseDetailListDTO {
/**
*
*/
private String name;
/**
*
*/
private String description;
/**
*
*/
private String filePath;
/**
*
*/
private String rowNumber;
/**
*
*/
private String level;
/**
*
*/
private Date detectTime;
/**
*
*/
private String uuid;
private Integer ruleId;
}

@ -0,0 +1,24 @@
package net.educoder.ecsonar.model.dto;
import lombok.Data;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/10/17
* @Description:
*/
@Data
public class CodeDetailDTO {
/**
*
*/
private List<FileSourceDTO> codes;
/**
*
*/
private String example;
}

@ -0,0 +1,36 @@
package net.educoder.ecsonar.model.dto;
import lombok.Data;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
@Data
public class DegreeDTO {
private String levelStr = "A";
private Integer total = 0;
/**
*
*/
private Integer blocker = 0;
/**
*
*/
private Integer critical = 0;
/**
*
*/
private Integer major = 0;
/**
*
*/
private Integer minor = 0;
}

@ -0,0 +1,16 @@
package net.educoder.ecsonar.model.dto;
import lombok.Data;
/**
* @Author: youys
* @Date: 2022/9/27
* @Description:
*/
@Data
public class FileSourceDTO {
private Integer rowNumber;
private String code;
}

@ -0,0 +1,36 @@
package net.educoder.ecsonar.model.vo;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
@Data
public class AnalyseDetailListVO extends PageVO {
/**
*
* 1 bug
* 2
* 3
*/
private Integer type;
/**
*
* all
*/
private Integer degree;
@NotBlank(message = "作业id不能为空")
private String homeworkId;
@NotBlank(message = "学号不能为空")
private String studentNo;
}

@ -0,0 +1,21 @@
package net.educoder.ecsonar.model.vo;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
@Data
public class AnalyseDetailVO {
@NotBlank(message = "作业id不能为空")
private String homeworkId;
@NotBlank(message = "学号不能为空")
private String studentNo;
}

@ -0,0 +1,16 @@
package net.educoder.ecsonar.model.vo;
import lombok.Data;
/**
* @Author: youys
* @Date: 2022/9/27
* @Description:
*/
@Data
public class CodeDetailVO {
private String uuid;
private Integer ruleId;
}

@ -0,0 +1,16 @@
package net.educoder.ecsonar.model.vo;
import lombok.Data;
/**
* @Author: youys
* @Date: 2022/12/20
* @Description:
*/
@Data
public class PageVO {
private Integer currentPage = 1;
private Integer pageSize = 20;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,21 +1,23 @@
package net.educoder.ecsonar.services; package net.educoder.ecsonar.services;
import com.google.protobuf.InvalidProtocolBufferException;
import net.educoder.ecsonar.dao.*;
import net.educoder.ecsonar.enums.AnalyseTypeEnum;
import net.educoder.ecsonar.enums.DegreeEnum;
import net.educoder.ecsonar.exception.BusinessException; import net.educoder.ecsonar.exception.BusinessException;
import net.educoder.ecsonar.dao.TaskInfoDao; import net.educoder.ecsonar.model.*;
import net.educoder.ecsonar.dao.TaskInfoDetailDao;
import net.educoder.ecsonar.model.Metrics;
import net.educoder.ecsonar.model.RollPage;
import net.educoder.ecsonar.model.TaskInfo;
import net.educoder.ecsonar.model.TaskInfoDetail;
import net.educoder.ecsonar.model.api.Quality; import net.educoder.ecsonar.model.api.Quality;
import net.educoder.ecsonar.model.api.QualityInspect; import net.educoder.ecsonar.model.api.QualityInspect;
import net.educoder.ecsonar.model.api.QualityInspectIsCompleted; import net.educoder.ecsonar.model.api.QualityInspectIsCompleted;
import net.educoder.ecsonar.model.api.QualityInspectResultData; import net.educoder.ecsonar.model.api.QualityInspectResultData;
import net.educoder.ecsonar.model.vo.QualityInspectUserDataVO; import net.educoder.ecsonar.model.dto.*;
import net.educoder.ecsonar.model.vo.QualityInspectVO; import net.educoder.ecsonar.model.vo.*;
import net.educoder.ecsonar.protobuf.DbFileSources;
import net.educoder.ecsonar.protobuf.DbIssues;
import net.educoder.ecsonar.task.QualityInspectRunnable; import net.educoder.ecsonar.task.QualityInspectRunnable;
import net.educoder.ecsonar.utils.IdUtils; import net.educoder.ecsonar.utils.IdUtils;
import net.educoder.ecsonar.utils.SystemUtil; import net.educoder.ecsonar.utils.SystemUtil;
import net.educoder.ecsonar.utils.html.HtmlSourceDecorator;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -54,6 +56,15 @@ public class QualityInspectService {
@Autowired @Autowired
private ReportService reportService; private ReportService reportService;
@Autowired
private IssuesDao issuesDao;
@Autowired
private ProjectDao projectDao;
@Autowired
private FileSourceDao fileSourceDao;
@Autowired @Autowired
@Qualifier("sonarScannerPool") @Qualifier("sonarScannerPool")
@ -63,6 +74,8 @@ public class QualityInspectService {
@Qualifier("sonarQueryResultPool") @Qualifier("sonarQueryResultPool")
private ExecutorService sonarQueryResultPool; private ExecutorService sonarQueryResultPool;
private static final Logger logger = LoggerFactory.getLogger(QualityInspectService.class);
public QualityInspect qualityInspect(QualityInspectVO qualityInspectVO) { public QualityInspect qualityInspect(QualityInspectVO qualityInspectVO) {
@ -193,17 +206,167 @@ public class QualityInspectService {
// 100 -(阻断 * 10 + 严重 * 5 + 主要* 3 + 次要 * 1/ 总行数 * 100 // 100 -(阻断 * 10 + 严重 * 5 + 主要* 3 + 次要 * 1/ 总行数 * 100
Quality bug = resultData.getBug(); Quality bug = resultData.getBug();
BigDecimal bugScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(bug.getBlocker() * 10 + bug.getCritical() * 5 + bug.getMajor() * 3 + bug.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()),2,RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100))); BigDecimal bugScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(bug.getBlocker() * 10 + bug.getCritical() * 5 + bug.getMajor() * 3 + bug.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
Quality vulnerability = resultData.getVulnerability(); Quality vulnerability = resultData.getVulnerability();
BigDecimal vulnerabilityScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(vulnerability.getBlocker() * 10 + vulnerability.getCritical() * 5 + vulnerability.getMajor() * 3 + vulnerability.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()),2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100))); BigDecimal vulnerabilityScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(vulnerability.getBlocker() * 10 + vulnerability.getCritical() * 5 + vulnerability.getMajor() * 3 + vulnerability.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
Quality codeSmall = resultData.getCodeSmall(); Quality codeSmall = resultData.getCodeSmall();
BigDecimal codeSmallScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(codeSmall.getBlocker() * 10 + codeSmall.getCritical() * 5 + codeSmall.getMajor() * 3 + codeSmall.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()),2,RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100))); BigDecimal codeSmallScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(codeSmall.getBlocker() * 10 + codeSmall.getCritical() * 5 + codeSmall.getMajor() * 3 + codeSmall.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
// 总得分= bugScore * 0.5 + vulnerabilityScore * 0.3 + codeSmallScore * 0.2 // 总得分= bugScore * 0.5 + vulnerabilityScore * 0.3 + codeSmallScore * 0.2
BigDecimal score = bugScore.multiply(BigDecimal.valueOf(0.5)).add(vulnerabilityScore.multiply(BigDecimal.valueOf(0.3))).add(codeSmallScore.multiply(BigDecimal.valueOf(0.2))).setScale(2, RoundingMode.HALF_UP); BigDecimal score = bugScore.multiply(BigDecimal.valueOf(0.5)).add(vulnerabilityScore.multiply(BigDecimal.valueOf(0.3))).add(codeSmallScore.multiply(BigDecimal.valueOf(0.2))).setScale(2, RoundingMode.HALF_UP);
return score; return score;
} }
/**
*
*
* @param analyseDetailVO
* @return
*/
public AnalyseDetailDTO getAnalyseDetail(AnalyseDetailVO analyseDetailVO) {
// 作业id+学号
String projectName = String.format("%s-%s", analyseDetailVO.getHomeworkId(), analyseDetailVO.getStudentNo());
Project project = projectDao.findByName(projectName);
if (project == null) {
throw new BusinessException(-1, String.format("找不到分析记录homeworkId:%s,studentNo:%s", analyseDetailVO.getHomeworkId(), analyseDetailVO.getStudentNo()));
}
DegreeDTO codeSmall = issuesDao.queryDegree(project.getProject_uuid(), AnalyseTypeEnum.CodeSmell.getType());
DegreeDTO bug = issuesDao.queryDegree(project.getProject_uuid(), AnalyseTypeEnum.BUG.getType());
DegreeDTO vulnerability = issuesDao.queryDegree(project.getProject_uuid(), AnalyseTypeEnum.Vulnerability.getType());
AnalyseDetailDTO analyseDetail = new AnalyseDetailDTO();
analyseDetail.setBug(bug == null ? new DegreeDTO() : bug);
analyseDetail.setVulnerability(vulnerability == null ? new DegreeDTO() : vulnerability);
analyseDetail.setCodeSmall(codeSmall == null ? new DegreeDTO() : codeSmall);
return analyseDetail;
}
/**
*
*
* @param analyseDetailListVO
* @return
*/
public RollPage<AnalyseDetailListDTO> getAnalyseDetailList(AnalyseDetailListVO analyseDetailListVO) {
RollPage rollPage = new RollPage();
if (analyseDetailListVO.getCurrentPage() <= 0) {
analyseDetailListVO.setCurrentPage(1);
}
if (analyseDetailListVO.getPageSize() >= 10000) {
analyseDetailListVO.setPageSize(10000);
}
rollPage.setCurrentPage(analyseDetailListVO.getCurrentPage());
rollPage.setPageSize(analyseDetailListVO.getPageSize());
// 作业id+学号
String projectName = String.format("%s-%s", analyseDetailListVO.getHomeworkId(), analyseDetailListVO.getStudentNo());
Project project = projectDao.findByName(projectName);
if (project == null) {
throw new BusinessException(-1, "找不到分析记录");
}
// 分析类型
AnalyseTypeEnum analyseTypeEnum = AnalyseTypeEnum.getAnalyseTypeEnum(analyseDetailListVO.getType());
// 严重程度
DegreeEnum degreeEnum = DegreeEnum.getDegreeEnum(analyseDetailListVO.getDegree());
String severity = null;
if (degreeEnum != DegreeEnum.All) {
severity = degreeEnum.getValue();
}
Integer pageIssuesCount = issuesDao.getPageIssuesCount(project.getProject_uuid(), analyseTypeEnum.getType(), severity);
rollPage.setRecordSum(pageIssuesCount);
if (pageIssuesCount > 0) {
int start = (analyseDetailListVO.getCurrentPage() - 1) * analyseDetailListVO.getPageSize();
List<Issues> pageIssues = issuesDao.getPageIssues(project.getProject_uuid(), analyseTypeEnum.getType(), severity, start, analyseDetailListVO.getPageSize());
processPageIssues(pageIssues, rollPage);
} else {
rollPage.setRecordList(new ArrayList(0));
}
return rollPage;
}
public String getProblemAnalysis(Integer ruleId) {
Rule rule = projectDao.findRuleById(ruleId);
if (rule != null) {
String example = rule.getDescription().replaceAll("<p>", "<p style=\"color: #d50000;font-size: 17px;\">")
.replaceAll("Noncompliant Code Example", "错误代码示范")
.replaceAll("Compliant Solution", "正确代码示范")
.replaceAll("Exceptions", "异常代码")
.replaceAll("See", "链接");
return example;
}
return "";
}
/**
*
*
* @param codeDetailVO
* @return
*/
public CodeDetailDTO getCodeDetail(CodeDetailVO codeDetailVO) {
FileSource fileSource = fileSourceDao.findFileSourceFileUuid(codeDetailVO.getUuid());
DbFileSources.Data data = fileSource.decodeSourceData(fileSource.getBinaryData());
List<DbFileSources.Line> linesList = data.getLinesList();
List<FileSourceDTO> fileSourceDTOList = new ArrayList<>(linesList.size());
for (DbFileSources.Line line : linesList) {
FileSourceDTO fileSourceDTO = new FileSourceDTO();
fileSourceDTO.setRowNumber(line.getLine());
fileSourceDTO.setCode(HtmlSourceDecorator.getInstance().getDecoratedSourceAsHtml(line.getSource(), line.getHighlighting(), line.getSymbols()));
fileSourceDTOList.add(fileSourceDTO);
}
CodeDetailDTO codeDetail = new CodeDetailDTO();
codeDetail.setCodes(fileSourceDTOList);
codeDetail.setExample(getProblemAnalysis(codeDetailVO.getRuleId()));
return codeDetail;
}
private void processPageIssues(List<Issues> pageIssues, RollPage<AnalyseDetailListDTO> rollPage) {
List<AnalyseDetailListDTO> analyseDetailLists = new ArrayList<>(pageIssues.size());
for (Issues pageIssue : pageIssues) {
AnalyseDetailListDTO detailListDTO = new AnalyseDetailListDTO();
analyseDetailLists.add(detailListDTO);
detailListDTO.setName(pageIssue.getName());
detailListDTO.setDescription(pageIssue.getMessage());
detailListDTO.setUuid(pageIssue.getUuid());
detailListDTO.setRuleId(pageIssue.getRuleId());
detailListDTO.setFilePath(pageIssue.getPath());
try {
DbIssues.Locations locations = DbIssues.Locations.parseFrom(pageIssue.getLocations());
detailListDTO.setRowNumber(String.valueOf(locations.getTextRange().getStartLine()));
} catch (InvalidProtocolBufferException e) {
detailListDTO.setRowNumber("0");
logger.error("Fail to read ISSUES.LOCATIONS [KEE=%s]", e);
}
}
rollPage.setRecordList(analyseDetailLists);
}
} }

@ -0,0 +1,73 @@
/*
* SonarQube
* Copyright (C) 2009-2019 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* 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 02110-1301, USA.
*/
package net.educoder.ecsonar.utils.html;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
class CharactersReader {
static final int END_OF_STREAM = -1;
private final BufferedReader stringBuffer;
private final Deque<String> openTags;
private int currentValue;
private int previousValue;
private int currentIndex = -1;
public CharactersReader(BufferedReader stringBuffer) {
this.stringBuffer = stringBuffer;
this.openTags = new ArrayDeque<>();
}
boolean readNextChar() throws IOException {
previousValue = currentValue;
currentValue = stringBuffer.read();
currentIndex++;
return currentValue != END_OF_STREAM;
}
int getCurrentValue() {
return currentValue;
}
int getPreviousValue() {
return previousValue;
}
int getCurrentIndex() {
return currentIndex;
}
void registerOpenTag(String textType) {
openTags.push(textType);
}
void removeLastOpenTag() {
openTags.remove();
}
Deque<String> getOpenTags() {
return openTags;
}
}

@ -0,0 +1,133 @@
/*
* SonarQube
* Copyright (C) 2009-2019 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* 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 02110-1301, USA.
*/
package net.educoder.ecsonar.utils.html;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
class DecorationDataHolder {
private static final String ENTITY_SEPARATOR = ";";
private static final String FIELD_SEPARATOR = ",";
private static final String SYMBOL_PREFIX = "sym-";
private static final String HIGHLIGHTABLE = "sym";
private List<OpeningHtmlTag> openingTagsEntries;
private int openingTagsIndex;
private List<Integer> closingTagsOffsets;
private int closingTagsIndex;
DecorationDataHolder() {
openingTagsEntries = new ArrayList<>();
closingTagsOffsets = new ArrayList<>();
}
void loadSymbolReferences(String symbolsReferences) {
String[] symbols = symbolsReferences.split(ENTITY_SEPARATOR);
for (String symbol : symbols) {
String[] symbolFields = symbol.split(FIELD_SEPARATOR);
int declarationStartOffset = Integer.parseInt(symbolFields[0]);
int declarationEndOffset = Integer.parseInt(symbolFields[1]);
int symbolLength = declarationEndOffset - declarationStartOffset;
String[] symbolOccurrences = Arrays.copyOfRange(symbolFields, 2, symbolFields.length);
loadSymbolOccurrences(declarationStartOffset, symbolLength, symbolOccurrences);
}
}
void loadLineSymbolReferences(String symbolsReferences) {
String[] symbols = symbolsReferences.split(ENTITY_SEPARATOR);
for (String symbol : symbols) {
String[] symbolFields = symbol.split(FIELD_SEPARATOR);
int startOffset = Integer.parseInt(symbolFields[0]);
int endOffset = Integer.parseInt(symbolFields[1]);
int symbolLength = endOffset - startOffset;
int symbolId = Integer.parseInt(symbolFields[2]);
loadSymbolOccurrences(symbolId, symbolLength, new String[] { Integer.toString(startOffset) });
}
}
void loadSyntaxHighlightingData(String syntaxHighlightingRules) {
String[] rules = syntaxHighlightingRules.split(ENTITY_SEPARATOR);
for (String rule : rules) {
String[] ruleFields = rule.split(FIELD_SEPARATOR);
int startOffset = Integer.parseInt(ruleFields[0]);
int endOffset = Integer.parseInt(ruleFields[1]);
if (startOffset < endOffset) {
insertAndPreserveOrder(new OpeningHtmlTag(startOffset, ruleFields[2]), openingTagsEntries);
insertAndPreserveOrder(endOffset, closingTagsOffsets);
}
}
}
List<OpeningHtmlTag> getOpeningTagsEntries() {
return openingTagsEntries;
}
OpeningHtmlTag getCurrentOpeningTagEntry() {
return openingTagsIndex < openingTagsEntries.size() ? openingTagsEntries.get(openingTagsIndex) : null;
}
void nextOpeningTagEntry() {
openingTagsIndex++;
}
List<Integer> getClosingTagsOffsets() {
return closingTagsOffsets;
}
int getCurrentClosingTagOffset() {
return closingTagsIndex < closingTagsOffsets.size() ? closingTagsOffsets.get(closingTagsIndex) : -1;
}
void nextClosingTagOffset() {
closingTagsIndex++;
}
private void loadSymbolOccurrences(int declarationStartOffset, int symbolLength, String[] symbolOccurrences) {
for (String symbolOccurrence : symbolOccurrences) {
int occurrenceStartOffset = Integer.parseInt(symbolOccurrence);
int occurrenceEndOffset = occurrenceStartOffset + symbolLength;
insertAndPreserveOrder(new OpeningHtmlTag(occurrenceStartOffset, SYMBOL_PREFIX + declarationStartOffset + " " + HIGHLIGHTABLE), openingTagsEntries);
insertAndPreserveOrder(occurrenceEndOffset, closingTagsOffsets);
}
}
private void insertAndPreserveOrder(OpeningHtmlTag newEntry, List<OpeningHtmlTag> openingHtmlTags) {
int insertionIndex = 0;
Iterator<OpeningHtmlTag> tagIterator = openingHtmlTags.iterator();
while (tagIterator.hasNext() && tagIterator.next().getStartOffset() <= newEntry.getStartOffset()) {
insertionIndex++;
}
openingHtmlTags.add(insertionIndex, newEntry);
}
private void insertAndPreserveOrder(int newOffset, List<Integer> orderedOffsets) {
int insertionIndex = 0;
Iterator<Integer> entriesIterator = orderedOffsets.iterator();
while (entriesIterator.hasNext() && entriesIterator.next() <= newOffset) {
insertionIndex++;
}
orderedOffsets.add(insertionIndex, newOffset);
}
}

@ -0,0 +1,74 @@
/*
* SonarQube
* Copyright (C) 2009-2019 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* 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 02110-1301, USA.
*/
package net.educoder.ecsonar.utils.html;
import org.apache.commons.lang3.StringUtils;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
*
*/
public final class HtmlSourceDecorator {
private static volatile HtmlSourceDecorator htmlSourceDecorator = null;
private HtmlSourceDecorator() {
}
public static HtmlSourceDecorator getInstance() {
if (htmlSourceDecorator == null) {
synchronized (HtmlSourceDecorator.class) {
if (htmlSourceDecorator == null) {
htmlSourceDecorator = new HtmlSourceDecorator();
}
}
}
return htmlSourceDecorator;
}
public String getDecoratedSourceAsHtml(@NotNull String sourceLine, @NotNull String highlighting, @NotNull String symbols) {
if (sourceLine == null) {
return null;
}
DecorationDataHolder decorationDataHolder = new DecorationDataHolder();
if (StringUtils.isNotBlank(highlighting)) {
decorationDataHolder.loadSyntaxHighlightingData(highlighting);
}
if (StringUtils.isNotBlank(symbols)) {
decorationDataHolder.loadLineSymbolReferences(symbols);
}
HtmlTextDecorator textDecorator = new HtmlTextDecorator();
List<String> decoratedSource = textDecorator.decorateTextWithHtml(sourceLine, decorationDataHolder, 1, 1);
if (decoratedSource == null) {
return null;
} else {
if (decoratedSource.isEmpty()) {
return "";
} else {
return decoratedSource.get(0);
}
}
}
}

@ -0,0 +1,223 @@
/*
* SonarQube
* Copyright (C) 2009-2019 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* 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 02110-1301, USA.
*/
package net.educoder.ecsonar.utils.html;
import com.google.common.io.Closeables;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
@Slf4j
public class HtmlTextDecorator {
static final char CR_END_OF_LINE = '\r';
static final char LF_END_OF_LINE = '\n';
static final char HTML_OPENING = '<';
static final char HTML_CLOSING = '>';
static final char AMPERSAND = '&';
static final String ENCODED_HTML_OPENING = "&lt;";
static final String ENCODED_HTML_CLOSING = "&gt;";
static final String ENCODED_AMPERSAND = "&amp;";
List<String> decorateTextWithHtml(String text, DecorationDataHolder decorationDataHolder) {
return decorateTextWithHtml(text, decorationDataHolder, null, null);
}
List<String> decorateTextWithHtml(String text, DecorationDataHolder decorationDataHolder, @Nullable Integer from, @Nullable Integer to) {
StringBuilder currentHtmlLine = new StringBuilder();
List<String> decoratedHtmlLines = newArrayList();
int currentLine = 1;
BufferedReader stringBuffer = null;
try {
stringBuffer = new BufferedReader(new StringReader(text));
CharactersReader charsReader = new CharactersReader(stringBuffer);
while (charsReader.readNextChar()) {
if (shouldStop(currentLine, to)) {
break;
}
if (shouldStartNewLine(charsReader)) {
if (canAddLine(currentLine, from)) {
decoratedHtmlLines.add(currentHtmlLine.toString());
}
currentLine++;
currentHtmlLine = new StringBuilder();
}
addCharToCurrentLine(charsReader, currentHtmlLine, decorationDataHolder);
}
closeCurrentSyntaxTags(charsReader, currentHtmlLine);
if (shouldStartNewLine(charsReader)) {
addLine(decoratedHtmlLines, currentHtmlLine.toString(), currentLine, from, to);
currentLine++;
addLine(decoratedHtmlLines, "", currentLine, from, to);
} else if (currentHtmlLine.length() > 0) {
addLine(decoratedHtmlLines, currentHtmlLine.toString(), currentLine, from, to);
}
} catch (IOException exception) {
String errorMsg = "An exception occurred while highlighting the syntax of one of the project's files";
log.error(errorMsg);
throw new IllegalStateException(errorMsg, exception);
} finally {
Closeables.closeQuietly(stringBuffer);
}
return decoratedHtmlLines;
}
private void addCharToCurrentLine(CharactersReader charsReader, StringBuilder currentHtmlLine, DecorationDataHolder decorationDataHolder) {
if (shouldStartNewLine(charsReader)) {
if (shouldReopenPendingTags(charsReader)) {
reopenCurrentSyntaxTags(charsReader, currentHtmlLine);
}
}
int numberOfTagsToClose = getNumberOfTagsToClose(charsReader.getCurrentIndex(), decorationDataHolder);
closeCompletedTags(charsReader, numberOfTagsToClose, currentHtmlLine);
if (shouldClosePendingTags(charsReader)) {
closeCurrentSyntaxTags(charsReader, currentHtmlLine);
}
Collection<String> tagsToOpen = getTagsToOpen(charsReader.getCurrentIndex(), decorationDataHolder);
openNewTags(charsReader, tagsToOpen, currentHtmlLine);
if (shouldAppendCharToHtmlOutput(charsReader)) {
char currentChar = (char) charsReader.getCurrentValue();
currentHtmlLine.append(normalize(currentChar));
}
}
private static void addLine(List<String> decoratedHtmlLines, String line, int currentLine, @Nullable Integer from, @Nullable Integer to) {
if (canAddLine(currentLine, from) && !shouldStop(currentLine, to)) {
decoratedHtmlLines.add(line);
}
}
private static boolean canAddLine(int currentLine, @Nullable Integer from) {
return from == null || currentLine >= from;
}
private static boolean shouldStop(int currentLine, @Nullable Integer to) {
return to != null && to < currentLine;
}
private char[] normalize(char currentChar) {
char[] normalizedChars;
if (currentChar == HTML_OPENING) {
normalizedChars = ENCODED_HTML_OPENING.toCharArray();
} else if (currentChar == HTML_CLOSING) {
normalizedChars = ENCODED_HTML_CLOSING.toCharArray();
} else if (currentChar == AMPERSAND) {
normalizedChars = ENCODED_AMPERSAND.toCharArray();
} else {
normalizedChars = new char[] {currentChar};
}
return normalizedChars;
}
private boolean shouldAppendCharToHtmlOutput(CharactersReader charsReader) {
return charsReader.getCurrentValue() != CR_END_OF_LINE && charsReader.getCurrentValue() != LF_END_OF_LINE;
}
private int getNumberOfTagsToClose(int currentIndex, DecorationDataHolder dataHolder) {
int numberOfTagsToClose = 0;
while (currentIndex == dataHolder.getCurrentClosingTagOffset()) {
numberOfTagsToClose++;
dataHolder.nextClosingTagOffset();
}
return numberOfTagsToClose;
}
private Collection<String> getTagsToOpen(int currentIndex, DecorationDataHolder dataHolder) {
Collection<String> tagsToOpen = newArrayList();
while (dataHolder.getCurrentOpeningTagEntry() != null && currentIndex == dataHolder.getCurrentOpeningTagEntry().getStartOffset()) {
tagsToOpen.add(dataHolder.getCurrentOpeningTagEntry().getCssClass());
dataHolder.nextOpeningTagEntry();
}
return tagsToOpen;
}
private boolean shouldClosePendingTags(CharactersReader charactersReader) {
return charactersReader.getCurrentValue() == CR_END_OF_LINE
|| (charactersReader.getCurrentValue() == LF_END_OF_LINE && charactersReader.getPreviousValue() != CR_END_OF_LINE)
|| (charactersReader.getCurrentValue() == CharactersReader.END_OF_STREAM && charactersReader.getPreviousValue() != LF_END_OF_LINE);
}
private boolean shouldReopenPendingTags(CharactersReader charactersReader) {
return (charactersReader.getPreviousValue() == LF_END_OF_LINE && charactersReader.getCurrentValue() != LF_END_OF_LINE)
|| (charactersReader.getPreviousValue() == CR_END_OF_LINE && charactersReader.getCurrentValue() != CR_END_OF_LINE
&& charactersReader.getCurrentValue() != LF_END_OF_LINE);
}
private boolean shouldStartNewLine(CharactersReader charactersReader) {
return charactersReader.getPreviousValue() == LF_END_OF_LINE
|| (charactersReader.getPreviousValue() == CR_END_OF_LINE && charactersReader.getCurrentValue() != LF_END_OF_LINE);
}
private void closeCompletedTags(CharactersReader charactersReader, int numberOfTagsToClose,
StringBuilder decoratedText) {
for (int i = 0; i < numberOfTagsToClose; i++) {
injectClosingHtml(decoratedText);
charactersReader.removeLastOpenTag();
}
}
private void openNewTags(CharactersReader charactersReader, Collection<String> tagsToOpen,
StringBuilder decoratedText) {
for (String tagToOpen : tagsToOpen) {
injectOpeningHtmlForRule(tagToOpen, decoratedText);
charactersReader.registerOpenTag(tagToOpen);
}
}
private void closeCurrentSyntaxTags(CharactersReader charactersReader, StringBuilder decoratedText) {
for (int i = 0; i < charactersReader.getOpenTags().size(); i++) {
injectClosingHtml(decoratedText);
}
}
private void reopenCurrentSyntaxTags(CharactersReader charactersReader, StringBuilder decoratedText) {
for (String tags : charactersReader.getOpenTags()) {
injectOpeningHtmlForRule(tags, decoratedText);
}
}
private void injectOpeningHtmlForRule(String textType, StringBuilder decoratedText) {
decoratedText.append("<span class=\"").append(textType).append("\">");
}
private void injectClosingHtml(StringBuilder decoratedText) {
decoratedText.append("</span>");
}
}

@ -0,0 +1,64 @@
/*
* SonarQube
* Copyright (C) 2009-2019 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* 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 02110-1301, USA.
*/
package net.educoder.ecsonar.utils.html;
class OpeningHtmlTag {
private final int startOffset;
private final String cssClass;
OpeningHtmlTag(int startOffset, String cssClass) {
this.startOffset = startOffset;
this.cssClass = cssClass;
}
int getStartOffset() {
return startOffset;
}
String getCssClass() {
return cssClass;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
return compareTo((OpeningHtmlTag) o);
}
@Override
public int hashCode() {
int result = startOffset;
result = 31 * result + (cssClass != null ? cssClass.hashCode() : 0);
return result;
}
private boolean compareTo(OpeningHtmlTag otherTag) {
if (startOffset != otherTag.startOffset) {
return false;
}
return (cssClass != null) ? cssClass.equals(otherTag.cssClass) : (otherTag.cssClass == null);
}
}

@ -5,10 +5,10 @@
#spring.datasource.driver-class-name=org.postgresql.Driver #spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.initSize=20 spring.datasource.initSize=20
spring.datasource.master.url=jdbc:postgresql://127.0.0.1:5432/sonar7.7 #spring.datasource.master.url=jdbc:postgresql://127.0.0.1:5432/sonar7.7
#spring.datasource.url=jdbc:postgresql://117.50.14.123:5432/sonar spring.datasource.master.url=jdbc:postgresql://117.50.14.123:5432/sonar
spring.datasource.master.username=root spring.datasource.master.username=sonar
spring.datasource.master.password=root spring.datasource.master.password=sonar
spring.datasource.master.driverClassName=org.postgresql.Driver spring.datasource.master.driverClassName=org.postgresql.Driver
@ -57,5 +57,6 @@ skip.checked=true
server.port=8081 server.port=8081
mybatis.mapper-locations=classpath:mapper/*
sonar.host=http://localhost:9000 sonar.host=http://localhost:9000

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.educoder.ecsonar.dao.FileSourceDao">
<select id="findFileSourceFileUuid" parameterType="java.lang.String" resultType="net.educoder.ecsonar.model.FileSource">
select
id,
project_uuid as projectUuid,
file_uuid as fileUuid,
binary_data as binaryData,
line_hashes as lineHashes,
data_hash as dataHash,
src_hash as srcHash
from file_sources where file_uuid=#{fileUuid,jdbcType=VARCHAR}
</select>
</mapper>

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.educoder.ecsonar.dao.IssuesDao">
<select id="getPageIssuesCount" resultType="java.lang.Integer">
select
count(1)
from issues i
inner join rules r on i.rule_id =r.id
inner join projects p on p.uuid =i.component_uuid
where i.project_uuid = #{projectUuid,jdbcType=VARCHAR}
and p.root_uuid =#{projectUuid,jdbcType=VARCHAR} and p.uuid !=#{projectUuid,jdbcType=VARCHAR} and p."scope" ='FIL'
<if test="issueType != null">
and i.issue_type=#{issueType,jdbcType=INTEGER}
</if>
<if test="severity != null">
and i.severity=#{severity,jdbcType=VARCHAR}
</if>
</select>
<select id="getPageIssues" resultType="net.educoder.ecsonar.model.Issues">
select
i.id,i.kee,i.rule_id ruleId,i.severity,i.status,i.project_uuid projectUuid,i.issue_type issueType,i.locations,r.name,r.description,p.path,p.uuid,i.message
from issues i
inner join rules r on i.rule_id =r.id
inner join projects p on p.uuid =i.component_uuid
where i.project_uuid = #{projectUuid,jdbcType=VARCHAR}
and p.root_uuid =#{projectUuid,jdbcType=VARCHAR} and p.uuid !=#{projectUuid,jdbcType=VARCHAR} and p."scope" ='FIL'
<if test="issueType != null">
and i.issue_type=#{issueType,jdbcType=INTEGER}
</if>
<if test="severity != null">
and i.severity=#{severity,jdbcType=VARCHAR}
</if>
limit #{pageSize} offset #{start}
</select>
<select id="queryDegree" resultType="net.educoder.ecsonar.model.dto.DegreeDTO">
select
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType}) total,
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'MAJOR') major,
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'MINOR') minor,
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'BLOCKER') blocker,
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'CRITICAL') critical,
(select text_value from project_measures i where component_uuid =#{projectUuid} and metric_id = 80 order by id desc limit 1) levelStr
</select>
</mapper>

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.educoder.ecsonar.dao.ProjectDao">
<select id="findRuleById" parameterType="java.lang.Integer" resultType="net.educoder.ecsonar.model.Rule">
select
id,
name,
description
from rules where id=#{id,jdbcType=INTEGER}
</select>
</mapper>

@ -0,0 +1,41 @@
// SonarQube, open source software quality management tool.
// Copyright (C) 2008-2016 SonarSource
// mailto:contact AT sonarsource DOT com
//
// SonarQube 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.
//
// SonarQube 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 02110-1301, USA.
syntax = "proto2";
package sonarqube.db.commons;
// The java package can be changed without breaking compatibility.
// it impacts only the generated Java code.
option java_package = "net.educoder.quality.protobuf";
option optimize_for = SPEED;
// Lines start at 1 and line offsets start at 0
message TextRange {
// Start line. Should never be absent
optional int32 start_line = 1;
// End line (inclusive). Absent means it is same as start line
optional int32 end_line = 2;
// If absent it means range starts at the first offset of start line
optional int32 start_offset = 3;
// If absent it means range ends at the last offset of end line
optional int32 end_offset = 4;
}

@ -0,0 +1,76 @@
/*
SonarQube, open source software quality management tool.
Copyright (C) 2008-2016 SonarSource
mailto:contact AT sonarsource DOT com
SonarQube 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.
SonarQube 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 02110-1301, USA.
*/
// Structure of db column FILE_SOURCES.BINARY_DATA
syntax = "proto2";
// Package must not be changed for backward-compatibility
// with the DB rows inserted in DB before 5.2
package org.sonar.server.source.db;
// The java package can be changed without breaking compatibility.
// it impacts only the generated Java code.
option java_package = "net.educoder.quality.protobuf";
option optimize_for = SPEED;
message Line {
optional int32 line = 1;
optional string source = 2;
// SCM
optional string scm_revision = 3;
optional string scm_author = 4;
optional int64 scm_date = 5;
// Deprecated fields in 6.2 (has been deprecated when merging coverage into a single metric)
// They are still used to read coverage info from sources that have not be re-analyzed
optional int32 deprecated_ut_line_hits = 6;
optional int32 deprecated_ut_conditions = 7;
optional int32 deprecated_ut_covered_conditions = 8;
optional int32 deprecated_it_line_hits = 9;
optional int32 deprecated_it_conditions = 10;
optional int32 deprecated_it_covered_conditions = 11;
optional int32 deprecated_overall_line_hits = 12;
optional int32 deprecated_overall_conditions = 13;
optional int32 deprecated_overall_covered_conditions = 14;
optional string highlighting = 15;
optional string symbols = 16;
repeated int32 duplication = 17 [packed = true];
// coverage info (since 6.2)
optional int32 line_hits = 18;
optional int32 conditions = 19;
optional int32 covered_conditions = 20;
optional bool is_new_line = 21;
}
message Range {
optional int32 startOffset = 1;
optional int32 endOffset = 2;
}
// TODO should be dropped as it prevents streaming
message Data {
repeated Line lines = 1;
}

@ -0,0 +1,47 @@
// SonarQube, open source software quality management tool.
// Copyright (C) 2008-2016 SonarSource
// mailto:contact AT sonarsource DOT com
//
// SonarQube 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.
//
// SonarQube 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 02110-1301, USA.
// Structure of table ISSUES
syntax = "proto2";
package sonarqube.db.issues;
import "db-commons.proto";
// The java package can be changed without breaking compatibility.
// it impacts only the generated Java code.
option java_package = "net.educoder.quality.protobuf";
option optimize_for = SPEED;
message Locations {
optional sonarqube.db.commons.TextRange text_range = 1;
repeated Flow flow = 2;
}
message Flow {
repeated Location location = 1;
}
message Location {
optional string component_id = 1;
// Only when component is a file. Can be empty for a file if this is an issue global to the file.
optional sonarqube.db.commons.TextRange text_range = 2;
optional string msg = 3;
}

@ -0,0 +1,40 @@
/*
SonarQube, open source software quality management tool.
Copyright (C) 2008-2016 SonarSource
mailto:contact AT sonarsource DOT com
SonarQube 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.
SonarQube 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 02110-1301, USA.
*/
// Structure of db column PROJECT_BRANCHES.PULL_REQUEST_DATA
syntax = "proto3";
package sonarqube.db.project_branches;
// The java package can be changed without breaking compatibility.
// it impacts only the generated Java code.
option java_package = "net.educoder.quality.protobuf";
option optimize_for = SPEED;
message PullRequestData {
string branch = 1;
string title = 2;
string url = 3;
map<string, string> attributes = 4;
string target = 5;
}
Loading…
Cancel
Save