diff options
author | 2016-10-11 18:04:16 +0000 | |
---|---|---|
committer | 2016-10-12 08:55:50 +0000 | |
commit | e51a4d2793de5de37190192851556b9a2554b2cb (patch) | |
tree | 46228dad254c1a2063ccf45195c1dddab464bf4f /src/main/java/com/google/devtools/build | |
parent | 1171a7fb55ae9928cd976d4c3963f4874d58f60c (diff) |
Automated cleanup
--
MOS_MIGRATED_REVID=135816105
Diffstat (limited to 'src/main/java/com/google/devtools/build')
24 files changed, 620 insertions, 493 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/AbstractComprehension.java b/src/main/java/com/google/devtools/build/lib/syntax/AbstractComprehension.java index 17777e8a8a..c5bb91ba53 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/AbstractComprehension.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/AbstractComprehension.java @@ -27,18 +27,15 @@ import com.google.devtools.build.lib.syntax.compiler.Jump.PrimitiveComparison; import com.google.devtools.build.lib.syntax.compiler.LabelAdder; import com.google.devtools.build.lib.syntax.compiler.Variable.InternalVariable; import com.google.devtools.build.lib.syntax.compiler.VariableScope; - -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.ByteCodeAppender; - import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; - import javax.annotation.Nullable; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.implementation.bytecode.ByteCodeAppender; /** * Base class for list and dict comprehension expressions. @@ -284,7 +281,7 @@ public abstract class AbstractComprehension extends Expression { StringBuilder sb = new StringBuilder(); sb.append(openingBracket).append(printExpressions()); for (Clause clause : clauses) { - sb.append(' ').append(clause.toString()); + sb.append(' ').append(clause); } sb.append(closingBracket); return sb.toString(); diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java index 942bf92657..f836704df4 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java @@ -22,18 +22,14 @@ import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature; import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; import com.google.devtools.build.lib.syntax.SkylarkList.Tuple; -import com.google.devtools.build.lib.syntax.Type.ConversionException; import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils; import com.google.devtools.build.lib.util.Preconditions; - -import net.bytebuddy.implementation.bytecode.StackManipulation; - import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; - import javax.annotation.Nullable; +import net.bytebuddy.implementation.bytecode.StackManipulation; /** * A base class for Skylark functions, whether builtin or user-defined. @@ -444,8 +440,7 @@ public abstract class BaseFunction implements SkylarkValue { } /** - * Inner call to a BaseFunction - * subclasses need to @Override this method. + * Inner call to a BaseFunction subclasses need to @Override this method. * * @param args an array of argument values sorted as per the signature. * @param ast the source code for the function if user-defined @@ -453,9 +448,8 @@ public abstract class BaseFunction implements SkylarkValue { * @throws InterruptedException may be thrown in the function implementations. */ // Don't make it abstract, so that subclasses may be defined that @Override the outer call() only. - protected Object call(Object[] args, - @Nullable FuncallExpression ast, @Nullable Environment env) - throws EvalException, ConversionException, InterruptedException { + protected Object call(Object[] args, @Nullable FuncallExpression ast, @Nullable Environment env) + throws EvalException, InterruptedException { throw new EvalException( (ast == null) ? Location.BUILTIN : ast.getLocation(), String.format("function %s not implemented", getName())); diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java index 15989eca5c..b3067e2616 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java @@ -268,6 +268,7 @@ public final class BinaryOperatorExpression extends Expression { /** * Compile a comparison oer + * * @param debugAccessors * @param code * @param leftCompiled @@ -278,8 +279,7 @@ public final class BinaryOperatorExpression extends Expression { AstAccessors debugAccessors, List<ByteCodeAppender> code, ByteCodeAppender leftCompiled, - ByteCodeAppender rightCompiled) - throws Error { + ByteCodeAppender rightCompiled) { PrimitiveComparison byteCodeOperator = PrimitiveComparison.forOperator(operator); code.add(leftCompiled); code.add(rightCompiled); @@ -408,7 +408,7 @@ public final class BinaryOperatorExpression extends Expression { // Java: -7/3 = -2 // Python: -7/3 = -3 // We want to follow Python semantics, so we use float division and round down. - return (int) Math.floor(new Double((Integer) lval) / (Integer) rval); + return (int) Math.floor(Double.valueOf((Integer) lval) / (Integer) rval); } throw typeException(lval, rval, Operator.DIVIDE, location); } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java index b3a763fd41..b050b2ec48 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/BuiltinFunction.java @@ -197,7 +197,7 @@ public class BuiltinFunction extends BaseFunction { private static String stacktraceToString(StackTraceElement[] elts) { StringBuilder b = new StringBuilder(); for (StackTraceElement e : elts) { - b.append(e.toString()); + b.append(e); b.append("\n"); } return b.toString(); diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java index a1dd6ea11a..d03aa27fe2 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java @@ -328,11 +328,11 @@ public final class Environment implements Freezable { private boolean isSkylark; /** - * Is this Environment being executed during the loading phase? - * Many builtin functions are only enabled during the loading phase, and check this flag. + * Is this Environment being executed during the loading phase? Many builtin functions are only + * enabled during the loading phase, and check this flag. * TODO(laurentlb): Remove from Environment */ - private Phase phase; + private final Phase phase; /** * When in a lexical (Skylark) Frame, this set contains the variable names that are global, diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java index ac0eb9c4a2..e498b9a54b 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java @@ -19,7 +19,6 @@ import com.google.devtools.build.lib.syntax.compiler.Jump; import com.google.devtools.build.lib.syntax.compiler.LoopLabels; import com.google.devtools.build.lib.syntax.compiler.VariableScope; import com.google.devtools.build.lib.util.Preconditions; - import net.bytebuddy.implementation.bytecode.ByteCodeAppender; /** @@ -30,7 +29,7 @@ public final class FlowStatement extends Statement { BREAK("break"), CONTINUE("continue"); - private String name; + private final String name; private Kind(String name) { this.name = name; diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FormatParser.java b/src/main/java/com/google/devtools/build/lib/syntax/FormatParser.java index b5ae740c06..64ad8900ca 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/FormatParser.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/FormatParser.java @@ -15,7 +15,6 @@ package com.google.devtools.build.lib.syntax; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.events.Location; - import java.util.List; import java.util.Map; @@ -200,11 +199,10 @@ public final class FormatParser { * * @param key Key to be converted * @param history Helper object that tracks information about previously seen positional - * replacement fields + * replacement fields * @return The integer equivalent of the key */ - protected int parsePositional(String key, History history) - throws NumberFormatException, EvalException { + protected int parsePositional(String key, History history) throws EvalException { int result = -1; try { diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java index c476033d11..131d022f4c 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java @@ -805,8 +805,7 @@ public final class FuncallExpression extends Expression { String name = arg.getName(); if (name != null && name.equals("name")) { Expression expr = arg.getValue(); - return (expr != null && expr instanceof StringLiteral) - ? ((StringLiteral) expr).getValue() : null; + return (expr instanceof StringLiteral) ? ((StringLiteral) expr).getValue() : null; } } } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FunctionSignature.java b/src/main/java/com/google/devtools/build/lib/syntax/FunctionSignature.java index b858d35ed5..7643201e92 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/FunctionSignature.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/FunctionSignature.java @@ -21,14 +21,13 @@ import com.google.common.collect.Lists; import com.google.devtools.build.lib.syntax.SkylarkList.Tuple; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.util.StringCanonicalizer; - import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; - import javax.annotation.Nullable; /** @@ -142,9 +141,7 @@ public abstract class FunctionSignature implements Serializable { public List<Class<?>> toClasses() { List<Class<?>> parameters = new ArrayList<>(); - for (int i = 0; i < getAllNamed(); i++) { - parameters.add(Object.class); - } + parameters.addAll(Collections.nCopies(getAllNamed(), Object.class)); if (hasStarArg()) { parameters.add(Tuple.class); } @@ -156,10 +153,8 @@ public abstract class FunctionSignature implements Serializable { } } - /** - * Names of a FunctionSignature - */ - private static Interner<ImmutableList<String>> namesInterner = Interners.newWeakInterner(); + /** Names of a FunctionSignature */ + private static final Interner<ImmutableList<String>> namesInterner = Interners.newWeakInterner(); /** Intern a list of names */ public static ImmutableList<String> names(List<String> names) { @@ -173,7 +168,7 @@ public abstract class FunctionSignature implements Serializable { } // Interner - private static Interner<FunctionSignature> signatureInterner = Interners.newWeakInterner(); + private static final Interner<FunctionSignature> signatureInterner = Interners.newWeakInterner(); /** * Signatures proper. diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java index d8b34be169..71a3fd1b41 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.syntax; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.events.Event; @@ -59,7 +60,7 @@ public final class Lexer { private final EventHandler eventHandler; // Input buffer and position - private char[] buffer; + private final char[] buffer; private int pos; /** @@ -829,7 +830,7 @@ public final class Lexer { } // Like Python, always end with a NEWLINE token, even if no '\n' in input: - if (tokens.isEmpty() || tokens.get(tokens.size() - 1).kind != TokenKind.NEWLINE) { + if (tokens.isEmpty() || Iterables.getLast(tokens).kind != TokenKind.NEWLINE) { addToken(new Token(TokenKind.NEWLINE, pos - 1, pos)); } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java index 8789e68a5d..d16a83daf1 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java @@ -21,13 +21,11 @@ import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.util.StringUtilities; import com.google.devtools.build.lib.vfs.PathFragment; - import java.io.Serializable; import java.nio.CharBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -114,7 +112,8 @@ public abstract class LineNumberTable implements Serializable { if (offset < 0) { throw new IllegalStateException("Illegal position: " + offset); } - int lowBoundary = 1, highBoundary = linestart.length - 1; + int lowBoundary = 1; + int highBoundary = linestart.length - 1; while (true) { if ((highBoundary - lowBoundary) <= 1) { if (linestart[highBoundary] > offset) { @@ -194,13 +193,14 @@ public abstract class LineNumberTable implements Serializable { } } - private static Ordering<SingleHashLine> hashOrdering = Ordering.from( - new Comparator<SingleHashLine>() { + private static final Ordering<SingleHashLine> hashOrdering = + new Ordering<SingleHashLine>() { + @Override public int compare(SingleHashLine o1, SingleHashLine o2) { return Integer.compare(o1.offset, o2.offset); } - }); + }; private static final Pattern pattern = Pattern.compile("\n#line ([0-9]+) \"([^\"\\n]+)\""); diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java index 21baa82ff5..843d8e90a8 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java @@ -241,88 +241,126 @@ public class MethodLibrary { } }; - @SkylarkSignature(name = "replace", objectType = StringModule.class, returnType = String.class, - doc = "Returns a copy of the string in which the occurrences " - + "of <code>old</code> have been replaced with <code>new</code>, optionally restricting " - + "the number of replacements to <code>maxsplit</code>.", - parameters = { - @Param(name = "self", type = String.class, doc = "This string."), - @Param(name = "old", type = String.class, doc = "The string to be replaced."), - @Param(name = "new", type = String.class, doc = "The string to replace with."), - @Param(name = "maxsplit", type = Integer.class, noneable = true, defaultValue = "None", - doc = "The maximum number of replacements.")}, - useLocation = true) - private static final BuiltinFunction replace = new BuiltinFunction("replace") { - public String invoke(String self, String oldString, String newString, Object maxSplitO, - Location loc) throws EvalException, ConversionException { - StringBuffer sb = new StringBuffer(); - Integer maxSplit = Type.INTEGER.convertOptional( - maxSplitO, "'maxsplit' argument of 'replace'", /*label*/null, Integer.MAX_VALUE); - try { - Matcher m = Pattern.compile(oldString, Pattern.LITERAL).matcher(self); - for (int i = 0; i < maxSplit && m.find(); i++) { - m.appendReplacement(sb, Matcher.quoteReplacement(newString)); + @SkylarkSignature( + name = "replace", + objectType = StringModule.class, + returnType = String.class, + doc = + "Returns a copy of the string in which the occurrences " + + "of <code>old</code> have been replaced with <code>new</code>, optionally " + + "restricting the number of replacements to <code>maxsplit</code>.", + parameters = { + @Param(name = "self", type = String.class, doc = "This string."), + @Param(name = "old", type = String.class, doc = "The string to be replaced."), + @Param(name = "new", type = String.class, doc = "The string to replace with."), + @Param( + name = "maxsplit", + type = Integer.class, + noneable = true, + defaultValue = "None", + doc = "The maximum number of replacements." + ) + }, + useLocation = true + ) + private static final BuiltinFunction replace = + new BuiltinFunction("replace") { + public String invoke( + String self, String oldString, String newString, Object maxSplitO, Location loc) + throws EvalException { + StringBuffer sb = new StringBuffer(); + Integer maxSplit = + Type.INTEGER.convertOptional( + maxSplitO, "'maxsplit' argument of 'replace'", /*label*/ null, Integer.MAX_VALUE); + try { + Matcher m = Pattern.compile(oldString, Pattern.LITERAL).matcher(self); + for (int i = 0; i < maxSplit && m.find(); i++) { + m.appendReplacement(sb, Matcher.quoteReplacement(newString)); + } + m.appendTail(sb); + } catch (IllegalStateException e) { + throw new EvalException(loc, e.getMessage() + " in call to replace"); + } + return sb.toString(); } - m.appendTail(sb); - } catch (IllegalStateException e) { - throw new EvalException(loc, e.getMessage() + " in call to replace"); - } - return sb.toString(); - } - }; + }; - @SkylarkSignature(name = "split", objectType = StringModule.class, - returnType = MutableList.class, - doc = "Returns a list of all the words in the string, using <code>sep</code> " - + "as the separator, optionally limiting the number of splits to <code>maxsplit</code>.", - parameters = { - @Param(name = "self", type = String.class, doc = "This string."), - @Param(name = "sep", type = String.class, doc = "The string to split on."), - @Param(name = "maxsplit", type = Integer.class, noneable = true, defaultValue = "None", - doc = "The maximum number of splits.")}, - useEnvironment = true, - useLocation = true) - private static final BuiltinFunction split = new BuiltinFunction("split") { - public MutableList<String> invoke(String self, String sep, Object maxSplitO, Location loc, - Environment env) throws ConversionException, EvalException { - int maxSplit = Type.INTEGER.convertOptional( - maxSplitO, "'split' argument of 'split'", /*label*/null, -2); - // + 1 because the last result is the remainder, and default of -2 so that after +1 it's -1 - String[] ss = Pattern.compile(sep, Pattern.LITERAL).split(self, maxSplit + 1); - return MutableList.of(env, ss); - } - }; + @SkylarkSignature( + name = "split", + objectType = StringModule.class, + returnType = MutableList.class, + doc = + "Returns a list of all the words in the string, using <code>sep</code> as the separator, " + + "optionally limiting the number of splits to <code>maxsplit</code>.", + parameters = { + @Param(name = "self", type = String.class, doc = "This string."), + @Param(name = "sep", type = String.class, doc = "The string to split on."), + @Param( + name = "maxsplit", + type = Integer.class, + noneable = true, + defaultValue = "None", + doc = "The maximum number of splits." + ) + }, + useEnvironment = true, + useLocation = true + ) + private static final BuiltinFunction split = + new BuiltinFunction("split") { + public MutableList<String> invoke( + String self, String sep, Object maxSplitO, Location loc, Environment env) + throws EvalException { + int maxSplit = + Type.INTEGER.convertOptional( + maxSplitO, "'split' argument of 'split'", /*label*/ null, -2); + // + 1 because the last result is the remainder. The default is -2 so that after +1, + // it becomes -1. + String[] ss = Pattern.compile(sep, Pattern.LITERAL).split(self, maxSplit + 1); + return MutableList.of(env, ss); + } + }; - @SkylarkSignature(name = "rsplit", objectType = StringModule.class, - returnType = MutableList.class, - doc = "Returns a list of all the words in the string, using <code>sep</code> " - + "as the separator, optionally limiting the number of splits to <code>maxsplit</code>. " - + "Except for splitting from the right, this method behaves like split().", - parameters = { - @Param(name = "self", type = String.class, doc = "This string."), - @Param(name = "sep", type = String.class, doc = "The string to split on."), - @Param(name = "maxsplit", type = Integer.class, noneable = true, - defaultValue = "None", doc = "The maximum number of splits.")}, - useEnvironment = true, - useLocation = true) - private static final BuiltinFunction rsplit = new BuiltinFunction("rsplit") { - @SuppressWarnings("unused") - public MutableList<String> invoke( - String self, String sep, Object maxSplitO, Location loc, Environment env) - throws ConversionException, EvalException { - int maxSplit = - Type.INTEGER.convertOptional(maxSplitO, "'split' argument of 'split'", null, -1); - try { - return stringRSplit(self, sep, maxSplit, env); - } catch (IllegalArgumentException ex) { - throw new EvalException(loc, ex); - } - } - }; + @SkylarkSignature( + name = "rsplit", + objectType = StringModule.class, + returnType = MutableList.class, + doc = + "Returns a list of all the words in the string, using <code>sep</code> as the separator, " + + "optionally limiting the number of splits to <code>maxsplit</code>. " + + "Except for splitting from the right, this method behaves like split().", + parameters = { + @Param(name = "self", type = String.class, doc = "This string."), + @Param(name = "sep", type = String.class, doc = "The string to split on."), + @Param( + name = "maxsplit", + type = Integer.class, + noneable = true, + defaultValue = "None", + doc = "The maximum number of splits." + ) + }, + useEnvironment = true, + useLocation = true + ) + private static final BuiltinFunction rsplit = + new BuiltinFunction("rsplit") { + @SuppressWarnings("unused") + public MutableList<String> invoke( + String self, String sep, Object maxSplitO, Location loc, Environment env) + throws EvalException { + int maxSplit = + Type.INTEGER.convertOptional(maxSplitO, "'split' argument of 'split'", null, -1); + try { + return stringRSplit(self, sep, maxSplit, env); + } catch (IllegalArgumentException ex) { + throw new EvalException(loc, ex); + } + } + }; /** - * Splits the given string into a list of words, using {@code separator} as a - * delimiter. + * Splits the given string into a list of words, using {@code separator} as a delimiter. * * <p>At most {@code maxSplits} will be performed, going from right to left. * @@ -333,8 +371,7 @@ public class MethodLibrary { * @throws IllegalArgumentException */ private static MutableList<String> stringRSplit( - String input, String separator, int maxSplits, Environment env) - throws IllegalArgumentException { + String input, String separator, int maxSplits, Environment env) { if (separator.isEmpty()) { throw new IllegalArgumentException("Empty separator"); } @@ -429,26 +466,23 @@ public class MethodLibrary { } /** - * Splits the input string at the {first|last} occurrence of the given separator - * and returns the resulting partition as a three-tuple of Strings, contained - * in a {@code MutableList}. + * Splits the input string at the {first|last} occurrence of the given separator and returns the + * resulting partition as a three-tuple of Strings, contained in a {@code MutableList}. * - * <p>If the input string does not contain the separator, the tuple will - * consist of the original input string and two empty strings. + * <p>If the input string does not contain the separator, the tuple will consist of the original + * input string and two empty strings. * - * <p>This method emulates the behavior of Python's str.partition() and - * str.rpartition(), depending on the value of the {@code forward} flag. + * <p>This method emulates the behavior of Python's str.partition() and str.rpartition(), + * depending on the value of the {@code forward} flag. * * @param input The input string * @param separator The string to split on - * @param forward A flag that controls whether the input string is split around - * the first ({@code true}) or last ({@code false}) occurrence of the separator. + * @param forward A flag that controls whether the input string is split around the first ({@code + * true}) or last ({@code false}) occurrence of the separator. * @return A three-tuple (List) of the form [part_before_separator, separator, - * part_after_separator]. - * + * part_after_separator]. */ - private static List<String> stringPartition(String input, String separator, boolean forward) - throws IllegalArgumentException { + private static List<String> stringPartition(String input, String separator, boolean forward) { if (separator.isEmpty()) { throw new IllegalArgumentException("Empty separator"); } @@ -584,53 +618,85 @@ public class MethodLibrary { } }; - @SkylarkSignature(name = "rindex", objectType = StringModule.class, returnType = Integer.class, - doc = "Returns the last index where <code>sub</code> is found, " - + "or raises an error if no such index exists, optionally restricting to " - + "[<code>start</code>:<code>end</code>], " - + "<code>start</code> being inclusive and <code>end</code> being exclusive.", - parameters = { - @Param(name = "self", type = String.class, doc = "This string."), - @Param(name = "sub", type = String.class, doc = "The substring to find."), - @Param(name = "start", type = Integer.class, defaultValue = "0", - doc = "Restrict to search from this position."), - @Param(name = "end", type = Integer.class, noneable = true, defaultValue = "None", - doc = "optional position before which to restrict to search.")}, - useLocation = true) - private static final BuiltinFunction rindex = new BuiltinFunction("rindex") { - public Integer invoke(String self, String sub, Integer start, Object end, - Location loc) throws EvalException, ConversionException { - int res = stringFind(false, self, sub, start, end, "'end' argument to rindex"); - if (res < 0) { - throw new EvalException(loc, Printer.format("substring %r not found in %r", sub, self)); - } - return res; - } - }; + @SkylarkSignature( + name = "rindex", + objectType = StringModule.class, + returnType = Integer.class, + doc = + "Returns the last index where <code>sub</code> is found, " + + "or raises an error if no such index exists, optionally restricting to " + + "[<code>start</code>:<code>end</code>], " + + "<code>start</code> being inclusive and <code>end</code> being exclusive.", + parameters = { + @Param(name = "self", type = String.class, doc = "This string."), + @Param(name = "sub", type = String.class, doc = "The substring to find."), + @Param( + name = "start", + type = Integer.class, + defaultValue = "0", + doc = "Restrict to search from this position." + ), + @Param( + name = "end", + type = Integer.class, + noneable = true, + defaultValue = "None", + doc = "optional position before which to restrict to search." + ) + }, + useLocation = true + ) + private static final BuiltinFunction rindex = + new BuiltinFunction("rindex") { + public Integer invoke(String self, String sub, Integer start, Object end, Location loc) + throws EvalException { + int res = stringFind(false, self, sub, start, end, "'end' argument to rindex"); + if (res < 0) { + throw new EvalException(loc, Printer.format("substring %r not found in %r", sub, self)); + } + return res; + } + }; - @SkylarkSignature(name = "index", objectType = StringModule.class, returnType = Integer.class, - doc = "Returns the first index where <code>sub</code> is found, " - + "or raises an error if no such index exists, optionally restricting to " - + "[<code>start</code>:<code>end]</code>, " - + "<code>start</code> being inclusive and <code>end</code> being exclusive.", - parameters = { - @Param(name = "self", type = String.class, doc = "This string."), - @Param(name = "sub", type = String.class, doc = "The substring to find."), - @Param(name = "start", type = Integer.class, defaultValue = "0", - doc = "Restrict to search from this position."), - @Param(name = "end", type = Integer.class, noneable = true, defaultValue = "None", - doc = "optional position before which to restrict to search.")}, - useLocation = true) - private static final BuiltinFunction index = new BuiltinFunction("index") { - public Integer invoke(String self, String sub, Integer start, Object end, - Location loc) throws EvalException, ConversionException { - int res = stringFind(true, self, sub, start, end, "'end' argument to index"); - if (res < 0) { - throw new EvalException(loc, Printer.format("substring %r not found in %r", sub, self)); - } - return res; - } - }; + @SkylarkSignature( + name = "index", + objectType = StringModule.class, + returnType = Integer.class, + doc = + "Returns the first index where <code>sub</code> is found, " + + "or raises an error if no such index exists, optionally restricting to " + + "[<code>start</code>:<code>end]</code>, " + + "<code>start</code> being inclusive and <code>end</code> being exclusive.", + parameters = { + @Param(name = "self", type = String.class, doc = "This string."), + @Param(name = "sub", type = String.class, doc = "The substring to find."), + @Param( + name = "start", + type = Integer.class, + defaultValue = "0", + doc = "Restrict to search from this position." + ), + @Param( + name = "end", + type = Integer.class, + noneable = true, + defaultValue = "None", + doc = "optional position before which to restrict to search." + ) + }, + useLocation = true + ) + private static final BuiltinFunction index = + new BuiltinFunction("index") { + public Integer invoke(String self, String sub, Integer start, Object end, Location loc) + throws EvalException { + int res = stringFind(true, self, sub, start, end, "'end' argument to index"); + if (res < 0) { + throw new EvalException(loc, Printer.format("substring %r not found in %r", sub, self)); + } + return res; + } + }; @SkylarkSignature(name = "splitlines", objectType = StringModule.class, returnType = SkylarkList.class, @@ -857,39 +923,57 @@ public class MethodLibrary { // In Python, formatting is very complex. // We handle here the simplest case which provides most of the value of the function. // https://docs.python.org/3/library/string.html#formatstrings - @SkylarkSignature(name = "format", objectType = StringModule.class, returnType = String.class, - doc = "Perform string interpolation. Format strings contain replacement fields " - + "surrounded by curly braces <code>{}</code>. Anything that is not contained " - + "in braces is considered literal text, which is copied unchanged to the output." - + "If you need to include a brace character in the literal text, it can be " - + "escaped by doubling: <code>{{</code> and <code>}}</code>" - + "A replacement field can be either a name, a number, or empty. Values are " - + "converted to strings using the <a href=\"globals.html#str\">str</a> function." - + "<pre class=\"language-python\">" - + "# Access in order:\n" - + "\"{} < {}\".format(4, 5) == \"4 < 5\"\n" - + "# Access by position:\n" - + "\"{1}, {0}\".format(2, 1) == \"1, 2\"\n" - + "# Access by name:\n" - + "\"x{key}x\".format(key = 2) == \"x2x\"</pre>\n", - parameters = { - @Param(name = "self", type = String.class, doc = "This string."), - }, - extraPositionals = - @Param(name = "args", type = SkylarkList.class, defaultValue = "()", - doc = "List of arguments"), - extraKeywords = @Param(name = "kwargs", type = SkylarkDict.class, defaultValue = "{}", - doc = "Dictionary of arguments"), - useLocation = true) - private static final BuiltinFunction format = new BuiltinFunction("format") { - @SuppressWarnings("unused") - public String invoke(String self, SkylarkList<Object> args, SkylarkDict<?, ?> kwargs, - Location loc) - throws ConversionException, EvalException { - return new FormatParser(loc).format( - self, args.getImmutableList(), kwargs.getContents(String.class, Object.class, "kwargs")); - } - }; + @SkylarkSignature( + name = "format", + objectType = StringModule.class, + returnType = String.class, + doc = + "Perform string interpolation. Format strings contain replacement fields " + + "surrounded by curly braces <code>{}</code>. Anything that is not contained " + + "in braces is considered literal text, which is copied unchanged to the output." + + "If you need to include a brace character in the literal text, it can be " + + "escaped by doubling: <code>{{</code> and <code>}}</code>" + + "A replacement field can be either a name, a number, or empty. Values are " + + "converted to strings using the <a href=\"globals.html#str\">str</a> function." + + "<pre class=\"language-python\">" + + "# Access in order:\n" + + "\"{} < {}\".format(4, 5) == \"4 < 5\"\n" + + "# Access by position:\n" + + "\"{1}, {0}\".format(2, 1) == \"1, 2\"\n" + + "# Access by name:\n" + + "\"x{key}x\".format(key = 2) == \"x2x\"</pre>\n", + parameters = { + @Param(name = "self", type = String.class, doc = "This string."), + }, + extraPositionals = + @Param( + name = "args", + type = SkylarkList.class, + defaultValue = "()", + doc = "List of arguments" + ), + extraKeywords = + @Param( + name = "kwargs", + type = SkylarkDict.class, + defaultValue = "{}", + doc = "Dictionary of arguments" + ), + useLocation = true + ) + private static final BuiltinFunction format = + new BuiltinFunction("format") { + @SuppressWarnings("unused") + public String invoke( + String self, SkylarkList<Object> args, SkylarkDict<?, ?> kwargs, Location loc) + throws EvalException { + return new FormatParser(loc) + .format( + self, + args.getImmutableList(), + kwargs.getContents(String.class, Object.class, "kwargs")); + } + }; @SkylarkSignature(name = "startswith", objectType = StringModule.class, returnType = Boolean.class, @@ -1087,11 +1171,10 @@ public class MethodLibrary { private static final BuiltinFunction sorted = new BuiltinFunction("sorted") { public <E> MutableList<E> invoke(Object self, Location loc, Environment env) - throws EvalException, ConversionException { + throws EvalException { try { return new MutableList( - EvalUtils.SKYLARK_COMPARATOR.sortedCopy(EvalUtils.toCollection(self, loc)), - env); + EvalUtils.SKYLARK_COMPARATOR.sortedCopy(EvalUtils.toCollection(self, loc)), env); } catch (EvalUtils.ComparisonException e) { throw new EvalException(loc, e); } @@ -1142,11 +1225,13 @@ public class MethodLibrary { @Param(name = "item", type = Object.class, doc = "Item to add at the end.") }, useLocation = true, - useEnvironment = true) + useEnvironment = true + ) private static final BuiltinFunction append = new BuiltinFunction("append") { - public Runtime.NoneType invoke(MutableList<Object> self, Object item, - Location loc, Environment env) throws EvalException, ConversionException { + public Runtime.NoneType invoke( + MutableList<Object> self, Object item, Location loc, Environment env) + throws EvalException { self.add(item, loc, env); return Runtime.NONE; } @@ -1169,7 +1254,7 @@ public class MethodLibrary { new BuiltinFunction("insert") { public Runtime.NoneType invoke( MutableList<Object> self, Integer index, Object item, Location loc, Environment env) - throws EvalException, ConversionException { + throws EvalException { self.add(clampIndex(index, self.size()), item, loc, env); return Runtime.NONE; } @@ -1191,7 +1276,7 @@ public class MethodLibrary { new BuiltinFunction("extend") { public Runtime.NoneType invoke( MutableList<Object> self, SkylarkList<Object> items, Location loc, Environment env) - throws EvalException, ConversionException { + throws EvalException { self.addAll(items, loc, env); return Runtime.NONE; } @@ -1441,39 +1526,46 @@ public class MethodLibrary { } }; - @SkylarkSignature(name = "values", objectType = SkylarkDict.class, - returnType = MutableList.class, - doc = "Returns the list of values. Dictionaries are always sorted by their keys:" - + "<pre class=\"language-python\">" - + "{2: \"a\", 4: \"b\", 1: \"c\"}.values() == [\"c\", \"a\", \"b\"]</pre>\n", - parameters = {@Param(name = "self", type = SkylarkDict.class, doc = "This dict.")}, - useEnvironment = true) - private static final BuiltinFunction values = new BuiltinFunction("values") { - public MutableList<?> invoke(SkylarkDict<?, ?> self, - Environment env) throws EvalException, ConversionException { - return new MutableList(self.values(), env); - } - }; + @SkylarkSignature( + name = "values", + objectType = SkylarkDict.class, + returnType = MutableList.class, + doc = + "Returns the list of values. Dictionaries are always sorted by their keys:" + + "<pre class=\"language-python\">" + + "{2: \"a\", 4: \"b\", 1: \"c\"}.values() == [\"c\", \"a\", \"b\"]</pre>\n", + parameters = {@Param(name = "self", type = SkylarkDict.class, doc = "This dict.")}, + useEnvironment = true + ) + private static final BuiltinFunction values = + new BuiltinFunction("values") { + public MutableList<?> invoke(SkylarkDict<?, ?> self, Environment env) throws EvalException { + return new MutableList(self.values(), env); + } + }; - @SkylarkSignature(name = "items", objectType = SkylarkDict.class, - returnType = MutableList.class, - doc = "Returns the list of key-value tuples. Dictionaries are always sorted by their keys:" - + "<pre class=\"language-python\">" - + "{2: \"a\", 4: \"b\", 1: \"c\"}.items() == [(1, \"c\"), (2, \"a\"), (4, \"b\")]" - + "</pre>\n", - parameters = { - @Param(name = "self", type = SkylarkDict.class, doc = "This dict.")}, - useEnvironment = true) - private static final BuiltinFunction items = new BuiltinFunction("items") { - public MutableList<?> invoke(SkylarkDict<?, ?> self, - Environment env) throws EvalException, ConversionException { - List<Object> list = Lists.newArrayListWithCapacity(self.size()); - for (Map.Entry<?, ?> entries : self.entrySet()) { - list.add(Tuple.of(entries.getKey(), entries.getValue())); - } - return new MutableList(list, env); - } - }; + @SkylarkSignature( + name = "items", + objectType = SkylarkDict.class, + returnType = MutableList.class, + doc = + "Returns the list of key-value tuples. Dictionaries are always sorted by their keys:" + + "<pre class=\"language-python\">" + + "{2: \"a\", 4: \"b\", 1: \"c\"}.items() == [(1, \"c\"), (2, \"a\"), (4, \"b\")]" + + "</pre>\n", + parameters = {@Param(name = "self", type = SkylarkDict.class, doc = "This dict.")}, + useEnvironment = true + ) + private static final BuiltinFunction items = + new BuiltinFunction("items") { + public MutableList<?> invoke(SkylarkDict<?, ?> self, Environment env) throws EvalException { + List<Object> list = Lists.newArrayListWithCapacity(self.size()); + for (Map.Entry<?, ?> entries : self.entrySet()) { + list.add(Tuple.of(entries.getKey(), entries.getValue())); + } + return new MutableList(list, env); + } + }; @SkylarkSignature(name = "keys", objectType = SkylarkDict.class, returnType = MutableList.class, @@ -1680,33 +1772,47 @@ public class MethodLibrary { }; @SkylarkSignature( - name = "set", - returnType = SkylarkNestedSet.class, - doc = "Creates a <a href=\"set.html\">set</a> from the <code>items</code>. " - + "The set supports nesting other sets of the same element type in it. " - + "A desired <a href=\"set.html\">iteration order</a> can also be specified.<br>" - + "Examples:<br><pre class=\"language-python\">set([\"a\", \"b\"])\n" - + "set([1, 2, 3], order=\"compile\")</pre>", - parameters = { - @Param(name = "items", type = Object.class, defaultValue = "[]", - doc = "The items to initialize the set with. May contain both standalone items " - + "and other sets."), - @Param(name = "order", type = String.class, defaultValue = "\"stable\"", - doc = "The ordering strategy for the set if it's nested, " - + "possible values are: <code>stable</code> (default), <code>compile</code>, " - + "<code>link</code> or <code>naive_link</code>. An explanation of the " - + "values can be found <a href=\"set.html\">here</a>.")}, - useLocation = true) - private static final BuiltinFunction set = new BuiltinFunction("set") { - public SkylarkNestedSet invoke(Object items, String order, - Location loc) throws EvalException, ConversionException { - try { - return new SkylarkNestedSet(Order.parse(order), items, loc); - } catch (IllegalArgumentException ex) { - throw new EvalException(loc, ex); - } - } - }; + name = "set", + returnType = SkylarkNestedSet.class, + doc = + "Creates a <a href=\"set.html\">set</a> from the <code>items</code>. " + + "The set supports nesting other sets of the same element type in it. " + + "A desired <a href=\"set.html\">iteration order</a> can also be specified.<br>" + + "Examples:<br><pre class=\"language-python\">set([\"a\", \"b\"])\n" + + "set([1, 2, 3], order=\"compile\")</pre>", + parameters = { + @Param( + name = "items", + type = Object.class, + defaultValue = "[]", + doc = + "The items to initialize the set with. May contain both standalone items " + + "and other sets." + ), + @Param( + name = "order", + type = String.class, + defaultValue = "\"stable\"", + doc = + "The ordering strategy for the set if it's nested, " + + "possible values are: <code>stable</code> (default), <code>compile</code>, " + + "<code>link</code> or <code>naive_link</code>. An explanation of the " + + "values can be found <a href=\"set.html\">here</a>." + ) + }, + useLocation = true + ) + private static final BuiltinFunction set = + new BuiltinFunction("set") { + public SkylarkNestedSet invoke(Object items, String order, Location loc) + throws EvalException { + try { + return new SkylarkNestedSet(Order.parse(order), items, loc); + } catch (IllegalArgumentException ex) { + throw new EvalException(loc, ex); + } + } + }; @SkylarkSignature( name = "dict", @@ -1791,26 +1897,28 @@ public class MethodLibrary { } }; - @SkylarkSignature(name = "enumerate", returnType = MutableList.class, - doc = "Returns a list of pairs (two-element tuples), with the index (int) and the item from" - + " the input list.\n<pre class=\"language-python\">" - + "enumerate([24, 21, 84]) == [(0, 24), (1, 21), (2, 84)]</pre>\n", - parameters = { - @Param(name = "list", type = SkylarkList.class, doc = "input list") - }, - useEnvironment = true) - private static final BuiltinFunction enumerate = new BuiltinFunction("enumerate") { - public MutableList<?> invoke(SkylarkList<?> input, Environment env) - throws EvalException, ConversionException { - int count = 0; - List<SkylarkList<?>> result = Lists.newArrayList(); - for (Object obj : input) { - result.add(Tuple.of(count, obj)); - count++; - } - return new MutableList(result, env); - } - }; + @SkylarkSignature( + name = "enumerate", + returnType = MutableList.class, + doc = + "Returns a list of pairs (two-element tuples), with the index (int) and the item from" + + " the input list.\n<pre class=\"language-python\">" + + "enumerate([24, 21, 84]) == [(0, 24), (1, 21), (2, 84)]</pre>\n", + parameters = {@Param(name = "list", type = SkylarkList.class, doc = "input list")}, + useEnvironment = true + ) + private static final BuiltinFunction enumerate = + new BuiltinFunction("enumerate") { + public MutableList<?> invoke(SkylarkList<?> input, Environment env) throws EvalException { + int count = 0; + List<SkylarkList<?>> result = Lists.newArrayList(); + for (Object obj : input) { + result.add(Tuple.of(count, obj)); + count++; + } + return new MutableList(result, env); + } + }; @SkylarkSignature(name = "hash", returnType = Integer.class, doc = "Return a hash value for a string. This is computed deterministically using the same " @@ -1830,59 +1938,79 @@ public class MethodLibrary { } }; - @SkylarkSignature(name = "range", returnType = MutableList.class, - doc = "Creates a list where items go from <code>start</code> to <code>stop</code>, using a " - + "<code>step</code> increment. If a single argument is provided, items will " - + "range from 0 to that element." - + "<pre class=\"language-python\">range(4) == [0, 1, 2, 3]\n" - + "range(3, 9, 2) == [3, 5, 7]\n" - + "range(3, 0, -1) == [3, 2, 1]</pre>", - parameters = { - @Param(name = "start_or_stop", type = Integer.class, - doc = "Value of the start element if stop is provided, " - + "otherwise value of stop and the actual start is 0"), - @Param(name = "stop_or_none", type = Integer.class, noneable = true, defaultValue = "None", - doc = "optional index of the first item <i>not</i> to be included in the " - + "resulting list; generation of the list stops before <code>stop</code> is reached."), - @Param(name = "step", type = Integer.class, defaultValue = "1", - doc = "The increment (default is 1). It may be negative.")}, - useLocation = true, - useEnvironment = true) - private static final BuiltinFunction range = new BuiltinFunction("range") { - public MutableList<?> invoke(Integer startOrStop, Object stopOrNone, Integer step, - Location loc, Environment env) - throws EvalException, ConversionException { - int start; - int stop; - if (stopOrNone == Runtime.NONE) { - start = 0; - stop = startOrStop; - } else { - start = startOrStop; - stop = Type.INTEGER.convert(stopOrNone, "'stop' operand of 'range'"); - } - if (step == 0) { - throw new EvalException(loc, "step cannot be 0"); - } - ArrayList<Integer> result = Lists.newArrayList(); - if (step > 0) { - int size = (stop - start) / step; - result.ensureCapacity(size); - while (start < stop) { - result.add(start); - start += step; - } - } else { - int size = (start - stop) / step; - result.ensureCapacity(size); - while (start > stop) { - result.add(start); - start += step; + @SkylarkSignature( + name = "range", + returnType = MutableList.class, + doc = + "Creates a list where items go from <code>start</code> to <code>stop</code>, using a " + + "<code>step</code> increment. If a single argument is provided, items will " + + "range from 0 to that element." + + "<pre class=\"language-python\">range(4) == [0, 1, 2, 3]\n" + + "range(3, 9, 2) == [3, 5, 7]\n" + + "range(3, 0, -1) == [3, 2, 1]</pre>", + parameters = { + @Param( + name = "start_or_stop", + type = Integer.class, + doc = + "Value of the start element if stop is provided, " + + "otherwise value of stop and the actual start is 0" + ), + @Param( + name = "stop_or_none", + type = Integer.class, + noneable = true, + defaultValue = "None", + doc = + "optional index of the first item <i>not</i> to be included in the resulting " + + "list; generation of the list stops before <code>stop</code> is reached." + ), + @Param( + name = "step", + type = Integer.class, + defaultValue = "1", + doc = "The increment (default is 1). It may be negative." + ) + }, + useLocation = true, + useEnvironment = true + ) + private static final BuiltinFunction range = + new BuiltinFunction("range") { + public MutableList<?> invoke( + Integer startOrStop, Object stopOrNone, Integer step, Location loc, Environment env) + throws EvalException { + int start; + int stop; + if (stopOrNone == Runtime.NONE) { + start = 0; + stop = startOrStop; + } else { + start = startOrStop; + stop = Type.INTEGER.convert(stopOrNone, "'stop' operand of 'range'"); + } + if (step == 0) { + throw new EvalException(loc, "step cannot be 0"); + } + ArrayList<Integer> result = Lists.newArrayList(); + if (step > 0) { + int size = (stop - start) / step; + result.ensureCapacity(size); + while (start < stop) { + result.add(start); + start += step; + } + } else { + int size = (start - stop) / step; + result.ensureCapacity(size); + while (start > stop) { + result.add(start); + start += step; + } + } + return new MutableList(result, env); } - } - return new MutableList(result, env); - } - }; + }; /** * Returns a function-value implementing "select" (i.e. configurable attributes) @@ -1901,62 +2029,82 @@ public class MethodLibrary { } }; - /** - * Returns true if the object has a field of the given name, otherwise false. - */ - @SkylarkSignature(name = "hasattr", returnType = Boolean.class, - doc = "Returns True if the object <code>x</code> has an attribute or method of the given " - + "<code>name</code>, otherwise False. Example:<br>" - + "<pre class=\"language-python\">hasattr(ctx.attr, \"myattr\")</pre>", - parameters = { - @Param(name = "x", doc = "The object to check."), - @Param(name = "name", type = String.class, doc = "The name of the attribute.")}, - useLocation = true, useEnvironment = true) - private static final BuiltinFunction hasattr = new BuiltinFunction("hasattr") { - @SuppressWarnings("unused") - public Boolean invoke(Object obj, String name, - Location loc, Environment env) throws EvalException, ConversionException { - if (obj instanceof ClassObject && ((ClassObject) obj).getValue(name) != null) { - return true; - } - return hasMethod(obj, name, loc); - } - }; + /** Returns true if the object has a field of the given name, otherwise false. */ + @SkylarkSignature( + name = "hasattr", + returnType = Boolean.class, + doc = + "Returns True if the object <code>x</code> has an attribute or method of the given " + + "<code>name</code>, otherwise False. Example:<br>" + + "<pre class=\"language-python\">hasattr(ctx.attr, \"myattr\")</pre>", + parameters = { + @Param(name = "x", doc = "The object to check."), + @Param(name = "name", type = String.class, doc = "The name of the attribute.") + }, + useLocation = true, + useEnvironment = true + ) + private static final BuiltinFunction hasattr = + new BuiltinFunction("hasattr") { + @SuppressWarnings("unused") + public Boolean invoke(Object obj, String name, Location loc, Environment env) + throws EvalException { + if (obj instanceof ClassObject && ((ClassObject) obj).getValue(name) != null) { + return true; + } + return hasMethod(obj, name, loc); + } + }; - @SkylarkSignature(name = "getattr", - doc = "Returns the struct's field of the given name if it exists. If not, it either returns " - + "<code>default</code> (if specified) or raises an error. However, if there is a method " - + "of the given name, this method always raises an error, regardless of the " - + "presence of a default value. <code>getattr(x, \"foobar\")</code> is equivalent to " - + "<code>x.foobar</code>." - + "<pre class=\"language-python\">getattr(ctx.attr, \"myattr\")\n" - + "getattr(ctx.attr, \"myattr\", \"mydefault\")</pre>", - parameters = { - @Param(name = "x", doc = "The struct whose attribute is accessed."), - @Param(name = "name", doc = "The name of the struct attribute."), - @Param(name = "default", defaultValue = "unbound", - doc = "The default value to return in case the struct " - + "doesn't have an attribute of the given name.")}, - useLocation = true, useEnvironment = true) - private static final BuiltinFunction getattr = new BuiltinFunction("getattr") { - @SuppressWarnings("unused") - public Object invoke(Object obj, String name, Object defaultValue, - Location loc, Environment env) throws EvalException, ConversionException { - Object result = DotExpression.eval(obj, name, loc, env); - if (result == null) { - // 'Real' describes methods with structField() == false. Because DotExpression.eval returned - // null in this case, we know that structField() cannot return true. - boolean isRealMethod = hasMethod(obj, name, loc); - if (defaultValue != Runtime.UNBOUND && !isRealMethod) { - return defaultValue; + @SkylarkSignature( + name = "getattr", + doc = + "Returns the struct's field of the given name if it exists. If not, it either returns " + + "<code>default</code> (if specified) or raises an error. However, if there is a " + + "method of the given name, this method always raises an error, regardless of the " + + "presence of a default value. <code>getattr(x, \"foobar\")</code> is equivalent to " + + "<code>x.foobar</code>." + + "<pre class=\"language-python\">getattr(ctx.attr, \"myattr\")\n" + + "getattr(ctx.attr, \"myattr\", \"mydefault\")</pre>", + parameters = { + @Param(name = "x", doc = "The struct whose attribute is accessed."), + @Param(name = "name", doc = "The name of the struct attribute."), + @Param( + name = "default", + defaultValue = "unbound", + doc = + "The default value to return in case the struct " + + "doesn't have an attribute of the given name." + ) + }, + useLocation = true, + useEnvironment = true + ) + private static final BuiltinFunction getattr = + new BuiltinFunction("getattr") { + @SuppressWarnings("unused") + public Object invoke( + Object obj, String name, Object defaultValue, Location loc, Environment env) + throws EvalException { + Object result = DotExpression.eval(obj, name, loc, env); + if (result == null) { + // 'Real' describes methods with structField() == false. Because DotExpression.eval + // returned null in this case, we know that structField() cannot return true. + boolean isRealMethod = hasMethod(obj, name, loc); + if (defaultValue != Runtime.UNBOUND && !isRealMethod) { + return defaultValue; + } + throw new EvalException( + loc, + Printer.format( + "Object of type '%s' has no attribute %r%s", + EvalUtils.getDataTypeName(obj), + name, + isRealMethod ? ", however, a method of that name exists" : "")); + } + return result; } - throw new EvalException(loc, Printer.format("Object of type '%s' has no attribute %r%s", - EvalUtils.getDataTypeName(obj), name, - isRealMethod ? ", however, a method of that name exists" : "")); - } - return result; - } - }; + }; /** * Returns whether the given object has a method with the given name. @@ -1974,29 +2122,35 @@ public class MethodLibrary { } } - @SkylarkSignature(name = "dir", returnType = MutableList.class, - doc = "Returns a list strings: the names of the attributes and " - + "methods of the parameter object.", - parameters = {@Param(name = "x", doc = "The object to check.")}, - useLocation = true, useEnvironment = true) - private static final BuiltinFunction dir = new BuiltinFunction("dir") { - public MutableList<?> invoke(Object object, - Location loc, Environment env) throws EvalException, ConversionException { - // Order the fields alphabetically. - Set<String> fields = new TreeSet<>(); - if (object instanceof ClassObject) { - fields.addAll(((ClassObject) object).getKeys()); - } - fields.addAll(Runtime.getFunctionNames(object.getClass())); - try { - fields.addAll(FuncallExpression.getMethodNames(object.getClass())); - } catch (ExecutionException e) { - // This shouldn't happen - throw new EvalException(loc, e.getMessage()); - } - return new MutableList(fields, env); - } - }; + @SkylarkSignature( + name = "dir", + returnType = MutableList.class, + doc = + "Returns a list strings: the names of the attributes and " + + "methods of the parameter object.", + parameters = {@Param(name = "x", doc = "The object to check.")}, + useLocation = true, + useEnvironment = true + ) + private static final BuiltinFunction dir = + new BuiltinFunction("dir") { + public MutableList<?> invoke(Object object, Location loc, Environment env) + throws EvalException { + // Order the fields alphabetically. + Set<String> fields = new TreeSet<>(); + if (object instanceof ClassObject) { + fields.addAll(((ClassObject) object).getKeys()); + } + fields.addAll(Runtime.getFunctionNames(object.getClass())); + try { + fields.addAll(FuncallExpression.getMethodNames(object.getClass())); + } catch (ExecutionException e) { + // This shouldn't happen + throw new EvalException(loc, e.getMessage()); + } + return new MutableList(fields, env); + } + }; @SkylarkSignature( name = "type", @@ -2050,8 +2204,7 @@ public class MethodLibrary { ) private static final BuiltinFunction fail = new BuiltinFunction("fail") { - public Runtime.NoneType invoke(Object msg, Object attr, Location loc) - throws EvalException, ConversionException { + public Runtime.NoneType invoke(Object msg, Object attr, Location loc) throws EvalException { String str = Printer.str(msg); if (attr != Runtime.NONE) { str = String.format("attribute %s: %s", attr, str); diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java b/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java index f0044c23a1..52bf2997ee 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java @@ -47,9 +47,11 @@ public abstract class Parameter<V, T> extends Argument { public boolean isOptional() { return false; } + @Override public boolean isStar() { return false; } + @Override public boolean isStarStar() { return false; } @@ -83,7 +85,7 @@ public abstract class Parameter<V, T> extends Argument { @Override public String toString() { - return name.toString(); + return name; } } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java index 18c2dbf43d..4d285a3e5b 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java @@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.events.Location; @@ -185,7 +186,7 @@ public class Parser { EnumSet.of(Operator.MINUS, Operator.PLUS), EnumSet.of(Operator.DIVIDE, Operator.MULT, Operator.PERCENT)); - private Iterator<Token> tokens = null; + private final Iterator<Token> tokens; private int errorsCount; private boolean recoveryMode; // stop reporting errors until next statement @@ -202,7 +203,7 @@ public class Parser { if (!statements.isEmpty()) { return lexer.createLocation( statements.get(0).getLocation().getStartOffset(), - statements.get(statements.size() - 1).getLocation().getEndOffset()); + Iterables.getLast(statements).getLocation().getEndOffset()); } else { return Location.fromPathFragment(lexer.getFilename()); } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Printer.java b/src/main/java/com/google/devtools/build/lib/syntax/Printer.java index 88abe13756..af6515f376 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Printer.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Printer.java @@ -20,11 +20,9 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkPrintableValue; import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; import com.google.devtools.build.lib.syntax.SkylarkList.Tuple; import com.google.devtools.build.lib.vfs.PathFragment; - import java.io.IOException; import java.util.Formattable; import java.util.Formatter; -import java.util.IllegalFormatException; import java.util.List; import java.util.Map; import java.util.MissingFormatWidthException; @@ -443,8 +441,7 @@ public final class Printer { * @param arguments positional arguments. * @return the formatted string. */ - public static Formattable formattable(final String pattern, Object... arguments) - throws IllegalFormatException { + public static Formattable formattable(final String pattern, Object... arguments) { final ImmutableList<Object> args = ImmutableList.copyOf(arguments); return new Formattable() { @Override @@ -466,8 +463,7 @@ public final class Printer { * @param arguments a tuple containing positional arguments. * @return the formatted string. */ - public static String format(String pattern, Object... arguments) - throws IllegalFormatException { + public static String format(String pattern, Object... arguments) { return formatToString(pattern, ImmutableList.copyOf(arguments)); } @@ -478,8 +474,7 @@ public final class Printer { * @param arguments a tuple containing positional arguments. * @return the formatted string. */ - public static String formatToString(String pattern, List<?> arguments) - throws IllegalFormatException { + public static String formatToString(String pattern, List<?> arguments) { return formatTo(new StringBuilder(), pattern, arguments).toString(); } @@ -493,8 +488,7 @@ public final class Printer { * @return the buffer, in fluent style. */ // TODO(bazel-team): support formatting arguments, and more complex Python patterns. - public static Appendable formatTo(Appendable buffer, String pattern, List<?> arguments) - throws IllegalFormatException { + public static Appendable formatTo(Appendable buffer, String pattern, List<?> arguments) { // N.B. MissingFormatWidthException is the only kind of IllegalFormatException // whose constructor can take and display arbitrary error message, hence its use below. diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java index 2795da10c2..f0608e6dc3 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java @@ -21,13 +21,11 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature; import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils; import com.google.devtools.build.lib.util.Preconditions; - -import net.bytebuddy.implementation.bytecode.StackManipulation; - import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.Set; +import net.bytebuddy.implementation.bytecode.StackManipulation; /** * Global constants and support for global namespaces of runtime functions. @@ -182,7 +180,8 @@ public final class Runtime { try { if (moduleClass.isAnnotationPresent(SkylarkModule.class)) { env.setup( - moduleClass.getAnnotation(SkylarkModule.class).name(), moduleClass.newInstance()); + moduleClass.getAnnotation(SkylarkModule.class).name(), + moduleClass.getConstructor().newInstance()); } for (Field field : moduleClass.getDeclaredFields()) { if (field.isAnnotationPresent(SkylarkSignature.class)) { @@ -199,7 +198,7 @@ public final class Runtime { } } } - } catch (IllegalAccessException | InstantiationException e) { + } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java index fc5e9cffaf..6ae2ae5f2a 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java @@ -46,9 +46,9 @@ import javax.annotation.Nullable; public final class SkylarkDict<K, V> extends MutableMap<K, V> implements Map<K, V>, SkylarkIndexable { - private TreeMap<K, V> contents = new TreeMap<>(EvalUtils.SKYLARK_COMPARATOR); + private final TreeMap<K, V> contents = new TreeMap<>(EvalUtils.SKYLARK_COMPARATOR); - private Mutability mutability; + private final Mutability mutability; @Override public Mutability mutability() { diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java index 99b604efa4..2910beb003 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java @@ -56,7 +56,7 @@ public class SkylarkImports { } private static final class AbsolutePathImport extends SkylarkImportImpl { - private PathFragment importPath; + private final PathFragment importPath; private AbsolutePathImport(String importString, PathFragment importPath) { this.importString = importString; @@ -85,7 +85,7 @@ public class SkylarkImports { } private static final class RelativePathImport extends SkylarkImportImpl { - private String importFile; + private final String importFile; private RelativePathImport(String importString, String importFile) { this.importString = importString; @@ -116,7 +116,7 @@ public class SkylarkImports { } private static final class AbsoluteLabelImport extends SkylarkImportImpl { - private Label importLabel; + private final Label importLabel; private AbsoluteLabelImport(String importString, Label importLabel) { this.importString = importString; @@ -137,7 +137,7 @@ public class SkylarkImports { } private static final class RelativeLabelImport extends SkylarkImportImpl { - private String importTarget; + private final String importTarget; private RelativeLabelImport(String importString, String importTarget) { this.importString = importString; diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java index 928165dbf4..228ef85e12 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.devtools.build.lib.syntax; +import com.google.common.primitives.Booleans; import com.google.devtools.build.lib.skylarkinterface.Param; import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature; import com.google.devtools.build.lib.syntax.BuiltinFunction.ExtraArgKind; @@ -191,8 +192,9 @@ public class SkylarkSignatureProcessor { /** Extract additional signature information for BuiltinFunction-s */ public static ExtraArgKind[] getExtraArgs(SkylarkSignature annotation) { - final int numExtraArgs = (annotation.useLocation() ? 1 : 0) - + (annotation.useAst() ? 1 : 0) + (annotation.useEnvironment() ? 1 : 0); + final int numExtraArgs = + Booleans.countTrue( + annotation.useLocation(), annotation.useAst(), annotation.useEnvironment()); if (numExtraArgs == 0) { return null; } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java index e73672a93b..d6695cbd5c 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java @@ -139,7 +139,7 @@ public abstract class SkylarkType implements Serializable { return TOP; } - private final class Empty { }; // Empty type, used as basis for Bottom + private static final class Empty {}; // Empty type, used as basis for Bottom // Notable types @@ -256,13 +256,15 @@ public abstract class SkylarkType implements Serializable { return this.type == type || super.canBeCastTo(type); } - private static LoadingCache<Class<?>, Simple> simpleCache = CacheBuilder.newBuilder() - .build(new CacheLoader<Class<?>, Simple>() { - @Override - public Simple load(Class<?> type) { - return create(type); - } - }); + private static final LoadingCache<Class<?>, Simple> simpleCache = + CacheBuilder.newBuilder() + .build( + new CacheLoader<Class<?>, Simple>() { + @Override + public Simple load(Class<?> type) { + return create(type); + } + }); private static Simple create(Class<?> type) { Simple simple; @@ -374,7 +376,7 @@ public abstract class SkylarkType implements Serializable { return genericType + " of " + argType + "s"; } - private static Interner<Combination> combinationInterner = + private static final Interner<Combination> combinationInterner = Interners.<Combination>newWeakInterner(); public static SkylarkType of(SkylarkType generic, SkylarkType argument) { @@ -520,7 +522,7 @@ public abstract class SkylarkType implements Serializable { */ public static final class SkylarkFunctionType extends SkylarkType { private final String name; - @Nullable private SkylarkType returnType; + @Nullable private final SkylarkType returnType; @Override public SkylarkType intersectWith(SkylarkType other) { // This gives the wrong result if both return types are incompatibly updated later! diff --git a/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java index 60b293bb1a..af36cd9919 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java @@ -69,7 +69,7 @@ public class UserDefinedFunction extends BaseFunction { // we close over the globals at the time of definition private final Environment.Frame definitionGlobals; - private Optional<Method> method; + private final Optional<Method> method; // TODO(bazel-team) make this configurable once the compiler is stable public static boolean debugCompiler = false; public static boolean debugCompilerPrintByteCode = false; @@ -250,10 +250,7 @@ public class UserDefinedFunction extends BaseFunction { .getLoaded(); return Optional.of( - ReflectionUtils.getMethod( - functionClass, - "call", - parameterTypes.toArray(new Class<?>[parameterTypes.size()])) + ReflectionUtils.getMethod(functionClass, "call", parameterTypes.toArray(new Class<?>[0])) .getLoadedMethod()); } catch (EvalException e) { // don't capture EvalExceptions @@ -295,8 +292,7 @@ public class UserDefinedFunction extends BaseFunction { } // add a return None if there are no statements or the last one to ensure the method always // returns something. This implements the interpreters behavior. - if (statements.isEmpty() - || !(statements.get(statements.size() - 1) instanceof ReturnStatement)) { + if (statements.isEmpty() || !(Iterables.getLast(statements) instanceof ReturnStatement)) { code.add(new ByteCodeAppender.Simple(Runtime.GET_NONE, MethodReturn.REFERENCE)); } // we now know which variables we used in the method, so assign them "undefined" (i.e. null) diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java index 991b106d91..095b46f243 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java @@ -18,7 +18,6 @@ import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.util.Preconditions; - import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -36,15 +35,15 @@ public final class ValidationEnvironment { private final ValidationEnvironment parent; - private Set<String> variables = new HashSet<>(); + private final Set<String> variables = new HashSet<>(); - private Map<String, Location> variableLocations = new HashMap<>(); + private final Map<String, Location> variableLocations = new HashMap<>(); - private Set<String> readOnlyVariables = new HashSet<>(); + private final Set<String> readOnlyVariables = new HashSet<>(); // A stack of variable-sets which are read only but can be assigned in different // branches of if-else statements. - private Stack<Set<String>> futureReadOnlyVariables = new Stack<>(); + private final Stack<Set<String>> futureReadOnlyVariables = new Stack<>(); /** * Tracks the number of nested for loops that contain the statement that is currently being diff --git a/src/main/java/com/google/devtools/build/lib/syntax/compiler/ByteCodeUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/compiler/ByteCodeUtils.java index 4e7abf863b..e08b69ad61 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/compiler/ByteCodeUtils.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/compiler/ByteCodeUtils.java @@ -14,7 +14,7 @@ package com.google.devtools.build.lib.syntax.compiler; import com.google.devtools.build.lib.syntax.compiler.Jump.PrimitiveComparison; - +import java.util.List; import net.bytebuddy.description.method.MethodDescription.ForLoadedMethod; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.generic.GenericTypeDescription; @@ -26,8 +26,6 @@ import net.bytebuddy.implementation.bytecode.constant.IntegerConstant; import net.bytebuddy.implementation.bytecode.member.FieldAccess; import net.bytebuddy.implementation.bytecode.member.MethodInvocation; -import java.util.List; - /** * Various utility methods for byte code generation. */ @@ -62,7 +60,7 @@ public class ByteCodeUtils { * <p>Exists just because {@link Compound} does not have a constructor taking a list. */ public static ByteCodeAppender compoundAppender(List<ByteCodeAppender> code) { - return new Compound(code.toArray(new ByteCodeAppender[code.size()])); + return new Compound(code.toArray(new ByteCodeAppender[0])); } /** diff --git a/src/main/java/com/google/devtools/build/lib/syntax/compiler/VariableStore.java b/src/main/java/com/google/devtools/build/lib/syntax/compiler/VariableStore.java index a418ad00b2..5ceff2f3c7 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/compiler/VariableStore.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/compiler/VariableStore.java @@ -16,14 +16,12 @@ package com.google.devtools.build.lib.syntax.compiler; import com.google.devtools.build.lib.syntax.compiler.Variable.InternalVariable; import com.google.devtools.build.lib.syntax.compiler.Variable.SkylarkVariable; import com.google.devtools.build.lib.util.Preconditions; - import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.implementation.Implementation.Context; import net.bytebuddy.implementation.bytecode.ByteCodeAppender; import net.bytebuddy.implementation.bytecode.StackManipulation.Size; import net.bytebuddy.implementation.bytecode.StackSize; - import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -61,7 +59,7 @@ enum VariableStore { // TODO(klaasb) javadoc class VariableIndexStore implements ByteCodeAppender { - private int operandIndex; + private final int operandIndex; private VariableIndexStore(int operandIndex) { this.operandIndex = operandIndex; |