From 045e42b0c4306e7999537a89d57ffd852ce434f8 Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Mon, 21 Mar 2016 15:23:21 -0500 Subject: [PATCH] fixes #50: strings longer than 1000 chars can be preserved in source code now --- NEWS | 3 +++ R/utils.R | 21 ++++++++++++++++++++- tests/testit/test-tidy.R | 6 ++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 96b8e40..e97eaef 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,9 @@ BUG FIXES o `tidy_source()` writes an extra space to the last line of code (thanks, @mr-karan, #49) + o long strings (> 1000 characters) in source code can be preserved now + (thanks, @jholtman, #50) + CHANGES IN formatR VERSION 1.3 NEW FEATURES diff --git a/R/utils.R b/R/utils.R index 2dce4d4..201eb41 100644 --- a/R/utils.R +++ b/R/utils.R @@ -22,6 +22,7 @@ mask_comments = function(x, width, keep.blank.line) { d = utils::getParseData(parse_source(x)) if (nrow(d) == 0 || (n <- sum(d$terminal)) == 0) return(x) d = d[d$terminal, ] + d = fix_parse_data(d, x) d.line = d$line1; d.line2 = d$line2; d.token = d$token; d.text = d$text # move else back @@ -157,6 +158,24 @@ parse_source = if (getRversion() > '3.2.2') function(lines) { parse(text = lines, srcfile = src) } - # restore backslashes restore_bs = function(x) gsub('\\\\\\\\', '\\\\', x) + +# a workaround for the R bug (long strings are truncated in getParseData()): +# https://bugs.r-project.org/bugzilla3/show_bug.cgi?id=16354 +fix_parse_data = function(d, x) { + if (length(s <- which(d$token == 'STR_CONST')) == 0) return(d) + ws = s[grep('^\\[\\d+ (wide )?chars quoted with \'"\'\\]$', d$text[s])] + for (i in ws) { + di = d[i, , drop = FALSE] + d[i, 'text'] = get_src_string(x, di$line1, di$line2, di$col1, di$col2) + } + d +} + +get_src_string = function(x, l1, l2, c1, c2) { + if (l1 == l2) return(substr(x[l1], c1, c2)) + x[l1] = substr(x[l1], c1, nchar(x[l1])) + x[l2] = substr(x[l2], 1, c2) + paste(x[l1:l2], collapse = '\n') +} diff --git a/tests/testit/test-tidy.R b/tests/testit/test-tidy.R index b6c2bbc..0aee909 100644 --- a/tests/testit/test-tidy.R +++ b/tests/testit/test-tidy.R @@ -116,3 +116,9 @@ assert( 'the shebang is preserved', identical(tidy.res(c('#!/usr/bin/Rscript', '1+1')), c('#!/usr/bin/Rscript', '1 + 1')) ) + +x1 = paste0('x="', r <- rand_string(2000), '"') +assert( + 'Long strings (> 1000 chars) can be preserved', + tidy.res(x1) %==% paste0('x = "', r, '"') +)