fmt: keep newlines between toplevel stmts (#8383)

pull/8410/head
Lukas Neubert 2021-01-29 11:17:59 +01:00 committed by GitHub
parent afddcda7a3
commit e47c13903b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 84 additions and 26 deletions

View File

@ -61,14 +61,10 @@ pub fn fmt(file ast.File, table &table.Table, is_debug bool) string {
} }
f.process_file_imports(file) f.process_file_imports(file)
f.set_current_module_name('main') f.set_current_module_name('main')
for stmt in file.stmts { // As these are toplevel stmts, the indent increase done in f.stmts() has to be compensated
if stmt is ast.Import { f.indent--
// Just remember the position of the imports for now f.stmts(file.stmts)
f.import_pos = f.out.len f.indent++
// f.imports(f.file.imports)
}
f.stmt(stmt)
}
// for comment in file.comments { println('$comment.line_nr $comment.text') } // for comment in file.comments { println('$comment.line_nr $comment.text') }
f.imports(f.file.imports) // now that we have all autoimports, handle them f.imports(f.file.imports) // now that we have all autoimports, handle them
res := f.out.str().trim_space() + '\n' res := f.out.str().trim_space() + '\n'
@ -271,20 +267,39 @@ pub fn (f Fmt) imp_stmt_str(imp ast.Import) string {
return '$imp.mod$imp_alias_suffix' return '$imp.mod$imp_alias_suffix'
} }
pub fn (mut f Fmt) stmts(stmts []ast.Stmt) { fn (mut f Fmt) should_insert_newline_before_stmt(stmt ast.Stmt, prev_stmt ast.Stmt) bool {
f.indent++ prev_line_nr := prev_stmt.position().last_line
mut prev_line_nr := 0 // The stmt either has or shouldn't have a newline before
if stmts.len >= 1 { if stmt.position().line_nr - prev_line_nr <= 1 || f.out.last_n(2) == '\n\n' {
prev_pos := stmts[0].position() return false
prev_line_nr = util.imax(prev_pos.line_nr, prev_pos.last_line)
} }
// Imports are handled special hence they are ignored here
if stmt is ast.Import || prev_stmt is ast.Import {
return false
}
// Attributes are not respected in the stmts position, so we have to check it manually
if stmt is ast.StructDecl {
if stmt.attrs.len > 0 && stmt.attrs[0].pos.line_nr - prev_line_nr <= 1 {
return false
}
}
if stmt is ast.FnDecl {
if stmt.attrs.len > 0 && stmt.attrs[0].pos.line_nr - prev_line_nr <= 1 {
return false
}
}
return true
}
pub fn (mut f Fmt) stmts(stmts []ast.Stmt) {
mut prev_stmt := if stmts.len > 0 { stmts[0] } else { ast.Stmt{} }
f.indent++
for stmt in stmts { for stmt in stmts {
if stmt.position().line_nr - prev_line_nr > 1 { if f.should_insert_newline_before_stmt(stmt, prev_stmt) {
f.out.writeln('') f.out.writeln('')
} }
f.stmt(stmt) f.stmt(stmt)
prev_pos := stmt.position() prev_stmt = stmt
prev_line_nr = util.imax(prev_pos.line_nr, prev_pos.last_line)
} }
f.indent-- f.indent--
} }
@ -362,6 +377,8 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
} }
ast.Import { ast.Import {
// Imports are handled after the file is formatted, to automatically add necessary modules // Imports are handled after the file is formatted, to automatically add necessary modules
// Just remember the position of the imports for now
f.import_pos = f.out.len
// f.imports(f.file.imports) // f.imports(f.file.imports)
} }
ast.InterfaceDecl { ast.InterfaceDecl {

View File

@ -1,5 +1,6 @@
import semver import semver
// as semver // as semver
fn main() { fn main() {
} }

View File

@ -0,0 +1,8 @@
// comment above HashStmts
#flag linux -lsdl2
#include "stdio.h"
// comment between with newlines around
#include "header.h"
#include "sqlite3.h"

View File

@ -0,0 +1,5 @@
// import time This should be commented out
import os
import rand
// another comment after imports

View File

@ -0,0 +1,19 @@
// Module with attribute
[manualfree]
module websocket
fn main() {}
// This should stay between both functions
fn x() {}
// doc comment above an attributed function
[inline]
fn y_with_attr() {
}
// doc comment above an attributed struct
[typedef]
struct Foo {
}

View File

@ -13,6 +13,7 @@ type MyInt = int
pub type Abc = f32 pub type Abc = f32
// Fn type decl // Fn type decl
type EmptyFn = fn () type EmptyFn = fn ()
type OneArgFn = fn (i int) type OneArgFn = fn (i int)

View File

@ -16,7 +16,7 @@ const (
// // #include, #flag, #v // // #include, #flag, #v
fn (mut p Parser) hash() ast.HashStmt { fn (mut p Parser) hash() ast.HashStmt {
mut pos := p.prev_tok.position() pos := p.tok.position()
val := p.tok.lit val := p.tok.lit
kind := val.all_before(' ') kind := val.all_before(' ')
p.next() p.next()

View File

@ -15,12 +15,11 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
p.inside_ct_if_expr = was_inside_ct_if_expr p.inside_ct_if_expr = was_inside_ct_if_expr
} }
p.inside_if_expr = true p.inside_if_expr = true
mut pos := if is_comptime { mut pos := p.tok.position()
if is_comptime {
p.inside_ct_if_expr = true p.inside_ct_if_expr = true
p.next() // `$` p.next() // `$`
p.prev_tok.position().extend(p.tok.position()) pos = p.prev_tok.position().extend(p.tok.position())
} else {
p.tok.position()
} }
mut branches := []ast.IfBranch{} mut branches := []ast.IfBranch{}
mut has_else := false mut has_else := false

View File

@ -204,7 +204,11 @@ pub fn (mut p Parser) parse() ast.File {
} }
// module // module
module_decl := p.module_decl() module_decl := p.module_decl()
stmts << module_decl if module_decl.is_skipped {
stmts.insert(0, ast.Stmt(module_decl))
} else {
stmts << module_decl
}
// imports // imports
for { for {
if p.tok.kind == .key_import { if p.tok.kind == .key_import {
@ -513,8 +517,10 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
return p.struct_decl() return p.struct_decl()
} }
.dollar { .dollar {
if_expr := p.if_expr(true)
return ast.ExprStmt{ return ast.ExprStmt{
expr: p.if_expr(true) expr: if_expr
pos: if_expr.pos
} }
} }
.hash { .hash {
@ -1753,6 +1759,7 @@ fn (mut p Parser) parse_number_literal() ast.Expr {
fn (mut p Parser) module_decl() ast.Module { fn (mut p Parser) module_decl() ast.Module {
mut module_attrs := []table.Attr{} mut module_attrs := []table.Attr{}
mut attrs_pos := p.tok.position()
if p.tok.kind == .lsbr { if p.tok.kind == .lsbr {
p.attributes() p.attributes()
module_attrs = p.attrs module_attrs = p.attrs
@ -1788,7 +1795,7 @@ fn (mut p Parser) module_decl() ast.Module {
return mod_node return mod_node
} }
} }
module_pos = module_pos.extend(name_pos) module_pos = attrs_pos.extend(name_pos)
} }
full_name := util.qualify_module(name, p.file_name) full_name := util.qualify_module(name, p.file_name)
p.mod = full_name p.mod = full_name

View File

@ -154,10 +154,11 @@ pub fn (mut s Scanner) set_current_tidx(cidx int) {
fn (mut s Scanner) new_token(tok_kind token.Kind, lit string, len int) token.Token { fn (mut s Scanner) new_token(tok_kind token.Kind, lit string, len int) token.Token {
cidx := s.tidx cidx := s.tidx
s.tidx++ s.tidx++
line_offset := if tok_kind == .hash { 0 } else { 1 }
return token.Token{ return token.Token{
kind: tok_kind kind: tok_kind
lit: lit lit: lit
line_nr: s.line_nr + 1 line_nr: s.line_nr + line_offset
pos: s.pos - len + 1 pos: s.pos - len + 1
len: len len: len
tidx: cidx tidx: cidx