unresolvedGlobalReferences(dir, files=<<see below>>, referenceList, definedHere=character(), expressions=1200, ignore.working.database=T) globalAssignments(files) globalReferences(files=character(), expr=NULL, cacheFrame=NULL, name="<root>", just.assigned.name=NULL, outputCacheFrame=NULL, expressions=1200)
files=
argument is ignored if this argument
is given.
dir=
argument is ignored
if this argument is given.
options("expressions")
.
dir=
and
files=
arguments must
not be supplied when this argument is given.
unresolvedGlobalReferences
returns a list of named character vectors, where each list element is a
vector of undefined references in a function, and the element's name gives
the name of the function.
The name of each list element is encoded to contain the
source file name and the function in that file, or a sequence of functions
if the function is nested within functions, having this format:
"filename#functionName#subfunctionName#subsubfunctionName"
sapply(x, function(xi)length(xi))
<anonymous-n>
with a different
n
for each unnamed function defined in a given function.
For example, the following list element shows that the first unnamed function in the function
newFunc1
contains undefined references.
$"/tmp/testdir/newFunctions.q#newFunc1#<anonymous-1>":
[1] "n" "sep"
If a function uses the
<<-
operator the output entry
for that function will have an attribute called
"uses <<-"
.
The double-arrow operator means different things in R and S-PLUS and such
code is not portable.
If a function uses the
::
or
:::
namespace
operators the output entry for that function will have an attribute
called
"uses explicit namespace"
listing all the usages
in the function. S-PLUS does not support namespaces and
::
and
:::
functions in the pkgutils library will ignore
the namespace in
namespace::name
.
unresolvedGlobalReferences
returns an empty list if no undefined objects
(or other problems) are found.
The following functions are called by
unresolvedGlobalReferences
,
and may not be useful to most users.
The function
globalAssignments
returns a character vector
containing all global assignments found in the given source file(s).
The function
globalReferences
returns a list of named
character vectors containing all global references found in the given source file(s).
There is a list element for each function defined in the source files. The format
of the list element names is the same as described above for the function
unresolvedGlobalReferences
.
The function
unresolvedGlobalReferences
is helpful
when porting R packages to S-PLUS
in order to find problems involving missing R functions
or lexical scoping. It searches either all source files in the specified
directory if the
dir
argument is specified or
the files included in the
files
argument.
Note how the names of the files and functions in the files are encoded in the output list: file#func#subfunc#subsubfunc, but line numbers are not given. To find the anonymous functions look for the word 'function' in your source file.
In order to analyze R source code files containing S-PLUS
code written for R, use
set.parse.mode("R")
.
Parsing in R mode allows underscores in names and treats 10 as a numeric instead
of an integer, although there are still some things the parser
rejects (like assigning to the variables T and F).
The contents of a non-S-PLUS clauses are ignored when either
is.R()
or
!is.R()
is used in
if
statements.
The name of the namespace in
namespace:::func
or
namespace::func
is ignored, but
:::
and
::
will
be reported as missing.
The names of the non-functions in formulae are also ignored
as those generally are found at run time in a
data=
argument, but the
subset=
and
weights=
arguments in modeling and trellis functions are
not ignored,
as those are evaluated with
local=data
also, just like the formula.
# This example shows that the function kahanAddNext, called by # kahanSum, is not defined in the file kahanSum.q. z <- unresolvedGlobalReferences(files = file.path(getenv("SHOME"), "samples/kahanSum/kahanSum.q")) z
# This example illustrates problems with missing functions # and lexical scoping (in the sapply call). newFunc1 <- function(x, sep) { tmp <- unknownFunc1(x) if(is.R()) tmp <- `some_R_func`(x) else tmp <- unknownFunc2(x) if(FALSE) tmp <- unknownFunc3(x) tmp <- newFunc2(x) sapply(tmp, function(tmpi) paste(tmpi, n, sep = sep)) } newFunc2 <- function(x) log(x) testdir <- tempfile() mkdir(testdir) file1 <- dump("newFunc1", file.path(testdir, "newFunc1.q")) file2 <- dump("newFunc2", file.path(testdir, "newFunc2.q")) unresolvedGlobalReferences(dir=testdir, definedHere=c("unknownFunc1")) unresolvedGlobalReferences(files=file1, ignore.working.database=F) globalAssignments(files=file1) globalReferences(files=file2) rmdir(testdir)
# Variables used in the default values of functions may be incorrectly # returned as undefined when defined in the body of the function. newFunc3 <- function (x, n = length(u)) { u <- unique(x) list(x=x, u=u, n=n) } testdir <- tempfile() mkdir(testdir) file3 <- dump("newFunc3", file.path(testdir, "newFunc3.q")) # u is incorrectly reported as unresolved unresolvedGlobalReferences(files=file3) rmdir(testdir)