diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/importer.nim | 1 | ||||
-rw-r--r-- | compiler/lineinfos.nim | 9 | ||||
-rw-r--r-- | compiler/patterns.nim | 2 | ||||
-rw-r--r-- | compiler/sem.nim | 7 | ||||
-rw-r--r-- | compiler/semcall.nim | 4 | ||||
-rw-r--r-- | compiler/semdata.nim | 4 | ||||
-rw-r--r-- | compiler/semexprs.nim | 41 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/semtempl.nim | 2 | ||||
-rw-r--r-- | compiler/semtypes.nim | 6 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 6 | ||||
-rw-r--r-- | compiler/suggest.nim | 17 |
12 files changed, 66 insertions, 35 deletions
diff --git a/compiler/importer.nim b/compiler/importer.nim index 2a5a1ac7c..426b79981 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -167,6 +167,7 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym = message(c.config, n.info, warnDeprecated, result.name.s & " is deprecated") suggestSym(c.config, n.info, result, c.graph.usageSym, false) importStmtResult.add newSymNode(result, n.info) + c.unusedImports.add((result, n.info)) #newStrNode(toFullPath(c.config, f), n.info) proc transformImportAs(c: PContext; n: PNode): PNode = diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index 121962014..42d33de7d 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -33,12 +33,14 @@ type warnFieldXNotSupported, warnCommentXIgnored, warnTypelessParam, warnUseBase, warnWriteToForeignHeap, warnUnsafeCode, + warnUnusedImportX, warnEachIdentIsTuple, warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed, warnInconsistentSpacing, warnCaseTransition, warnUser, hintSuccess, hintSuccessX, hintCC, - hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, + hintLineTooLong, hintXDeclaredButNotUsed, + hintConvToBaseNotNeeded, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern, @@ -78,6 +80,7 @@ const warnUseBase: "use {.base.} for base methods; baseless methods are deprecated", warnWriteToForeignHeap: "write to foreign heap", warnUnsafeCode: "unsafe code: '$1'", + warnUnusedImportX: "imported and not used: '$1'", warnEachIdentIsTuple: "each identifier is a tuple", warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.", warnProveField: "cannot prove that field '$1' is accessible", @@ -133,6 +136,7 @@ const "LanguageXNotSupported", "FieldXNotSupported", "CommentXIgnored", "TypelessParam", "UseBase", "WriteToForeignHeap", + "UnusedModule", "UnsafeCode", "EachIdentIsTuple", "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit", "GcMem", "Destructor", "LockLevel", "ResultShadowed", @@ -140,7 +144,8 @@ const HintsToStr* = [ "Success", "SuccessX", "CC", "LineTooLong", - "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", + "XDeclaredButNotUsed", + "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", "Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency", "Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "ExpandMacro", diff --git a/compiler/patterns.nim b/compiler/patterns.nim index e20c42b66..623a04406 100644 --- a/compiler/patterns.nim +++ b/compiler/patterns.nim @@ -295,7 +295,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode = # constraint not fulfilled: if not ok: return nil - markUsed(c.config, n.info, s, c.graph.usageSym) + markUsed(c, n.info, s, c.graph.usageSym) if ctx.subMatch: assert m.len == 3 m.sons[1] = result diff --git a/compiler/sem.nim b/compiler/sem.nim index fa0f742f7..e33170553 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -450,7 +450,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, pushInfoContext(c.config, nOrig.info, sym.detailedInfo) let info = getCallLineInfo(n) - markUsed(c.config, info, sym, c.graph.usageSym) + markUsed(c, info, sym, c.graph.usageSym) onUse(info, sym) if sym == c.p.owner: globalError(c.config, info, "recursive dependency: '$1'" % sym.name.s) @@ -618,12 +618,17 @@ proc myProcess(context: PPassContext, n: PNode): PNode = #if c.config.cmd == cmdIdeTools: findSuggest(c, n) rod.storeNode(c.graph, c.module, result) +proc reportUnusedModules(c: PContext) = + for i in 0..high(c.unusedImports): + message(c.config, c.unusedImports[i][1], warnUnusedImportX, c.unusedImports[i][0].name.s) + proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode = var c = PContext(context) if c.config.cmd == cmdIdeTools and not c.suggestionsMade: suggestSentinel(c) closeScope(c) # close module's scope rawCloseScope(c) # imported symbols; don't check for unused ones! + reportUnusedModules(c) result = newNode(nkStmtList) if n != nil: internalError(c.config, n.info, "n is not nil") #result := n; diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 805a29303..d2f878831 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -474,7 +474,7 @@ proc semResolvedCall(c: PContext, x: TCandidate, assert x.state == csMatch var finalCallee = x.calleeSym let info = getCallLineInfo(n) - markUsed(c.config, info, finalCallee, c.graph.usageSym) + markUsed(c, info, finalCallee, c.graph.usageSym) onUse(info, finalCallee) assert finalCallee.ast != nil if x.hasFauxMatch: @@ -584,7 +584,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode = var newInst = generateInstance(c, s, m.bindings, n.info) newInst.typ.flags.excl tfUnresolved let info = getCallLineInfo(n) - markUsed(c.config, info, s, c.graph.usageSym) + markUsed(c, info, s, c.graph.usageSym) onUse(info, s) result = newSymNode(newInst, info) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 6c7dd02ed..76eb468ed 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -71,7 +71,8 @@ type TExprFlags* = set[TExprFlag] PContext* = ref TContext - TContext* = object of TPassContext # a context represents a module + TContext* = object of TPassContext # a context represents the module + # that is currently being compiled enforceVoidContext*: PType module*: PSym # the module sym belonging to the context currentScope*: PScope # current scope @@ -136,6 +137,7 @@ type # the generic type has been constructed completely. See # tests/destructor/topttree.nim for an example that # would otherwise fail. + unusedImports*: seq[(PSym, TLineInfo)] template config*(c: PContext): ConfigRef = c.graph.config diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index bdf742bf1..929283bef 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -25,7 +25,7 @@ const proc semTemplateExpr(c: PContext, n: PNode, s: PSym, flags: TExprFlags = {}): PNode = let info = getCallLineInfo(n) - markUsed(c.config, info, s, c.graph.usageSym) + markUsed(c, info, s, c.graph.usageSym) onUse(info, s) # Note: This is n.info on purpose. It prevents template from creating an info # context when called from an another template @@ -305,7 +305,7 @@ proc semConv(c: PContext, n: PNode): PNode = let it = op.sons[i] let status = checkConvertible(c, result.typ, it) if status in {convOK, convNotNeedeed}: - markUsed(c.config, n.info, it.sym, c.graph.usageSym) + markUsed(c, n.info, it.sym, c.graph.usageSym) onUse(n.info, it.sym) markIndirect(c, it.sym) return it @@ -1106,7 +1106,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = let s = getGenSym(c, sym) case s.kind of skConst: - markUsed(c.config, n.info, s, c.graph.usageSym) + markUsed(c, n.info, s, c.graph.usageSym) onUse(n.info, s) let typ = skipTypes(s.typ, abstractInst-{tyTypeDesc}) case typ.kind @@ -1138,7 +1138,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = of skMacro: if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or (n.kind notin nkCallKinds and s.requiredParams > 0): - markUsed(c.config, n.info, s, c.graph.usageSym) + markUsed(c, n.info, s, c.graph.usageSym) onUse(n.info, s) result = symChoice(c, n, s, scClosed) else: @@ -1148,13 +1148,13 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = (n.kind notin nkCallKinds and s.requiredParams > 0) or sfCustomPragma in sym.flags: let info = getCallLineInfo(n) - markUsed(c.config, info, s, c.graph.usageSym) + markUsed(c, info, s, c.graph.usageSym) onUse(info, s) result = symChoice(c, n, s, scClosed) else: result = semTemplateExpr(c, n, s, flags) of skParam: - markUsed(c.config, n.info, s, c.graph.usageSym) + markUsed(c, n.info, s, c.graph.usageSym) onUse(n.info, s) if s.typ != nil and s.typ.kind == tyStatic and s.typ.n != nil: # XXX see the hack in sigmatch.nim ... @@ -1178,7 +1178,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = if s.magic == mNimvm: localError(c.config, n.info, "illegal context for 'nimvm' magic") - markUsed(c.config, n.info, s, c.graph.usageSym) + markUsed(c, n.info, s, c.graph.usageSym) onUse(n.info, s) result = newSymNode(s, n.info) # We cannot check for access to outer vars for example because it's still @@ -1196,7 +1196,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = n.typ = s.typ return n of skType: - markUsed(c.config, n.info, s, c.graph.usageSym) + markUsed(c, n.info, s, c.graph.usageSym) onUse(n.info, s) if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil: return s.typ.n @@ -1218,7 +1218,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = if f != nil and fieldVisible(c, f): # is the access to a public field or in the same module or in a friend? doAssert f == s - markUsed(c.config, n.info, f, c.graph.usageSym) + markUsed(c, n.info, f, c.graph.usageSym) onUse(n.info, f) result = newNodeIT(nkDotExpr, n.info, f.typ) result.add makeDeref(newSymNode(p.selfSym)) @@ -1231,12 +1231,12 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = if ty.sons[0] == nil: break ty = skipTypes(ty.sons[0], skipPtrs) # old code, not sure if it's live code: - markUsed(c.config, n.info, s, c.graph.usageSym) + markUsed(c, n.info, s, c.graph.usageSym) onUse(n.info, s) result = newSymNode(s, n.info) else: let info = getCallLineInfo(n) - markUsed(c.config, info, s, c.graph.usageSym) + markUsed(c, info, s, c.graph.usageSym) onUse(info, s) result = newSymNode(s, info) @@ -1258,7 +1258,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = result = symChoice(c, n, s, scClosed) if result.kind == nkSym: result = semSym(c, n, s, flags) else: - markUsed(c.config, n.sons[1].info, s, c.graph.usageSym) + markUsed(c, n.sons[1].info, s, c.graph.usageSym) result = semSym(c, n, s, flags) onUse(n.sons[1].info, s) return @@ -1322,7 +1322,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = result = newSymNode(f) result.info = n.info result.typ = ty - markUsed(c.config, n.info, f, c.graph.usageSym) + markUsed(c, n.info, f, c.graph.usageSym) onUse(n.info, f) return of tyObject, tyTuple: @@ -1357,7 +1357,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = else: true if not visibilityCheckNeeded or fieldVisible(c, f): # is the access to a public field or in the same module or in a friend? - markUsed(c.config, n.sons[1].info, f, c.graph.usageSym) + markUsed(c, n.sons[1].info, f, c.graph.usageSym) onUse(n.sons[1].info, f) n.sons[0] = makeDeref(n.sons[0]) n.sons[1] = newSymNode(f) # we now have the correct field @@ -1371,7 +1371,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = elif ty.kind == tyTuple and ty.n != nil: f = getSymFromList(ty.n, i) if f != nil: - markUsed(c.config, n.sons[1].info, f, c.graph.usageSym) + markUsed(c, n.sons[1].info, f, c.graph.usageSym) onUse(n.sons[1].info, f) n.sons[0] = makeDeref(n.sons[0]) n.sons[1] = newSymNode(f) @@ -1905,7 +1905,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode = if expandedSym.kind == skError: return n macroCall.sons[0] = newSymNode(expandedSym, macroCall.info) - markUsed(c.config, n.info, expandedSym, c.graph.usageSym) + markUsed(c, n.info, expandedSym, c.graph.usageSym) onUse(n.info, expandedSym) if isCallExpr(macroCall): @@ -1930,7 +1930,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode = else: let info = macroCall.sons[0].info macroCall.sons[0] = newSymNode(cand, info) - markUsed(c.config, info, cand, c.graph.usageSym) + markUsed(c, info, cand, c.graph.usageSym) onUse(info, cand) # we just perform overloading resolution here: @@ -2453,9 +2453,10 @@ proc semExportExcept(c: PContext, n: PNode): PNode = var s = initTabIter(i, exported.tab) while s != nil: if s.kind in ExportableSymKinds+{skModule} and - s.name.id notin exceptSet: + s.name.id notin exceptSet and sfError notin s.flags: strTableAdd(c.module.tab, s) result.add newSymNode(s, n.info) + markUsed(c, n.info, s, c.graph.usageSym) s = nextIter(i, exported.tab) proc semExport(c: PContext, n: PNode): PNode = @@ -2476,14 +2477,16 @@ proc semExport(c: PContext, n: PNode): PNode = strTableAdd(c.module.tab, it) result.add newSymNode(it, a.info) it = nextIter(ti, s.tab) + markUsed(c, n.info, s, c.graph.usageSym) else: while s != nil: if s.kind == skEnumField: localError(c.config, a.info, errGenerated, "cannot export: " & renderTree(a) & "; enum field cannot be exported individually") - if s.kind in ExportableSymKinds+{skModule}: + if s.kind in ExportableSymKinds+{skModule} and sfError notin s.flags: result.add(newSymNode(s, a.info)) strTableAdd(c.module.tab, s) + markUsed(c, n.info, s, c.graph.usageSym) s = nextOverloadIter(o, c, a) proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 2020f10f8..402816078 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -812,7 +812,7 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode = errors, false) if r.state == csMatch: var match = r.calleeSym - markUsed(c.config, n[0].info, match, c.graph.usageSym) + markUsed(c, n[0].info, match, c.graph.usageSym) onUse(n[0].info, match) # but pass 'n' to the 'match' macro, not 'n[0]': diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 7a56f8c45..1b9b9e8a9 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -64,7 +64,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode = # (s.kind notin routineKinds or s.magic != mNone): # for instance 'nextTry' is both in tables.nim and astalgo.nim ... result = newSymNode(s, info) - markUsed(c.config, info, s, c.graph.usageSym) + markUsed(c, info, s, c.graph.usageSym) onUse(info, s) else: # semantic checking requires a type; ``fitNode`` deals with it diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index e927be417..e7fbc83ec 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -353,7 +353,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = if result.isNil: result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared}) if result != nil: - markUsed(c.config, n.info, result, c.graph.usageSym) + markUsed(c, n.info, result, c.graph.usageSym) onUse(n.info, result) if result.kind == skParam and result.typ.kind == tyTypeDesc: @@ -1063,7 +1063,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), false)) of tyGenericParam: - markUsed(c.config, paramType.sym.info, paramType.sym, c.graph.usageSym) + markUsed(c, paramType.sym.info, paramType.sym, c.graph.usageSym) onUse(paramType.sym.info, paramType.sym) if tfWildcard in paramType.flags: paramType.flags.excl tfWildcard @@ -1751,7 +1751,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = else: assignType(prev, t) result = prev - markUsed(c.config, n.info, n.sym, c.graph.usageSym) + markUsed(c, n.info, n.sym, c.graph.usageSym) onUse(n.info, n.sym) else: if s.kind != skError: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index b331b6f1f..828d25fe8 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -107,7 +107,7 @@ type const isNilConversion = isConvertible # maybe 'isIntConv' fits better? -proc markUsed*(conf: ConfigRef; info: TLineInfo, s: PSym; usageSym: var PSym) +proc markUsed*(c: PContext; info: TLineInfo, s: PSym; usageSym: var PSym) template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone @@ -1891,7 +1891,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, dest = generateTypeInstance(c, m.bindings, arg, dest) let fdest = typeRel(m, f, dest) if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind == tyVar): - markUsed(c.config, arg.info, c.converters[i], c.graph.usageSym) + markUsed(c, arg.info, c.converters[i], c.graph.usageSym) var s = newSymNode(c.converters[i]) s.typ = c.converters[i].typ s.info = arg.info @@ -2220,7 +2220,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, else: result = nil else: # only one valid interpretation found: - markUsed(m.c.config, arg.info, arg.sons[best].sym, m.c.graph.usageSym) + markUsed(m.c, arg.info, arg.sons[best].sym, m.c.graph.usageSym) onUse(arg.info, arg.sons[best].sym) result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best], argOrig) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 2f92825c0..59e3a7242 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -528,7 +528,21 @@ proc userError(conf: ConfigRef; info: TLineInfo; s: PSym) = return localError(conf, info, "usage of '$1' is a user-defined error" % s.name.s) -proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = +proc markOwnerModuleAsUsed(c: PContext; s: PSym) = + var module = s + while module != nil and module.kind != skModule: + module = module.owner + if module != nil and module != c.module: + var i = 0 + while i <= high(c.unusedImports): + if c.unusedImports[i][0] == module: + # mark it as used: + c.unusedImports.del(i) + else: + inc i + +proc markUsed(c: PContext; info: TLineInfo; s: PSym; usageSym: var PSym) = + let conf = c.config incl(s.flags, sfUsed) if s.kind == skEnumField and s.owner != nil: incl(s.owner.flags, sfUsed) @@ -541,6 +555,7 @@ proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = suggestSym(conf, info, s, usageSym, false) if {optStyleHint, optStyleError} * conf.globalOptions != {}: styleCheckUse(conf, info, s) + markOwnerModuleAsUsed(c, s) proc safeSemExpr*(c: PContext, n: PNode): PNode = # use only for idetools support! |