Skip to content

Commit

Permalink
Scanning imported pacakges for annotations.
Browse files Browse the repository at this point in the history
  • Loading branch information
victornicolet committed Oct 28, 2024
1 parent 7dbdcfd commit 03f495c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 12 deletions.
19 changes: 10 additions & 9 deletions analysis/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,19 +211,20 @@ func (pa ProgramAnnotations) Iter(fx func(a Annotation)) {
for _, cst := range pa.Globals {
funcutil.Iter(cst, fx)
}
for _, cst := range pa.Positional {
fx(cst)
}
}

// CompleteFromSyntax takes a set of program annotations and adds additional non-ssa linked annotations
// to the annotations
func (pa ProgramAnnotations) CompleteFromSyntax(logger *config.LogGroup, pkgs []*packages.Package) {
for _, pkg := range pkgs {
for _, astFile := range pkg.Syntax {
pa.loadPackageDocAnnotations(astFile.Doc)
for _, comments := range astFile.Comments {
for _, comment := range comments.List {
if annotationContents := extractAnnotation(comment); annotationContents != nil {
pa.loadFileAnnotations(logger, annotationContents, pkg.Fset.Position(comment.Pos()))
}
func (pa ProgramAnnotations) CompleteFromSyntax(logger *config.LogGroup, pkg *packages.Package) {
for _, astFile := range pkg.Syntax {
pa.loadPackageDocAnnotations(astFile.Doc)
for _, comments := range astFile.Comments {
for _, comment := range comments.List {
if annotationContents := extractAnnotation(comment); annotationContents != nil {
pa.loadFileAnnotations(logger, annotationContents, pkg.Fset.Position(comment.Pos()))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion analysis/annotations/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestLoadAnnotations(t *testing.T) {
testProgram.Prog.Build()
logger := config.NewLogGroup(testProgram.Config)
a, err := annotations.LoadAnnotations(logger, testProgram.Prog.AllPackages())
a.CompleteFromSyntax(logger, testProgram.Pkgs)
a.CompleteFromSyntax(logger, testProgram.Pkgs[0])
if err != nil {
t.Errorf("error loading annotations: %s", err)
}
Expand Down
18 changes: 16 additions & 2 deletions analysis/dataflow/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/awslabs/ar-go-tools/analysis/config"
"github.com/awslabs/ar-go-tools/analysis/lang"
"github.com/awslabs/ar-go-tools/analysis/summaries"
"github.com/awslabs/ar-go-tools/internal/analysisutil"
"github.com/awslabs/ar-go-tools/internal/pointer"
"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/callgraph/cha"
Expand Down Expand Up @@ -120,10 +121,23 @@ func NewAnalyzerState(p *ssa.Program, pkgs []*packages.Package, l *config.LogGro
steps []func(*AnalyzerState)) (*AnalyzerState, error) {
var allContracts []Contract

// Load annotations
// Load annotations by scanning all packages' syntax
pa, err := annotations.LoadAnnotations(l, p.AllPackages())

if pkgs != nil {
pa.CompleteFromSyntax(l, pkgs)
for _, pkg := range pkgs {
analysisutil.VisitPackages(pkg, func(p *packages.Package) bool {
// Don't scan stdlib for annotations!
if summaries.IsStdPackageName(p.Name) {
return false
}
// TODO: find a way to not scan dependencies if there is demand. Currently, it is unlikely that some
// dependencies will contain argot annotations.
l.Debugf("Scan %s for annotations.\n", p.PkgPath)
pa.CompleteFromSyntax(l, p)
return true
})
}
}

if err != nil {
Expand Down
39 changes: 39 additions & 0 deletions internal/analysisutil/iterators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// 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 analysisutil

import (
"golang.org/x/tools/go/packages"
)

// VisitPackages calls f recursively on the root package provided, and then all the imports provided f returns
// true for that package. If f returns false, the imports will not be visited.
func VisitPackages(root *packages.Package, f func(p *packages.Package) bool) {
seen := map[*packages.Package]bool{}
queue := []*packages.Package{root}
for len(queue) > 0 {
cur := queue[0]
queue = queue[1:]
if seen[cur] {
continue
}
if f(cur) {
for _, importedPkg := range cur.Imports {
queue = append(queue, importedPkg)
}
}
seen[cur] = true
}
}

0 comments on commit 03f495c

Please sign in to comment.