From cd6fb7d699033dbe9e880ff755a8de5f60fdc324 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 31 Mar 2021 00:03:32 -0700 Subject: [PATCH] Extract files for error locations Co-authored-by: Chris Smowton --- extractor/extractor.go | 34 ++++++++++++++++++++++++++-------- extractor/trap/labels.go | 6 +++--- ql/src/semmle/go/Files.qll | 15 ++++++++++++++- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/extractor/extractor.go b/extractor/extractor.go index 6995046ff12..2697d4ae7cc 100644 --- a/extractor/extractor.go +++ b/extractor/extractor.go @@ -236,6 +236,11 @@ type FileInfo struct { NextErr int } +func (extraction *Extraction) SeenFile(path string) bool { + _, ok := extraction.FileInfo[path] + return ok +} + func (extraction *Extraction) GetFileInfo(path string) *FileInfo { if fileInfo, ok := extraction.FileInfo[path]; ok { return fileInfo @@ -487,13 +492,15 @@ func (extraction *Extraction) extractError(tw *trap.Writer, err packages.Error, } transformed := filepath.ToSlash(srcarchive.TransformPath(ffile)) + extraction.extractFileInfo(tw, ffile) + extraction.Lock.Lock() + diagLbl := extraction.StatWriter.Labeler.FreshID() - dbscheme.DiagnosticsTable.Emit(extraction.StatWriter, diagLbl, 1, tag, err.Msg, err.Msg, - emitLocation( - extraction.StatWriter, extraction.StatWriter.Labeler.GlobalID(ffile+";sourcefile"), - line, col, line, col, - )) + flbl := extraction.StatWriter.Labeler.FileLabelFor(ffile) + dbscheme.DiagnosticsTable.Emit( + extraction.StatWriter, diagLbl, 1, tag, err.Msg, err.Msg, + emitLocation(extraction.StatWriter, flbl, line, col, line, col)) dbscheme.DiagnosticForTable.Emit(extraction.StatWriter, diagLbl, extraction.Label, extraction.GetFileIdx(transformed), extraction.GetNextErr(transformed)) extraction.Lock.Unlock() dbscheme.ErrorsTable.Emit(tw, lbl, kind, err.Msg, pos, transformed, line, col, pkglbl, idx) @@ -585,6 +592,16 @@ func (extraction *Extraction) extractFileInfo(tw *trap.Writer, file string) { components := strings.Split(path, "/") parentPath := "" var parentLbl trap.Label + + // We may visit the same file twice because `extractError` calls this function to describe files containing + // compilation errors. It is also called for user source files being extracted. + extraction.Lock.Lock() + if extraction.SeenFile(path) { + extraction.Lock.Unlock() + return + } + extraction.Lock.Unlock() + for i, component := range components { if i == 0 { if component == "" { @@ -597,12 +614,13 @@ func (extraction *Extraction) extractFileInfo(tw *trap.Writer, file string) { } if i == len(components)-1 { stem, ext := stemAndExt(component) - lbl := tw.Labeler.FileLabel() + lbl := tw.Labeler.FileLabelFor(path) dbscheme.FilesTable.Emit(tw, lbl, path, stem, ext, 0) dbscheme.ContainerParentTable.Emit(tw, parentLbl, lbl) - extractLocation(tw, lbl, 0, 0, 0, 0) + dbscheme.HasLocationTable.Emit(tw, lbl, emitLocation(tw, lbl, 0, 0, 0, 0)) extraction.Lock.Lock() - dbscheme.CompilationCompilingFilesTable.Emit(extraction.StatWriter, extraction.Label, extraction.GetFileIdx(path), extraction.StatWriter.Labeler.FileLabelFor(tw)) + slbl := extraction.StatWriter.Labeler.FileLabelFor(path) + dbscheme.CompilationCompilingFilesTable.Emit(extraction.StatWriter, extraction.Label, extraction.GetFileIdx(path), slbl) extraction.Lock.Unlock() break } diff --git a/extractor/trap/labels.go b/extractor/trap/labels.go index bbbb6dfb73d..48e7d919bd9 100644 --- a/extractor/trap/labels.go +++ b/extractor/trap/labels.go @@ -62,7 +62,7 @@ func (l *Labeler) GlobalID(key string) Label { return label } -// FileLabel returns the label for the file with which the trap writer is associated +// FileLabel returns the label for a file with path `path`. func (l *Labeler) FileLabel() Label { if l.fileLabel == InvalidLabel { l.fileLabel = l.GlobalID(l.tw.path + ";sourcefile") @@ -71,8 +71,8 @@ func (l *Labeler) FileLabel() Label { } // FileLabelFor returns the label for the file for which the trap writer `tw` is associated -func (l *Labeler) FileLabelFor(tw *Writer) Label { - return l.GlobalID(tw.path + ";sourcefile") +func (l *Labeler) FileLabelFor(path string) Label { + return l.GlobalID(path + ";sourcefile") } // LocalID associates a label with the given AST node `nd` and returns it diff --git a/ql/src/semmle/go/Files.qll b/ql/src/semmle/go/Files.qll index 7bf684cb9c7..73c30605ff9 100644 --- a/ql/src/semmle/go/Files.qll +++ b/ql/src/semmle/go/Files.qll @@ -180,9 +180,22 @@ class Folder extends Container, @folder { /** A file. */ class File extends Container, @file, Documentable, ExprParent, GoModExprParent, DeclParent, ScopeNode { + string path; + + File() { + files(this, path, _, _, _) and + ( + // Exclude `.go` files that have not been extracted. Non-extracted files only exist in the `files` + // table if we are reporting compilation errors relating to them in the `diagnostics` table. + not path.matches("%.go") + or + exists(this.getAChild()) + ) + } + override Location getLocation() { has_location(this, result) } - override string getAbsolutePath() { files(this, result, _, _, _) } + override string getAbsolutePath() { result = path } /** Gets the number of lines in this file. */ int getNumberOfLines() { numlines(this, result, _, _) }