Skip to content

Commit ca01d67

Browse files
author
Pavel Marek
committed
[GR-29435] Provide partial support for testthat 3.0.1.
PullRequest: fastr/2613
2 parents 15a31f7 + 5bc2f2e commit ca01d67

File tree

27 files changed

+418
-44
lines changed

27 files changed

+418
-44
lines changed

com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ private static void initializeR(String[] args, boolean initMainLoop) {
103103
* has been fully initialized yet.
104104
*/
105105
@SuppressWarnings("unused")
106-
private static void setParams(boolean quietA, boolean noEcho, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
106+
private static void setParams(boolean quietA, boolean noEchoA, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
107107
boolean loadInitFileA, boolean debugInitFileA, int restoreActionA, int saveActionA, boolean noRenvironA) {
108108
context.enter();
109109
RStartParams params = RContext.getInstance().getStartParams();
110-
params.setParams(quietA, noEcho, interactiveA, verboseA, loadSiteFileA, loadInitFileA, debugInitFileA, restoreActionA, saveActionA, noRenvironA);
110+
params.setParams(quietA, noEchoA, interactiveA, verboseA, loadSiteFileA, loadInitFileA, debugInitFileA, restoreActionA, saveActionA, noRenvironA);
111111
context.leave();
112112
}
113113

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MatchNodes.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,15 +32,15 @@
3232
import com.oracle.truffle.r.runtime.RInternalError;
3333
import com.oracle.truffle.r.runtime.RRuntime;
3434
import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
35-
import com.oracle.truffle.r.runtime.data.RTypes;
3635
import com.oracle.truffle.r.runtime.data.RStringVector;
36+
import com.oracle.truffle.r.runtime.data.RTypes;
3737

3838
public final class MatchNodes {
3939

4040
@TypeSystemReference(RTypes.class)
4141
public abstract static class Match5UpCallNode extends FFIUpCallNode.Arg5 {
4242
@Specialization
43-
Object match(Object x, Object table, int noMatch, Object incomparables, @SuppressWarnings("unused") Object env,
43+
Object match(Object table, Object x, int noMatch, Object incomparables, @SuppressWarnings("unused") Object env,
4444
@Cached Match5Node match5Node) {
4545
return match5Node.execute(x, table, noMatch, incomparables);
4646
}

com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RStartParams.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@ public RStartParams(RCmdOptions options, boolean embedded) {
132132
/**
133133
* Used for R embedding, allows to alter some of the values.
134134
*/
135-
public void setParams(boolean quietA, boolean noEcho, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
135+
public void setParams(boolean quietA, boolean noEchoA, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
136136
boolean loadInitFileA, boolean debugInitFileA, @SuppressWarnings("unused") int restoreActionA, @SuppressWarnings("unused") int saveActionA, boolean noRenvironA) {
137137
quiet = quietA;
138-
this.noEcho = noEcho;
138+
noEcho = noEchoA;
139139
interactive = interactiveA;
140140
verbose = verboseA;
141141
loadSiteFile = loadSiteFileA;

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import java.io.BufferedInputStream;
3737
import java.io.BufferedOutputStream;
38+
import java.io.File;
3839
import java.io.IOException;
3940
import java.io.UncheckedIOException;
4041
import java.nio.file.CopyOption;
@@ -713,7 +714,7 @@ private static RStringVector doListFilesBody(RStringVector vec, String patternSt
713714
}
714715
file = root.relativize(file);
715716
String p = file.getPath();
716-
if (p.startsWith(vecPathString)) {
717+
if (isPathPrefixOf(p, vecPathString)) {
717718
p = p.substring(vecPathString.length());
718719
if (p.startsWith("/")) {
719720
p = p.substring(1);
@@ -762,6 +763,13 @@ private static RStringVector doListFilesBody(RStringVector vec, String patternSt
762763
}
763764
}
764765

766+
private static boolean isPathPrefixOf(String filePath, String dirPath) {
767+
if (!filePath.startsWith(dirPath)) {
768+
return false;
769+
}
770+
return dirPath.contains(File.separator) && filePath.contains(File.separator);
771+
}
772+
765773
private static String skipLeadingDotInFilename(String filePath, String fileSeparator) {
766774
String[] items = filePath.split(Pattern.quote(fileSeparator));
767775
String baseName = items[items.length - 1];

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ protected Object doGrep(String patternArg, RStringVector vector, boolean ignoreC
255255
if (!perl) {
256256
// TODO case
257257
if (!fixed) {
258-
pattern = RegExp.checkPreDefinedClasses(pattern);
258+
pattern = RegExp.transformPatternToGnurCompatible(pattern);
259259
}
260260
findAllMatches(matches, pattern, vector, fixed, ignoreCase);
261261
} else {
@@ -488,7 +488,7 @@ protected RStringVector doSub(String patternArg, String replacementArg, RStringV
488488
} else if (perl) {
489489
pcre = compilePerlPattern(pattern, ignoreCase);
490490
} else {
491-
pattern = RegExp.checkPreDefinedClasses(pattern);
491+
pattern = RegExp.transformPatternToGnurCompatible(pattern);
492492
}
493493
String preparedReplacement = null;
494494
String[] result = new String[len];
@@ -874,7 +874,7 @@ protected Object regexp(RStringVector patternArg, RStringVector vector, boolean
874874
}
875875
String pattern = patternArg.getDataAt(0);
876876
if (!perl && !fixed) {
877-
pattern = RegExp.checkPreDefinedClasses(pattern);
877+
pattern = RegExp.transformPatternToGnurCompatible(pattern);
878878
}
879879
// TODO: useBytes normally depends on the value of the parameter and (if false) on
880880
// whether the string is ASCII
@@ -1115,7 +1115,7 @@ protected Object regexp(RStringVector patternArgIn, RStringVector vector, boolea
11151115
}
11161116
RList ret = RDataFactory.createList(vector.getLength());
11171117
String pattern = patternArg.getDataAt(0);
1118-
pattern = RegExp.checkPreDefinedClasses(pattern);
1118+
pattern = RegExp.transformPatternToGnurCompatible(pattern);
11191119
// TODO: useBytes normally depends on the value of the parameter and (if false) on
11201120
// whether the string is ASCII
11211121
boolean useBytes = true;
@@ -1262,7 +1262,7 @@ protected Object regexp(RStringVector patternArg, RStringVector vector, boolean
12621262
}
12631263
String pattern = patternArg.getDataAt(0);
12641264
if (!perl && !fixed) {
1265-
pattern = RegExp.checkPreDefinedClasses(pattern);
1265+
pattern = RegExp.transformPatternToGnurCompatible(pattern);
12661266
}
12671267
// TODO: useBytes normally depends on the value of the parameter and (if false) on
12681268
// whether the string is ASCII
@@ -1552,7 +1552,7 @@ protected RList split(RStringVector x, RStringVector splitArg, boolean fixed, bo
15521552
na.enable(x);
15531553
for (int i = 0; i < splits.length; i++) {
15541554
String currentSplit = split.getDataAt(i);
1555-
splits[i] = fixed || perl ? split.getDataAt(i) : RegExp.checkPreDefinedClasses(split.getDataAt(i));
1555+
splits[i] = fixed || perl ? split.getDataAt(i) : RegExp.transformPatternToGnurCompatible(split.getDataAt(i));
15561556
if (perl) {
15571557
if (!currentSplit.isEmpty()) {
15581558
pcreSplits[i] = common.compileNode.execute(currentSplit, 0, pcreTables);

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,12 @@
3131
* Read/write a <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html">Debian
3232
* Control File</a>.
3333
*
34+
* Note that for the
35+
* <a href="https://cran.r-project.org/doc/manuals/r-release/R-exts.html#The-DESCRIPTION-file"> R
36+
* DESCRIPTION file </a> it is not specified whether or not the whitespaces in fields values (for
37+
* multiline and continuation fields) should be retained. GNU-R 4.0.3 does retain the whitespaces in
38+
* the fields by default, therefore we also retain them.
39+
*
3440
*/
3541
public class DCF {
3642

@@ -42,6 +48,9 @@ private void add(String name, String content) {
4248
fieldMap.put(name, content);
4349
}
4450

51+
/**
52+
* Note that values of fields may contain white spaces at the beginning or at the end.
53+
*/
4554
public LinkedHashMap<String, String> getFields() {
4655
return fieldMap;
4756
}
@@ -61,9 +70,13 @@ public static DCF read(String[] lines, Set<String> keepWhiteSet) {
6170
if (line.startsWith("#")) {
6271
continue;
6372
}
64-
final int wsLen = getWhiteSpaceHeadLength(line);
65-
if (wsLen > 0) {
66-
fieldContent.append('\n').append(line.substring(wsLen));
73+
if (isContinuationLine(line)) {
74+
assert fieldName != null;
75+
if (shouldStripWhiteSpaceOfField(fieldName, keepWhiteSet)) {
76+
fieldContent.append('\n').append(line.trim());
77+
} else {
78+
fieldContent.append('\n').append(line);
79+
}
6780
} else {
6881
// should start a field, finish off any current one
6982
if (fieldName != null) {
@@ -92,14 +105,9 @@ public static DCF read(String[] lines, Set<String> keepWhiteSet) {
92105
}
93106
}
94107
}
95-
// end of the field for sure
96108
if (fieldName != null) {
97-
boolean stripWhite = keepWhiteSet == null || !keepWhiteSet.contains(fieldName);
98-
String fieldAsString = fieldContent.toString();
99-
if (stripWhite) {
100-
fieldAsString = fieldAsString.trim();
101-
}
102-
fields.add(fieldName, fieldAsString);
109+
// Finish the last field
110+
fields.add(fieldName, fieldContent.toString());
103111
result.paragraphs.add(fields);
104112
}
105113
return result;
@@ -109,6 +117,16 @@ public List<Fields> getRecords() {
109117
return paragraphs;
110118
}
111119

120+
private static boolean isContinuationLine(String line) {
121+
int wsLen = getWhiteSpaceHeadLength(line);
122+
return wsLen > 0;
123+
}
124+
125+
private static boolean shouldStripWhiteSpaceOfField(String fieldName, Set<String> keepWhiteSet) {
126+
assert fieldName != null;
127+
return keepWhiteSet == null || !keepWhiteSet.contains(fieldName);
128+
}
129+
112130
private static int getWhiteSpaceHeadLength(String line) {
113131
int i;
114132
for (i = 0; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++) {

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RLocale.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -154,7 +154,7 @@ public void setLocale(RLocale locale, String value, boolean startup) {
154154
l = getLocale(value);
155155
if ((c == null && l == null) || (l == null && locale.needsLocale)) {
156156
if (startup) {
157-
RContext.getInstance().getConsole().printErrorln("Setting " + locale.name + " failed, using default");
157+
RContext.getInstance().getConsole().printErrorln("Setting " + locale.name + " to " + value + " failed, using default");
158158
} else {
159159
RError.warning(RError.SHOW_CALLER, Message.OS_REQUEST_LOCALE, value);
160160
}

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -54,14 +54,27 @@ private enum Predefined {
5454
}
5555
}
5656

57+
/**
58+
* Transforms given pattern into a pattern that can be used by the Java regexp library.
59+
*
60+
* @param pattern Pattern that can be used directly by GNU-R engine.
61+
* @return Pattern that can be used directly by Java regexp library.
62+
*/
63+
public static String transformPatternToGnurCompatible(String pattern) {
64+
String transformedPattern = pattern;
65+
transformedPattern = checkPreDefinedClasses(transformedPattern);
66+
transformedPattern = checkSpacesInQuantifiers(transformedPattern);
67+
return transformedPattern;
68+
}
69+
5770
/**
5871
* R defines some short forms of character classes. E.g. {@code [[:alnum:]]} means
5972
* {@code [0-9A-Za-z]} but independent of locale and character encoding. So we have to translate
6073
* these for use with Java regexp. TODO handle the complete set and do locale and character
6174
* encoding
6275
*/
6376
@TruffleBoundary
64-
public static String checkPreDefinedClasses(String pattern) {
77+
private static String checkPreDefinedClasses(String pattern) {
6578
String result = pattern;
6679
/*
6780
* this loop replaces "[[]" (illegal in Java regex) with "[\[]", "[\]" with "[\\]" and
@@ -139,4 +152,101 @@ public static String checkPreDefinedClasses(String pattern) {
139152
}
140153
return result;
141154
}
155+
156+
/**
157+
* GNU-R ignores some spaces in quantifiers, e.g., in "{3, }", the space in front of the last
158+
* bracket is ignored. In PCRE, this is a valid expression that is, however, not interpreted as
159+
* a quantifier. In Java regexp library, this is not a valid expression.
160+
*
161+
* @param pattern Pattern, potentially with spaces in quantifiers.
162+
* @return Pattern without spaces in quantifiers.
163+
*/
164+
@TruffleBoundary
165+
private static String checkSpacesInQuantifiers(String pattern) {
166+
boolean escapedOpeningBracket = false;
167+
int i = 0;
168+
StringBuilder sb = new StringBuilder();
169+
while (i < pattern.length()) {
170+
char currentChar = pattern.charAt(i);
171+
switch (currentChar) {
172+
case '{':
173+
if (!escapedOpeningBracket) {
174+
int idxOfClosingBracket = pattern.indexOf("}", i);
175+
if (idxOfClosingBracket == -1) {
176+
// This is a pattern syntax error, just forward the pattern as is.
177+
return pattern;
178+
}
179+
// quantifierContent is without the opening bracket.
180+
String quantifierContent = pattern.substring(i + 1, idxOfClosingBracket);
181+
int idxOfComma = quantifierContent.indexOf(",");
182+
if (idxOfComma == -1) {
183+
return pattern;
184+
}
185+
String quantifierContentBeforeComma = quantifierContent.substring(0, idxOfComma);
186+
String quantifierContentAfterComma = quantifierContent.substring(idxOfComma + 1);
187+
sb.append("{");
188+
sb.append(quantifierContentBeforeComma);
189+
sb.append(",");
190+
if (!quantifierContentAfterComma.isEmpty() && containsOnlyWhiteSpaces(quantifierContentAfterComma)) {
191+
sb.append(removeWhiteSpaces(quantifierContentAfterComma));
192+
} else {
193+
sb.append(quantifierContentAfterComma);
194+
}
195+
sb.append("}");
196+
i += 3 + quantifierContentBeforeComma.length() + quantifierContentAfterComma.length();
197+
} else {
198+
escapedOpeningBracket = false;
199+
sb.append(currentChar);
200+
i++;
201+
}
202+
break;
203+
case '\\':
204+
if (i < pattern.length() - 1 && pattern.charAt(i + 1) == '{') {
205+
escapedOpeningBracket = true;
206+
}
207+
sb.append(currentChar);
208+
i++;
209+
break;
210+
default:
211+
sb.append(currentChar);
212+
i++;
213+
break;
214+
}
215+
}
216+
return sb.toString();
217+
}
218+
219+
private static boolean containsOnlyWhiteSpaces(String string) {
220+
for (int i = 0; i < string.length(); i++) {
221+
if (!isWhiteSpace(string.charAt(i))) {
222+
return false;
223+
}
224+
}
225+
return true;
226+
}
227+
228+
private static int indexOfWhiteSpace(String string) {
229+
for (int i = 0; i < string.length(); i++) {
230+
if (isWhiteSpace(string.charAt(i))) {
231+
return i;
232+
}
233+
}
234+
return -1;
235+
}
236+
237+
private static boolean isWhiteSpace(char c) {
238+
return c == ' ';
239+
}
240+
241+
private static String removeWhiteSpaces(String string) {
242+
int idxOfWhiteSpace = indexOfWhiteSpace(string);
243+
assert idxOfWhiteSpace != -1;
244+
StringBuilder sb = new StringBuilder(string.length());
245+
for (int i = 0; i < string.length(); i++) {
246+
if (!isWhiteSpace(string.charAt(i))) {
247+
sb.append(string.charAt(i));
248+
}
249+
}
250+
return sb.toString();
251+
}
142252
}

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Mach.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Copyright (C) 1998 Ross Ihaka
33
* Copyright (c) 2000--2014, The R Core Team
4-
* Copyright (c) 2016, 2018, Oracle and/or its affiliates
4+
* Copyright (c) 2016, 2021, Oracle and/or its affiliates
55
*
66
* This program is free software; you can redistribute it and/or modify
77
* it under the terms of the GNU General Public License as published by

0 commit comments

Comments
 (0)