xmlparsedata/ 0000755 0001762 0000144 00000000000 14020661412 012733 5 ustar ligges users xmlparsedata/NAMESPACE 0000644 0001762 0000144 00000000200 14020644101 014136 0 ustar ligges users # Generated by roxygen2: do not edit by hand
export(xml_parse_data)
export(xml_parse_token_map)
importFrom(utils,getParseData)
xmlparsedata/LICENSE 0000644 0001762 0000144 00000000055 13347702527 013756 0 ustar ligges users YEAR: 2016
COPYRIGHT HOLDER: Mango Solutions
xmlparsedata/README.md 0000644 0001762 0000144 00000025661 14020645205 014226 0 ustar ligges users
# xmlparsedata
> Parse Data of R Code as an ‘XML’ Tree
[](https://github.com/r-lib/xmlparsedata/actions)
[](https://www.r-pkg.org/pkg/xmlparsedata)
[](https://www.r-pkg.org/pkg/xmlparsedata)
[](https://codecov.io/github/r-lib/xmlparsedata?branch=master)
Convert the output of ‘utils::getParseData()’ to an ‘XML’ tree, that is
searchable and easier to manipulate in general.
-----
- [Installation](#installation)
- [Usage](#usage)
- [Introduction](#introduction)
- [`utils::getParseData()`](#utilsgetparsedata)
- [`xml_parse_data()`](#xml_parse_data)
- [Renaming some tokens](#renaming-some-tokens)
- [Search the parse tree with
`xml2`](#search-the-parse-tree-with-xml2)
- [License](#license)
## Installation
``` r
install.packages("xmlparsedata")
```
## Usage
### Introduction
In recent R versions the parser can attach source code location
information to the parsed expressions. This information is often useful
for static analysis, e.g. code linting. It can be accessed via the
`utils::getParseData()` function.
`xmlparsedata` converts this information to an XML tree. The R parser’s
token names are preserved in the XML as much as possible, but some of
them are not valid XML tag names, so they are renamed, see below.
### `utils::getParseData()`
`utils::getParseData()` summarizes the parse information in a data
frame. The data frame has one row per expression tree node, and each
node points to its parent. Here is a small example:
``` r
p <- parse(
text = "function(a = 1, b = 2) { \n a + b\n}\n",
keep.source = TRUE
)
getParseData(p)
```
#> line1 col1 line2 col2 id parent token terminal text
#> 33 1 1 3 1 33 0 expr FALSE
#> 1 1 1 1 8 1 33 FUNCTION TRUE function
#> 2 1 9 1 9 2 33 '(' TRUE (
#> 3 1 10 1 10 3 33 SYMBOL_FORMALS TRUE a
#> 4 1 12 1 12 4 33 EQ_FORMALS TRUE =
#> 5 1 14 1 14 5 6 NUM_CONST TRUE 1
#> 6 1 14 1 14 6 33 expr FALSE
#> 7 1 15 1 15 7 33 ',' TRUE ,
#> 10 1 17 1 17 10 33 SYMBOL_FORMALS TRUE b
#> 11 1 19 1 19 11 33 EQ_FORMALS TRUE =
#> 12 1 21 1 21 12 13 NUM_CONST TRUE 2
#> 13 1 21 1 21 13 33 expr FALSE
#> 14 1 22 1 22 14 33 ')' TRUE )
#> 30 1 24 3 1 30 33 expr FALSE
#> 17 1 24 1 24 17 30 '{' TRUE {
#> 25 2 3 2 7 25 30 expr FALSE
#> 19 2 3 2 3 19 21 SYMBOL TRUE a
#> 21 2 3 2 3 21 25 expr FALSE
#> 20 2 5 2 5 20 25 '+' TRUE +
#> 22 2 7 2 7 22 24 SYMBOL TRUE b
#> 24 2 7 2 7 24 25 expr FALSE
#> 28 3 1 3 1 28 30 '}' TRUE }
### `xml_parse_data()`
`xmlparsedata::xml_parse_data()` converts the parse information to an
XML document. It works similarly to `getParseData()`. Specify the
`pretty = TRUE` option to pretty-indent the XML output. Note that this
has a small overhead, so if you are parsing large files, I suggest you
omit it.
``` r
library(xmlparsedata)
xml <- xml_parse_data(p, pretty = TRUE)
cat(xml)
```
#>
#>
#>
#> function
#> (
#> a
#> =
#>
#> 1
#>
#> ,
#> b
#> =
#>
#> 2
#>
#> )
#>
#> {
#>
#>
#> a
#>
#> +
#>
#> b
#>
#>
#> }
#>
#>
#>
The top XML tag is ``, which is a list of expressions, each
expression is an `` tag. Each tag has attributes that define the
location: `line1`, `col1`, `line2`, `col2`. These are from the
`getParseData()` data frame column names.
### Renaming some tokens
The R parser’s token names are preserved in the XML as much as possible,
but some of them are not valid XML tag names, so they are renamed, see
the `xml_parse_token_map` vector for the mapping:
``` r
xml_parse_token_map
```
#> '?' '~' '+' '-'
#> "OP-QUESTION" "OP-TILDE" "OP-PLUS" "OP-MINUS"
#> '*' '/' ':' '^'
#> "OP-STAR" "OP-SLASH" "OP-COLON" "OP-CARET"
#> '$' '@' '(' '['
#> "OP-DOLLAR" "OP-AT" "OP-LEFT-PAREN" "OP-LEFT-BRACKET"
#> ';' '{' '}' ')'
#> "OP-SEMICOLON" "OP-LEFT-BRACE" "OP-RIGHT-BRACE" "OP-RIGHT-PAREN"
#> '!' ']' ',' '\\\\'
#> "OP-EXCLAMATION" "OP-RIGHT-BRACKET" "OP-COMMA" "OP-LAMBDA"
### Search the parse tree with `xml2`
The `xml2` package can search XML documents using
[XPath](https://en.wikipedia.org/wiki/XPath) expressions. This is often
useful to search for specific code patterns.
As an example we search a source file from base R for `1:nrow()`
expressions, which are usually unsafe, as `nrow()` might be zero, and
then the expression is equivalent to `1:0`, i.e. `c(1, 0)`, which is
usually not the intended behavior.
We load and parse the file directly from the the R source code mirror at
:
``` r
url <- paste0(
"https://raw.githubusercontent.com/wch/r-source/",
"4fc93819fc7401b8695ce57a948fe163d4188f47/src/library/tools/R/xgettext.R"
)
src <- readLines(url)
p <- parse(text = src, keep.source = TRUE)
```
and we convert it to an XML tree:
``` r
library(xml2)
xml <- read_xml(xml_parse_data(p))
```
The `1:nrow()` expression corresponds to the following tree in R:
+--
+-- NUM_CONST: 1
+-- ':'
+--
+--
+-- SYMBOL_FUNCTION_CALL nrow
+-- '('
+--
+-- ')'
``` r
bad <- xml_parse_data(
parse(text = "1:nrow(expr)", keep.source = TRUE),
pretty = TRUE
)
cat(bad)
```
#>
#>
#>
#>
#> 1
#>
#> :
#>
#>
#> nrow
#>
#> (
#>
#> expr
#>
#> )
#>
#>
#>
This translates to the following XPath expression (ignoring the last
tree tokens from the `length(expr)` expressions):
``` r
xp <- paste0(
"//expr",
"[expr[NUM_CONST[text()='1']]]",
"[OP-COLON]",
"[expr[expr[SYMBOL_FUNCTION_CALL[text()='nrow']]]]"
)
```
We can search for this subtree with `xml2::xml_find_all()`:
``` r
bad_nrow <- xml_find_all(xml, xp)
bad_nrow
```
#> {xml_nodeset (1)}
#> [1] [2,] "333" " else"
#> [3,] "334" "\tfor (i in 1:nrow(x)) {"
#> [4,] "335" "\t if (is.na(x[i, 2L])) cols <- c(1L, 3:5)"
#> [5,] "336" "\t else cols <- 1:5"
## License
MIT © Mango Solutions
xmlparsedata/man/ 0000755 0001762 0000144 00000000000 14020644610 013507 5 ustar ligges users xmlparsedata/man/xml_parse_data.Rd 0000644 0001762 0000144 00000004276 14020644610 016772 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/package.R
\name{xml_parse_data}
\alias{xml_parse_data}
\title{Convert R parse data to XML}
\usage{
xml_parse_data(x, includeText = NA, pretty = FALSE)
}
\arguments{
\item{x}{
an expression returned from \code{\link{parse}}, or a function or other
object with source reference information
}
\item{includeText}{
logical; whether to include the text of parsed items in the result
}
\item{pretty}{Whether to pretty-indent the XML output. It has a small
overhead which probably only matters for very large source files.}
}
\value{
An XML string representing the parse data. See details below.
}
\description{
In recent R versions the parser can attach source code location
information to the parsed expressions. This information is often
useful for static analysis, e.g. code linting. It can be accessed
via the \code{\link[utils]{getParseData}} function.
}
\details{
\code{xml_parse_data} converts this information to an XML tree.
The R parser's token names are preserved in the XML as much as
possible, but some of them are not valid XML tag names, so they are
renamed, see the \code{\link{xml_parse_token_map}} vector for the
mapping.
The top XML tag is \code{}, which is a list of
expressions, each expression is an \code{} tag. Each tag
has attributes that define the location: \code{line1}, \code{col1},
\code{line2}, \code{col2}. These are from the \code{\link{getParseData}}
data frame column names.
See an example below. See also the README at
\url{https://github.com/r-lib/xmlparsedata#readme}
for examples on how to search the XML tree with the \code{xml2} package
and XPath expressions.
Note that `xml_parse_data()` silently drops all control characters
(0x01-0x1f) from the input, except horizontal tab (0x09) and newline
(0x0a), because they are invalid in XML 1.0.
}
\examples{
code <- "function(a = 1, b = 2) {\\n a + b\\n}\\n"
expr <- parse(text = code, keep.source = TRUE)
# The base R way:
getParseData(expr)
cat(xml_parse_data(expr, pretty = TRUE))
}
\seealso{
\code{\link{xml_parse_token_map}} for the token names.
\url{https://github.com/r-lib/xmlparsedata#readme} for more
information and use cases.
}
xmlparsedata/man/xmlparsedata.Rd 0000644 0001762 0000144 00000000546 14020644610 016470 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/package.R
\docType{package}
\name{xmlparsedata}
\alias{xmlparsedata}
\alias{xmlparsedata-package}
\title{Parse Data of R Code as an 'XML' Tree}
\description{
Convert the output of 'utils::getParseData()' to an 'XML' tree, that is
searchable and easier to manipulate in general.
}
xmlparsedata/man/xml_parse_token_map.Rd 0000644 0001762 0000144 00000001043 14020644610 020023 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/package.R
\docType{data}
\name{xml_parse_token_map}
\alias{xml_parse_token_map}
\title{Map token names of the R parser to token names in
\code{\link{xml_parse_data}}}
\format{An object of class \code{character} of length 20.}
\usage{
xml_parse_token_map
}
\description{
Some of the R token names are not valid XML tag names,
so \code{\link{xml_parse_data}} needs to replace them to create a
valid XML file.
}
\seealso{
\code{\link{xml_parse_data}}
}
\keyword{datasets}
xmlparsedata/DESCRIPTION 0000644 0001762 0000144 00000001247 14020661412 014445 0 ustar ligges users Package: xmlparsedata
Title: Parse Data of 'R' Code as an 'XML' Tree
Version: 1.0.5
Author: Gábor Csárdi
Maintainer: Gábor Csárdi
Description: Convert the output of 'utils::getParseData()' to an 'XML'
tree, that one can search via 'XPath', and easier to manipulate in
general.
License: MIT + file LICENSE
LazyData: true
URL: https://github.com/r-lib/xmlparsedata#readme
BugReports: https://github.com/r-lib/xmlparsedata/issues
RoxygenNote: 6.0.1
Suggests: covr, testthat, xml2
Depends: R (>= 3.0.0)
Encoding: UTF-8
NeedsCompilation: no
Packaged: 2021-03-06 10:52:40 UTC; gaborcsardi
Repository: CRAN
Date/Publication: 2021-03-06 11:10:02 UTC
xmlparsedata/tests/ 0000755 0001762 0000144 00000000000 13347702527 014113 5 ustar ligges users xmlparsedata/tests/testthat/ 0000755 0001762 0000144 00000000000 14020661412 015735 5 ustar ligges users xmlparsedata/tests/testthat/test.R 0000644 0001762 0000144 00000010405 14020653444 017045 0 ustar ligges users
context("xmlparsedata")
test_that("empty input", {
xml <- xml_parse_data(parse(text = "", keep.source = TRUE))
expect_true(is.character(xml))
expect_true(length(xml) == 1)
expect_match(xml, "\\s*")
expect_silent(x <- xml2::read_xml(xml))
})
test_that("trivial input", {
xml <- xml_parse_data(parse(text = "# comment\n", keep.source = TRUE))
expect_true(is.character(xml))
expect_true(length(xml) == 1)
expect_match(xml, "\\s*\\s*")
expect_silent(x <- xml2::read_xml(xml))
xml <- xml_parse_data(parse(text = "1", keep.source = TRUE))
expect_match(
xml,
paste0(
"\\s*\\s*",
"\\s*"
)
)
expect_silent(x <- xml2::read_xml(xml))
})
test_that("non-trivial input", {
ip <- deparse(utils::install.packages)
xml <- xml_parse_data(parse(text = ip, keep.source = TRUE))
expect_silent(x <- xml2::read_xml(xml))
dp <- deparse(utils::install.packages)
xml <- xml_parse_data(
parse(text = dp, keep.source = TRUE),
pretty = TRUE
)
expect_silent(x <- xml2::read_xml(xml))
})
test_that("UTF-8 is OK", {
src <- enc2native("# comment with éápő")
xml <- xml_parse_data(parse(text = src, keep.source = TRUE))
x <- xml2::read_xml(xml)
comment <- xml2::xml_children(x)
col1 <- xml2::xml_attr(comment, "col1")
col2 <- xml2::xml_attr(comment, "col2")
expect_equal(
substring(src, col1, col2),
src
)
src <- enc2native("# 現行の学校文法では、英語にあるような「目的語」「補語」")
xml <- xml_parse_data(parse(text = src, keep.source = TRUE))
x <- xml2::read_xml(xml)
comment <- xml2::xml_children(x)
col1 <- xml2::xml_attr(comment, "col1")
col2 <- xml2::xml_attr(comment, "col2")
expect_equal(
substring(src, col1, col2),
iconv(src, to = "UTF-8")
)
src <- enc2native("`%ééé%` <- function(l, r) l + r")
xml <- xml_parse_data(parse(text = src, keep.source = TRUE), pretty = TRUE)
op <- xml2::xml_find_all(
xml2::read_xml(xml),
iconv(enc2native("/exprlist/expr/expr/SYMBOL[text()='`%ééé%`']"),
to = "UTF-8")
)
expect_equal(length(op), 1)
})
test_that("data frame input", {
p <- parse(text = "1 + 1", keep.source = TRUE)
pd <- getParseData(p)
attr(pd, "srcfile") <- NULL
class(pd) <- "data.frame"
x1 <- xml_parse_data(pd)
x2 <- xml_parse_data(p)
expect_equal(x1, x2)
})
test_that("Control-C character", {
src <- "# Control-C \003
# Bell \007
# Escape \027
# Form feed \f
# Vertical tab \t
"
xml <- xml_parse_data(parse(text = src, keep.source = TRUE))
x <- xml2::read_xml(xml)
expect_is(x, "xml_document")
})
test_that("equal_assign is handled on R 3.6", {
# `a = 1` is an example of an R statement that gets parsed into nested xml
# nodes that have different token / tagnames (following the introduction of
# the `equal_assign` token to getParseData() in R-3.6), but the same ending
# position in the original code. Tokens/expressions that start before should
# end after any nested subexpressions in the resulting xml:
xml <- xml_parse_data(parse(text = "a = 1", keep.source = TRUE))
expect_true(is.character(xml))
expect_true(length(xml) == 1)
expect_silent(x <- xml2::read_xml(xml))
})
test_that("includeText=FALSE works", {
# getParseData(..., includeText = FALSE) returns a data.frame
# without `text` column. xml_parse_data should handle this case
# correctly and the resulting xml text should not contain text
# elements.
xml <- xml_parse_data(parse(text = "x <- 1", keep.source = TRUE),
includeText = FALSE)
expect_true(is.character(xml))
expect_true(length(xml) == 1)
expect_silent(x <- xml2::read_xml(xml))
expect_true(xml2::xml_text(x) == "")
})
test_that("lambda operator works", {
testthat::skip_if_not(getRversion() >= "4.1.0" && as.numeric(R.version[["svn rev"]]) >= 79553)
# r-devel rev 79553 introduces native pipe syntax (|>) and lambda expression (e.g \(x) x + 1).
xml <- xml_parse_data(parse(text = "\\(x) x + 1", keep.source = TRUE))
expect_true(is.character(xml))
expect_true(length(xml) == 1)
expect_silent(x <- xml2::read_xml(xml))
expect_true(length(xml2::xml_find_all(x, "//OP-LAMBDA")) == 1)
})
xmlparsedata/tests/testthat.R 0000644 0001762 0000144 00000000171 13347702527 016075 0 ustar ligges users library(testthat)
library(xmlparsedata)
if (requireNamespace("xml2", quietly = TRUE)) {
test_check("xmlparsedata")
}
xmlparsedata/R/ 0000755 0001762 0000144 00000000000 14020644075 013142 5 ustar ligges users xmlparsedata/R/utils.R 0000644 0001762 0000144 00000000206 13347702527 014433 0 ustar ligges users
spaces_const <- sapply(1:41-1, function(x) paste(rep(" ", x), collapse = ""))
spaces <- function(x) spaces_const[ pmin(x, 40) + 1 ]
xmlparsedata/R/package.R 0000644 0001762 0000144 00000012675 14020644075 014673 0 ustar ligges users
#' Parse Data of R Code as an 'XML' Tree
#'
#' Convert the output of 'utils::getParseData()' to an 'XML' tree, that is
#' searchable and easier to manipulate in general.
#'
#' @docType package
#' @name xmlparsedata
NULL
#' Convert R parse data to XML
#'
#' In recent R versions the parser can attach source code location
#' information to the parsed expressions. This information is often
#' useful for static analysis, e.g. code linting. It can be accessed
#' via the \code{\link[utils]{getParseData}} function.
#'
#' \code{xml_parse_data} converts this information to an XML tree.
#' The R parser's token names are preserved in the XML as much as
#' possible, but some of them are not valid XML tag names, so they are
#' renamed, see the \code{\link{xml_parse_token_map}} vector for the
#' mapping.
#'
#' The top XML tag is \code{}, which is a list of
#' expressions, each expression is an \code{} tag. Each tag
#' has attributes that define the location: \code{line1}, \code{col1},
#' \code{line2}, \code{col2}. These are from the \code{\link{getParseData}}
#' data frame column names.
#'
#' See an example below. See also the README at
#' \url{https://github.com/r-lib/xmlparsedata#readme}
#' for examples on how to search the XML tree with the \code{xml2} package
#' and XPath expressions.
#'
#' Note that `xml_parse_data()` silently drops all control characters
#' (0x01-0x1f) from the input, except horizontal tab (0x09) and newline
#' (0x0a), because they are invalid in XML 1.0.
#'
#' @param pretty Whether to pretty-indent the XML output. It has a small
#' overhead which probably only matters for very large source files.
#' @inheritParams utils::getParseData
#' @return An XML string representing the parse data. See details below.
#'
#' @export
#' @importFrom utils getParseData
#' @seealso \code{\link{xml_parse_token_map}} for the token names.
#' \url{https://github.com/r-lib/xmlparsedata#readme} for more
#' information and use cases.
#' @examples
#' code <- "function(a = 1, b = 2) {\n a + b\n}\n"
#' expr <- parse(text = code, keep.source = TRUE)
#'
#' # The base R way:
#' getParseData(expr)
#'
#' cat(xml_parse_data(expr, pretty = TRUE))
xml_parse_data <- function(x, includeText = NA, pretty = FALSE) {
xml_header <- paste0(
"\n\n"
)
xml_footer <- "\n\n"
## Maybe it is already a data frame, e.g. when used in lintr
if (is.data.frame(x)) {
pd <- x
} else {
pd <- getParseData(x, includeText = includeText)
}
if (!nrow(pd)) return(paste0(xml_header, xml_footer))
pd <- fix_comments(pd)
if (!is.null(pd$text)) {
pd$text <- enc2utf8(pd$text)
}
## Tags for all nodes, teminal nodes have end tags as well
pd$token <- map_token(pd$token)
## Positions, to make it easy to compare what comes first
maxcol <- max(pd$col1, pd$col2) + 1L
pd$start <- pd$line1 * maxcol + pd$col1
pd$end <- pd$line2 * maxcol + pd$col2
pd$tag <- paste0(
"<", pd$token,
" line1=\"", pd$line1,
"\" col1=\"", pd$col1,
"\" line2=\"", pd$line2,
"\" col2=\"", pd$col2,
"\" start=\"", pd$start,
"\" end=\"", pd$end,
"\">",
if (!is.null(pd$text)) xml_encode(pd$text) else "",
ifelse(pd$terminal, paste0("", pd$token, ">"), "")
)
## Add an extra terminal tag for each non-terminal one
pd2 <- pd[! pd$terminal, ]
if (nrow(pd2)) {
pd2$terminal <- TRUE
pd2$parent <- -1
pd2$line1 <- pd2$line2
pd2$col1 <- pd2$col2
pd2$line2 <- pd2$line2 - 1L
pd2$col2 <- pd2$col2 - 1L
pd2$tag <- paste0("", pd2$token, ">")
pd <- rbind(pd, pd2)
}
## Order the nodes properly
## - the terminal nodes from pd2 may be nested inside each other, when
## this happens they will have the same line1, col1, line2, col2 and
## terminal status; and 'start' is used to break ties
ord <- order(pd$line1, pd$col1, -pd$line2, -pd$col2, pd$terminal, -pd$start)
pd <- pd[ord, ]
if (pretty) {
str <- ! pd$terminal
end <- pd$parent == -1
ind <- 2L + cumsum(str * 2L + end * (-2L)) - str * 2L
xml <- paste0(spaces(ind), pd$tag, collapse = "\n")
} else {
xml <- paste(pd$tag, collapse = "\n")
}
paste0(xml_header, xml, xml_footer)
}
fix_comments <- function(pd) {
pd$parent[ pd$parent < 0 ] <- 0
pd
}
map_token <- function(token) {
map <- xml_parse_token_map[token]
ifelse(is.na(map), token, map)
}
#' Map token names of the R parser to token names in
#' \code{\link{xml_parse_data}}
#'
#' Some of the R token names are not valid XML tag names,
#' so \code{\link{xml_parse_data}} needs to replace them to create a
#' valid XML file.
#'
#' @export
#' @seealso \code{\link{xml_parse_data}}
xml_parse_token_map <- c(
"'?'" = "OP-QUESTION",
"'~'" = "OP-TILDE",
"'+'" = "OP-PLUS",
"'-'" = "OP-MINUS",
"'*'" = "OP-STAR",
"'/'" = "OP-SLASH",
"':'" = "OP-COLON",
"'^'" = "OP-CARET",
"'$'" = "OP-DOLLAR",
"'@'" = "OP-AT",
"'('" = "OP-LEFT-PAREN",
"'['" = "OP-LEFT-BRACKET",
"';'" = "OP-SEMICOLON",
"'{'" = "OP-LEFT-BRACE",
"'}'" = "OP-RIGHT-BRACE",
"')'" = "OP-RIGHT-PAREN",
"'!'" = "OP-EXCLAMATION",
"']'" = "OP-RIGHT-BRACKET",
"','" = "OP-COMMA",
"'\\\\'" = "OP-LAMBDA"
)
xml_encode <- function(x) {
x <- gsub("&", "&", x, fixed = TRUE)
x <- gsub("<", "<", x, fixed = TRUE)
x <- gsub(">", ">", x, fixed = TRUE)
# most control characters are not allowed in XML, except tab and nl
x <- gsub("[\x01-\x08\x0b-\x1f]", "", x, useBytes = TRUE)
x
}
xmlparsedata/NEWS.md 0000644 0001762 0000144 00000002312 14020657351 014036 0 ustar ligges users
# 1.0.5
* Translate `\` in lambda expression to `OP-LAMBDA` (#18 @renkun-ken).
* Drop all control characters, except horizontal tab and newline (#19).
# 1.0.4
* Translate ] tokens to `OP-RIGHT-BRACKET` instead of
`OP-RIGHT-BRACE` (#11 @AshesITR).
* `xml_parse_data()` now works if `includeText = FALSE`
(#14 @renkun-ken).
# 1.0.3
* Ensure that closing xml-tags for code expressions that end at the same
position in a file respect start-first-end-last ordering in the produced xml.
Ensures that the new `equal_assign` token in `getParseData()` for R-3.6 is
handled appropriately. #5 @russHyde
# 1.0.2
* Remove control characters `\003`, `\007`, `\010`, `\027`, as they are
not allowed in XML 1.0, #1 @GregoireGauriot
* Always convert parsed text to UTF-8
# 1.0.1
* Fix a bug when the input is already a `getParseData()` data frame.
https://github.com/jimhester/lintr filters the parsed data to include
individual functions only, but only filters the data frame, not the
underlying srcrefs, so when we call `getParseData()` on the data frame
again, we get the data for the whole source file. This is fixed now by
noticing that the input is already a data frame
# 1.0.0
First public release.
xmlparsedata/MD5 0000644 0001762 0000144 00000001112 14020661412 013236 0 ustar ligges users c81ffeeb680d1d61f3eab80216ff6812 *DESCRIPTION
ddfa93fe5d0827d872d34b7eef574617 *LICENSE
b2c9fae9076284c39dd55eac62cd4528 *NAMESPACE
63b98e498c6e9a9a2acb152bed18c17b *NEWS.md
ac335566d960fe5120f5cac137118dbb *R/package.R
74bfaec363848edc39352fda859d345b *R/utils.R
e1a021151e2532e5a7c9efa115b9d89b *README.md
1893cc5e4dbd1491b2304b798ac7b188 *man/xml_parse_data.Rd
9d813c403244b59828e7ba1ffccc2189 *man/xml_parse_token_map.Rd
f20233779409f754b38347eebe7e53f9 *man/xmlparsedata.Rd
bb1eefb84eb029c384ec6c50d5e88fc8 *tests/testthat.R
9b0a253859ba3fcf791005f81ead6e3e *tests/testthat/test.R