/* * Copyright 2013-2016 Sergey Ignatov, Alexander Zolotov, Florin Patan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.goide.runconfig.testing.coverage; import com.goide.GoConstants; import com.goide.sdk.GoPackageUtil; import com.intellij.coverage.BaseCoverageSuite; import com.intellij.coverage.CoverageEngine; import com.intellij.coverage.CoverageRunner; import com.intellij.coverage.CoverageSuite; import com.intellij.execution.configurations.ModuleBasedConfiguration; import com.intellij.execution.configurations.RunConfigurationBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.rt.coverage.data.ClassData; import com.intellij.rt.coverage.data.LineData; import com.intellij.rt.coverage.data.ProjectData; import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.*; import java.util.List; public class GoCoverageRunner extends CoverageRunner { private static final Logger LOG = Logger.getInstance(GoCoverageRunner.class); private static final String ID = "GoCoverage"; private static final String DATA_FILE_EXTENSION = "out"; private static final String PRESENTABLE_NAME = GoConstants.GO; @Override public ProjectData loadCoverageData(@NotNull File sessionDataFile, @Nullable CoverageSuite baseCoverageSuite) { if (!(baseCoverageSuite instanceof BaseCoverageSuite)) { return null; } Project project = baseCoverageSuite.getProject(); if (project == null) { return null; } RunConfigurationBase configuration = ((BaseCoverageSuite)baseCoverageSuite).getConfiguration(); Module module = configuration instanceof ModuleBasedConfiguration ? ((ModuleBasedConfiguration)configuration).getConfigurationModule().getModule() : null; try { BufferedReader reader = new BufferedReader(new FileReader(sessionDataFile.getAbsolutePath())); try { return parseCoverage(reader, project, module); } catch (IOException e) { LOG.warn(e); } finally { try { reader.close(); } catch (IOException e) { LOG.warn(e); } } } catch (FileNotFoundException e) { LOG.warn(e); } return null; } @Nullable public static GoCoverageProjectData parseCoverage(@NotNull BufferedReader dataReader, @NotNull Project project, @Nullable Module module) throws IOException { GoCoverageProjectData result = new GoCoverageProjectData(); String line; while ((line = dataReader.readLine()) != null) { if (line.isEmpty()) continue; List<String> fileNameTail = StringUtil.split(line, ":"); VirtualFile file = GoPackageUtil.findByImportPath(fileNameTail.get(0), project, module); if (file == null) continue; String filePath = file.getPath(); List<String> tailParts = StringUtil.split(fileNameTail.get(1), " "); if (tailParts.size() != 3) continue; int statements = Integer.parseInt(tailParts.get(1)); int hit = Integer.parseInt(tailParts.get(2)); String offsets = tailParts.get(0); int firstDot = offsets.indexOf('.'); int comma = offsets.indexOf(',', firstDot); int secondDot = offsets.indexOf('.', comma); if (firstDot == -1 || comma == -1 || secondDot == -1) continue; int lineStart = Integer.parseInt(offsets.substring(0, firstDot)); int columnStart = Integer.parseInt(offsets.substring(firstDot + 1, comma)); int lineEnd = Integer.parseInt(offsets.substring(comma + 1, secondDot)); int columnEnd = Integer.parseInt(offsets.substring(secondDot + 1)); result.addData(filePath, lineStart, columnStart, lineEnd, columnEnd, statements, hit); } result.processFiles(fileData -> { ClassData classData = result.getOrCreateClassData(fileData.myFilePath); int max = -1; TIntObjectHashMap<LineData> linesMap = new TIntObjectHashMap<>(); for (GoCoverageProjectData.RangeData rangeData : fileData.myRangesData.values()) { for (int i = rangeData.startLine; i <= rangeData.endLine; i++) { LineData existingData = linesMap.get(i); if (existingData != null) { existingData.setHits(existingData.getHits() + rangeData.hits); // emulate partial existingData.setFalseHits(0, 0); existingData.setTrueHits(0, 0); } else { LineData newData = new LineData(i, null); newData.setHits(newData.getHits() + rangeData.hits); linesMap.put(i, newData); } } max = Math.max(max, rangeData.endLine); } LineData[] linesArray = new LineData[max + 1]; linesMap.forEachValue(data -> { data.fillArrays(); linesArray[data.getLineNumber()] = data; return true; }); classData.setLines(linesArray); return true; }); return result; } @Override public String getPresentableName() { return PRESENTABLE_NAME; } @Override public String getId() { return ID; } @Override public String getDataFileExtension() { return DATA_FILE_EXTENSION; } @Override public boolean acceptsCoverageEngine(@NotNull CoverageEngine engine) { return engine instanceof GoCoverageEngine; } }