Source file src/cmd/compile/internal/syntax/testing.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file implements testing support.
     6  
     7  package syntax
     8  
     9  import (
    10  	"io"
    11  	"regexp"
    12  	"strings"
    13  )
    14  
    15  // CommentsDo parses the given source and calls the provided handler for each
    16  // comment or error. If the text provided to handler starts with a '/' it is
    17  // the comment text; otherwise it is the error message.
    18  func CommentsDo(src io.Reader, handler func(line, col uint, text string)) {
    19  	var s scanner
    20  	s.init(src, handler, comments)
    21  	for s.tok != _EOF {
    22  		s.next()
    23  	}
    24  }
    25  
    26  // ERROR comments must start with text `ERROR "msg"` or `ERROR msg`.
    27  // Space around "msg" or msg is ignored.
    28  var errRx = regexp.MustCompile(`^ *ERROR *"?([^"]*)"?`)
    29  
    30  // ErrorMap collects all comments with comment text of the form
    31  // `ERROR "msg"` or `ERROR msg` from the given src and returns them
    32  // as []Error lists in a map indexed by line number. The position
    33  // for each Error is the position of the token immediately preceding
    34  // the comment, the Error message is the message msg extracted from
    35  // the comment, with all errors that are on the same line collected
    36  // in a slice, in source order. If there is no preceding token (the
    37  // `ERROR` comment appears in the beginning of the file), then the
    38  // recorded position is unknown (line, col = 0, 0). If there are no
    39  // ERROR comments, the result is nil.
    40  func ErrorMap(src io.Reader) (errmap map[uint][]Error) {
    41  	// position of previous token
    42  	var base *PosBase
    43  	var prev struct{ line, col uint }
    44  
    45  	var s scanner
    46  	s.init(src, func(_, _ uint, text string) {
    47  		if text[0] != '/' {
    48  			return // error, ignore
    49  		}
    50  		if text[1] == '*' {
    51  			text = text[:len(text)-2] // strip trailing */
    52  		}
    53  		if s := errRx.FindStringSubmatch(text[2:]); len(s) == 2 {
    54  			pos := MakePos(base, prev.line, prev.col)
    55  			err := Error{pos, strings.TrimSpace(s[1])}
    56  			if errmap == nil {
    57  				errmap = make(map[uint][]Error)
    58  			}
    59  			errmap[prev.line] = append(errmap[prev.line], err)
    60  		}
    61  	}, comments)
    62  
    63  	for s.tok != _EOF {
    64  		s.next()
    65  		if s.tok == _Semi && s.lit != "semicolon" {
    66  			continue // ignore automatically inserted semicolons
    67  		}
    68  		prev.line, prev.col = s.line, s.col
    69  	}
    70  
    71  	return
    72  }
    73  

View as plain text