#!/usr/bin/env rune # Copyright 2003-2004 Kevin Reid. # This source code and related files are distributed under the MIT License, as described in the document named "License.txt" which should be provided with this source distribution. pragma.enable("explicit-result-guard") pragma.disable("easy-return") def checkUnused(expr) :any { def exprScope := expr.staticScope() def [subExprs] := expr.welcome(def visitor { # AIEEEEE to visitAssignExpr(_, noun, rValue) :any { [[noun, rValue]] } to visitCallExpr(_, recip, verb, args) :any { [[recip] + args] } to visitCatchExpr(_, attempt, patt, catcher) :any { [[attempt, patt, catcher]] } to visitCdrPattern(_, subs, rest) :any { [[subs, rest]] } to visitDefineExpr(_, patt, rValue) :any { [[patt, rValue]] } to visitEMatcher(_, pattern, body) :any { [[pattern, body]] } to visitEMethod(_, docComment, verb, patterns, optResultGuard, body) :any { [patterns + [optResultGuard, body]] } to visitEScript(_, optMethods, matchers) :any { [optMethods + matchers] } to visitEscapeExpr(_, hatch, body, optArgPattern, optCatcher) :any { [[body, optArgPattern, optCatcher]] } to visitFinalPattern(_, nounExpr, optGuardExpr) :any { [[nounExpr, optGuardExpr]] } to visitFinallyExpr(_, attempt, unwinder) :any { [[attempt, unwinder]] } to visitHideExpr(_, body) :any { [[body]] } to visitIfExpr(_, test, then, els) :any { [[test, then, els]] } to visitIgnorePattern(_) :any { [[]] } to visitListPattern(_, subs) :any { [subs] } to visitLiteralExpr(_, _) :any { [[]] } to visitMatchBindExpr(_, specimen, patt) :any { [[specimen, patt]] } to visitMetaContextExpr(_) :any { [[]] } to visitMetaStateExpr(_) :any { [[]] } to visitNounExpr(_, varName) :any { [[]] } to visitObjectExpr(_, docComment, qualifiedName, auditors, eScript) :any { [auditors + [eScript]] } to visitQuasiLiteralExpr(_, index) :any { [[]] } to visitQuasiLiteralPatt(_, index) :any { [[]] } to visitQuasiPatternExpr(_, index) :any { [[]] } to visitQuasiPatternPatt(_, index) :any { [[]] } to visitScopeExpr(_) :any { [[]] } to visitSendExpr(_, recip, verb, args) :any { [[recip] + args] } to visitSeqExpr(_, subs) :any { [subs] } to visitSlotExpr(_, _) :any { [[]] } to visitSlotPattern(_, nounExpr, optGuardExpr) :any { [[nounExpr, optGuardExpr]] } to visitSuchThatPattern(_, patt, test) :any { [[patt, test]] } to visitVarPattern(_, nounExpr, optGuardExpr) :any { [[nounExpr, optGuardExpr]] } #match [verb, args] { [[]] } }) var namesUnused := exprScope.namesOut().getKeys().asSet() for subExpr ? (subExpr != null) in subExprs { checkUnused(subExpr) namesUnused butNot= (subExpr.staticScope().namesUsed().getKeys().asSet()) } for name in namesUnused { println(` Unused: $name`) } } def scan(f) :void { if (f.isDirectory()) { for g in f { scan(g) } } else if (f.getName() =~ `@filebase.@fileext` && ["e", "e-awt", "e-swt", "emaker"].contains(fileext)) { var needsHeader := true def header() :void { if (needsHeader) { println(f) needsHeader := false } } def expr := e__quasiParser(f.getText()) #checkUnused(expr) expr.welcome(def visitor { to visitSeqExpr(_, subs) :void { def exprScope := expr.staticScope() var namesUnused := exprScope.namesOut().getKeys().asSet() # for our imperfect algorithm namesUnused without= filebase for subExpr in subs { namesUnused butNot= (subExpr.staticScope().namesUsed().getKeys().asSet()) } for name in namesUnused { header() println(` Unused: $name`) } } match [verb, args] {} }) } } scan()