Skip to content

Commit

Permalink
Add check of consistent foreign symbol usage [skip ci]
Browse files Browse the repository at this point in the history
Checking the style of foreign symbol usages was completely disabled by
PR #19822. Now all style checks of a foreign symbol are checked against
the first time the symbol is used within a module.
  • Loading branch information
quantimnot committed Aug 25, 2022
1 parent bde0699 commit 149ce83
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 5 deletions.
23 changes: 18 additions & 5 deletions compiler/linter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

## This module implements the style checker.

import std/strutils
import std/[strutils, tables]
from std/sugar import dup

import options, ast, msgs, idents, lineinfos, wordrecg, astmsgs, semdata, packages
Expand Down Expand Up @@ -113,16 +113,19 @@ template styleCheckDef*(ctx: PContext; s: PSym) =
## Check symbol definitions adhere to NEP1 style rules.
styleCheckDef(ctx, s.info, s, s.kind)

proc differs(conf: ConfigRef; info: TLineInfo; newName: string): string =
proc extractIdent(conf: ConfigRef; info: TLineInfo): tuple[source: string, first, last: int] =
let line = sourceLine(conf, info)
var first = min(info.col.int, line.len)
if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first)
while first > 0 and line[first-1] in Letters: dec first
if first < 0: return
if first+1 < line.len and line[first] == '`': inc first

let last = first+identLen(line, first)-1
(line, first, last)

proc differs(conf: ConfigRef; info: TLineInfo; newName: string): string =
let (line, first, last) = conf.extractIdent(info)
result = differ(line, first, last, newName)

proc styleCheckUseImpl(conf: ConfigRef; info: TLineInfo; s: PSym) =
Expand All @@ -131,15 +134,25 @@ proc styleCheckUseImpl(conf: ConfigRef; info: TLineInfo; s: PSym) =
if badName.len > 0:
lintReport(conf, info, newName, badName, "".dup(addDeclaredLoc(conf, s)))

proc styleCheckUsagesMatchFirstUse(ctx: PContext; info: TLineInfo; sym: PSym) =
let (line, first, last) = ctx.config.extractIdent(info)
discard ctx.firstUsageOfForeignSym.hasKeyOrPut(sym.id, (line[first..last], info))
let (firstUseIdent, firstUseLineInfo) = ctx.firstUsageOfForeignSym[sym.id]
let badName = differ(line, first, last, firstUseIdent)
if badName.len > 0:
lintReport(ctx.config, info, firstUseIdent, badName, " [first used at $1]" % [toFileLineCol(ctx.config, firstUseLineInfo)])

template styleCheckUse*(ctx: PContext; info: TLineInfo; sym: PSym) =
## Check symbol uses match their definition's style.
if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
hintName in ctx.config.notes and # ignore if name checks are not requested
ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
sym.kind != skTemp and # ignore temporary variables created by the compiler
sym.name.s[0] in Letters and # ignore operators TODO: what about unicode symbols???
sfAnon notin sym.flags: # ignore temporary variables created by the compiler
styleCheckUseImpl(ctx.config, info, sym)
if ctx.config.belongsToProjectPackage(sym):
styleCheckUseImpl(ctx.config, info, sym)
else:
styleCheckUsagesMatchFirstUse(ctx, info, sym)

proc checkPragmaUseImpl(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
let wanted = $w
Expand Down
1 change: 1 addition & 0 deletions compiler/semdata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ type
lastTLineInfo*: TLineInfo
sideEffects*: Table[int, seq[(TLineInfo, PSym)]] # symbol.id index
inUncheckedAssignSection*: int
firstUsageOfForeignSym*: Table[int, tuple[ident: string, info: TLineInfo]] # (symbol.id, ...)

template config*(c: PContext): ConfigRef = c.graph.config

Expand Down
5 changes: 5 additions & 0 deletions tests/stylecheck/thint.nim
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,8 @@ proc generic_proc*[T] {.no_destroy, userPragma.} = #[tt.Hint
^ 'snakeCase' should be: 'snake_case' [let declared in thint.nim(28, 7)] [Name] ]#

generic_proc[int]()

# Test that foreign symbols usages are consistent within a module:
discard host_os # `system.hostOS`
discard hostos #[tt.Hint
^ 'hostos' should be: 'host_os' [first used at thint.nim(46, 9)] [Name] ]#

0 comments on commit 149ce83

Please sign in to comment.