auphong2707/dl4se-code-review-dataset huggingface dataset:
Source:
@Test public void testExhaustionClosesSourceIterator() { START iterator.setCallback(new Callback() END { @Override public void call() { /* do nothing */ } }); Context context = new Context() ; ExecutionContext ec = new ExecutionContext(context, (Graph) null, (DatasetGraph) null, (OpExecutorFactory) null); QueryIterSort qis = new QueryIterSort(iterator, comparator, ec); while (qis.hasNext()) qis.next(); assertTrue("source iterator should have been closed", iterator.isClosed()); } This can be written as `iterator.setCallback(()->{});`

Target:
public void testExhaustionClosesSourceIterator() { iterator.setCallback(() -> {}); Context context = new Context() ; ExecutionContext ec = new ExecutionContext(context, (Graph) null, (DatasetGraph) null, (OpExecutorFactory) null); QueryIterSort qis = new QueryIterSort(iterator, comparator, ec); while (qis.hasNext()) qis.next(); assertTrue("source iterator should have been closed", iterator.isClosed()); }
Source:
public void testReplace() { START final String value1 = "A" ; END final String value2 = "B" ; final Cache<Integer, Object> testCache = new CacheSimple<>(5); testCache.put(1, value1); testCache.put(1, value2); assertEquals("Wrong size", 1, testCache.size()) ; assertEquals("Wrong slot contents", value2, testCache.getIfPresent(1)) ; } Better - use the key not the constant.

Target:
public void testReplace() { final Integer key = 1 ; final String value1 = "A" ; final String value2 = "B" ; final Cache<Integer, Object> testCache = new CacheSimple<>(5); testCache.put(key, value1); testCache.put(key, value2); assertEquals("Wrong size", 1, testCache.size()) ; assertEquals("Wrong slot contents", value2, testCache.getIfPresent(key)) ; }
Source:
START private static Boolean cacheGet(final CacheKey key) { END final LRUMap<CacheKey, Boolean> cache = SecuredItemImpl.CACHE.get(); return (cache == null) ? null : (Boolean) cache.get(key); } What is the reasoning for making this a static method? While it is using thread local only it seems to me that this is not semantically the same as a static method.

Target:
private Boolean cacheGet(final CacheKey key) { final LRUMap<CacheKey, Boolean> cache = SecuredItemImpl.CACHE.get(); return (cache == null) ? null : (Boolean) cache.get(key); }
Source:
public void isolation_01() { // Start a read transaction on another thread. // The transaction has begin() by the time threadTxnRead // returns but the action of the ThreadTxn is not triggered // until other.run() is called. DatasetGraph dsg = create() ; ThreadAction other = ThreadTxn.threadTxnRead(dsg, ()-> { long x = Iter.count(dsg.find()) ; START Assert.assertEquals(0, x) ; END }) ; dsg.begin(WRITE) ; dsg.add(q1) ; dsg.commit() ; dsg.end() ; other.run() ; } Maybe `ThreadAction other = ThreadTxn.threadTxnRead(dsg, () -> Assert.assertTrue(dsg.isEmpty()));` is a little clearer?

Target:
public void isolation_01() { // Start a read transaction on another thread. // The transaction has begin() by the time threadTxnRead // returns but the action of the ThreadTxn is not triggered // until other.run() is called. DatasetGraph dsg = create() ; ThreadAction other = ThreadTxn.threadTxnRead(dsg, ()-> Assert.assertTrue(dsg.isEmpty()) ) ; dsg.begin(WRITE) ; dsg.add(q1) ; dsg.commit() ; dsg.end() ; other.run() ; }
Source:
protected QueryIterator nextStage(Binding binding) { QueryIterator iter = exec(binding, argSubject, predicate, argObject, super.getExecContext()) ; if ( iter == null ) iter = IterLib.noResults(execCxt) ; START return iter ; END } This change is potentially significant. The execution context can change during execution where a new context derived from the current one is produced so please keep L108/L109.

Target:
protected QueryIterator nextStage(Binding binding) { QueryIterator iter = exec(binding, argSubject, predicate, argObject, getExecContext()) ; if ( iter == null ) iter = IterLib.noResults(getExecContext()) ; return iter ; }
Source:
public void visitFormatSpecifier(FormatSpecifier formatSpecifier) { START scan(formatSpecifier.columnToken()); END scan(formatSpecifier.formatExpressions()); } As we don't visit such tokens in the `BaseTreeVisitor`, I wouldn't do it for this one either to stay consistent (it doesn't have an impact).

Target:
public void visitFormatSpecifier(FormatSpecifier formatSpecifier) { scan(formatSpecifier.formatExpressions()); }
Source:
private static void checkDictionary(UnpackingExpression unpackingExpression, Map<String, List<Tree>> passedParameters) { List<String> dictionaryKeys = extractKeysFromDictionary(unpackingExpression); for (String key : dictionaryKeys) { START passedParameters.computeIfAbsent(key, k -> new ArrayList<>()).add(unpackingExpression); END } } This looks as if this might collide with rules about duplicate keys in dictionary literals for cases like `foo(**{'a': 1, 'a': 1})`. If this is the case, consider replacing `List<String>` by `Set<String>` in the return types of the helper methods that collect the keys.

Target:
private static void checkDictionary(UnpackingExpression unpackingExpression, Map<String, List<Tree>> passedParameters) { Set<String> dictionaryKeys = extractKeysFromDictionary(unpackingExpression); dictionaryKeys.forEach(key -> passedParameters.computeIfAbsent(key, k -> new ArrayList<>()).add(unpackingExpression)); }
Source:
private static boolean isVariableThatCanEscape(Symbol symb) { List<Usage> usages = symb.usages(); if (usages.size() > 2) { // Check whether there are any usages except assignments and `is`-comparisons. // (Assignments override, they don't let the reference escape. Comparisons with `is` also don't let it escape, // because they only compare, they don't copy the reference anywhere.) return usages.stream().anyMatch(u -> !u.isBindingUsage() && TreeUtils.firstAncestorOfKind(u.tree(), Tree.Kind.IS) == null); START } else { END // Only original assignment and usage within comparison itself, ignore return false; } } Minor: I believe you can remove the `else` as you're returning in the `if` body

Target:
private static boolean isVariableThatCanEscape(Symbol symb) { List<Usage> usages = symb.usages(); if (usages.size() > 2) { // Check whether there are any usages except assignments and `is`-comparisons. // (Assignments override, they don't let the reference escape. Comparisons with `is` also don't let it escape, // because they only compare, they don't copy the reference anywhere.) return usages.stream().anyMatch(u -> !u.isBindingUsage() && TreeUtils.firstAncestorOfKind(u.tree(), Tree.Kind.IS) == null); } // Must be definition and usage within <code>is</code>-comparison itself. return false; }
Source:
private static Predicate<Expression> isStringSatisfying(Predicate<String> pred) { return expr -> { if (expr.is(Tree.Kind.STRING_LITERAL)) { return pred.test(((StringLiteral) expr).trimmedQuotesValue()); } else { START return false; END } }; } Minor nitpick but I believe the `else` is not needed since you return directly from the `if` anyway.

Target:
private static Predicate<Expression> isStringSatisfying(Predicate<String> pred) { return expr -> expr.is(Tree.Kind.STRING_LITERAL) && pred.test(((StringLiteral) expr).trimmedQuotesValue()); }
Source:
private static boolean isUsedInLhsOfCompoundAssignment(Tree tree) { CompoundAssignmentStatement compoundAssignmentStatement = ((CompoundAssignmentStatement) TreeUtils.firstAncestorOfKind(tree, COMPOUND_ASSIGNMENT)); START if (compoundAssignmentStatement == null) { return false; } return isAccessingExpression(compoundAssignmentStatement.lhsExpression(), tree); END } Nitpick: I would simplify this to `return compoundAssignmentStatement != null && isAccessingExpression(...)`

Target:
private static boolean isUsedInLhsOfCompoundAssignment(Tree tree) { CompoundAssignmentStatement compoundAssignmentStatement = ((CompoundAssignmentStatement) TreeUtils.firstAncestorOfKind(tree, COMPOUND_ASSIGNMENT)); return compoundAssignmentStatement != null && isAccessingExpression(compoundAssignmentStatement.lhsExpression(), tree); }
Source:
private static boolean isUsageInClassBody(Usage usage, ClassDef classDef) { if (usage.kind() == Usage.Kind.FUNC_DECLARATION) { return false; } Tree tree = usage.tree(); START return classDef.equals(TreeUtils.firstAncestorOfKind(tree, Tree.Kind.CLASSDEF)) END && TreeUtils.firstAncestorOfKind(tree, Tree.Kind.FUNCDEF) == null; } I think you can refactor this code: ```java return classDef.equals(TreeUtils.firstAncestorOfKind(tree, Tree.Kind.CLASSDEF, Tree.Kind.FUNCDEF)) ```

Target:
private static boolean isUsageInClassBody(Usage usage, ClassDef classDef) { // We want all usages that are not function declarations and their closes parent is the class definition return usage.kind() != Usage.Kind.FUNC_DECLARATION && classDef.equals(TreeUtils.firstAncestorOfKind(usage.tree(), Tree.Kind.CLASSDEF, Tree.Kind.FUNCDEF)); }
Source:
START Map<String, Symbol> membersByName() { END if (membersByName == null) { membersByName = declaredMembers().stream().collect(Collectors.toMap(Symbol::name, m -> m, (s1, s2) -> s1)); } return membersByName; } do we still need that change?

Target:
private Map<String, Symbol> membersByName() { if (membersByName == null) { membersByName = declaredMembers().stream().collect(Collectors.toMap(Symbol::name, m -> m, (s1, s2) -> s1)); } return membersByName; }
Source:
public InferredType type() { if (valueAsStringLowerCase.contains("j")) { return InferredTypes.runtimeType("complex"); } if (valueAsString.contains(".") || valueAsStringLowerCase.contains("e")) { return InferredTypes.runtimeType("float"); } START return InferredTypes.runtimeType("int"); END } Maybe we could have constants for `InferredTypes.runtimeType("int")` and other types to avoid reinstantiating them many times.

Target:
public InferredType type() { return type; }
Source:
private boolean argumentInheritsFromBaseException(Argument argument) { if (!argument.is(Tree.Kind.REGULAR_ARGUMENT)) { // Need type inference to assess further return true; } Expression expression = ((RegularArgument) argument).expression(); START if (expression.is(Tree.Kind.NAME) || expression.is(Tree.Kind.QUALIFIED_EXPR)) { END return inheritsFromBaseException(((HasSymbol) expression).symbol()); } return true; } I think here we could check if expression is an instance of `HasSymbol`

Target:
private boolean argumentInheritsFromBaseException(Argument argument) { if (!argument.is(Tree.Kind.REGULAR_ARGUMENT)) { // Need type inference to assess further return true; } Expression expression = ((RegularArgument) argument).expression(); if (expression instanceof HasSymbol) { return inheritsFromBaseException(((HasSymbol) expression).symbol()); } return true; }
Source:
public void visitImportFrom(ImportFrom importFrom) { START hasUnresolvedWildcardImport |= (importFrom.isWildcardImport() && importFrom.hasUnresolvedWildcardImport()); END super.visitImportFrom(importFrom); } Is `importFrom.isWildcardImport()` actually still needed here?

Target:
public void visitImportFrom(ImportFrom importFrom) { hasUnresolvedWildcardImport |= importFrom.hasUnresolvedWildcardImport(); super.visitImportFrom(importFrom); }
Source:
public PythonScanner(SensorContext context, PythonChecks checks, FileLinesContextFactory fileLinesContextFactory, NoSonarFilter noSonarFilter, List<InputFile> inputFiles) { this.context = context; this.checks = checks; this.fileLinesContextFactory = fileLinesContextFactory; this.noSonarFilter = noSonarFilter; this.cpdAnalyzer = new PythonCpdAnalyzer(context); this.inputFiles = inputFiles; this.parser = PythonParser.create(); START this.packageNames = new HashMap<>(); END } Why not assigning this value in the field declaration?

Target:
public PythonScanner(SensorContext context, PythonChecks checks, FileLinesContextFactory fileLinesContextFactory, NoSonarFilter noSonarFilter, List<InputFile> inputFiles) { this.context = context; this.checks = checks; this.fileLinesContextFactory = fileLinesContextFactory; this.noSonarFilter = noSonarFilter; this.cpdAnalyzer = new PythonCpdAnalyzer(context); this.inputFiles = inputFiles; this.parser = PythonParser.create(); }
Source:
public void visitName(Name name) { START if (!callGlobalsOrLocals && !hasWildcardImport && name.isVariable() && name.symbol() == null) { END nameIssues.computeIfAbsent(name.name(), k -> new ArrayList<>()).add(name); } } I think you can now drop `!callGlobalsOrLocals && !hasWildcardImport` on this line.

Target:
public void visitName(Name name) { if (name.isVariable() && name.symbol() == null) { nameIssues.computeIfAbsent(name.name(), k -> new ArrayList<>()).add(name); } }
Source:
private static String fullyQualifiedModuleName(String fileName, String packageName) { int extensionIndex = fileName.lastIndexOf('.'); START String moduleName = fileName.substring(0, extensionIndex); END return packageName.isEmpty() ? moduleName : (packageName + "." + moduleName); } What if `fileName` doesn't have any `.`?

Target:
private static String fullyQualifiedModuleName(String fileName, String packageName) { int extensionIndex = fileName.lastIndexOf('.'); String moduleName = extensionIndex > 0 ? fileName.substring(0, extensionIndex) : fileName; return packageName.isEmpty() ? moduleName : (packageName + "." + moduleName); }
Source:
public static String unescape(StringElement stringElement) { String lowerCasePrefix = stringElement.prefix().toLowerCase(Locale.ROOT); String valueWithoutQuotes = stringElement.trimmedQuotesValue(); boolean isEscaped = lowerCasePrefix.indexOf('r') == -1; boolean isBytesLiteral = lowerCasePrefix.indexOf('b') != -1; if (isEscaped) { boolean support16Bits = !isBytesLiteral; valueWithoutQuotes = unescapeString(valueWithoutQuotes, support16Bits); START } END return valueWithoutQuotes; } It would be good to add a http link to the language reference.

Target:
public static String unescape(StringElement stringElement) { String lowerCasePrefix = stringElement.prefix().toLowerCase(Locale.ROOT); String valueWithoutQuotes = stringElement.trimmedQuotesValue(); boolean isEscaped = lowerCasePrefix.indexOf('r') == -1; boolean isBytesLiteral = lowerCasePrefix.indexOf('b') != -1; if (isEscaped) { valueWithoutQuotes = unescapeString(valueWithoutQuotes, isBytesLiteral); } return valueWithoutQuotes; }
Source:
private static void addSecondaryLocations(PreciseIssue issue, Expression expression) { Expression unwrappedExpression = Expressions.removeParentheses(expression); if (unwrappedExpression.is(Tree.Kind.CONDITIONAL_EXPR)) { ConditionalExpression conditionalExpression = (ConditionalExpression) unwrappedExpression; ignoreList.add(conditionalExpression); START addSecondaryLocations(issue, (conditionalExpression).trueExpression()); END addSecondaryLocations(issue, (conditionalExpression).falseExpression()); } else { issue.secondary(unwrappedExpression, null); } } I believe those parenthesis around `conditionalExpression` are not necessary

Target:
private static void addSecondaryLocations(PreciseIssue issue, Expression expression) { Expression unwrappedExpression = Expressions.removeParentheses(expression); if (unwrappedExpression.is(Tree.Kind.CONDITIONAL_EXPR)) { ConditionalExpression conditionalExpression = (ConditionalExpression) unwrappedExpression; ignoreList.add(conditionalExpression); addSecondaryLocations(issue, conditionalExpression.trueExpression()); addSecondaryLocations(issue, conditionalExpression.falseExpression()); } else { issue.secondary(unwrappedExpression, null); } }
Source:
public void visitName(Name name) { Optional.ofNullable(name.symbol()).ifPresent(symbol -> symbol.usages().stream() START .filter(usage -> usage.tree() == name) END .findFirst() .ifPresent(usage -> addToSymbolToUsageMap(usage, symbol)) ); super.visitName(name); } This is inefficient. We should have a method to access directly the usage from the tree.

Target:
public void visitName(Name name) { Optional.ofNullable(name.usage()).ifPresent(usage -> addToSymbolToUsageMap(usage, name.symbol())); super.visitName(name); }
Source:
public boolean isInterpolated() { START return prefix().contains("F") || prefix().contains("f"); END } Why `contains` instead of `equalsIgnoreCase`?

Target:
public boolean isInterpolated() { return prefix().equalsIgnoreCase("F"); }
Source:
public static Tree firstAncestorOfKind(Tree tree, Kind... kinds) { START return firstAncestor(tree, t -> Arrays.asList(kinds).contains(t.getKind())); END } What about changing Tree#is to be variadic ? `is(Kind... kinds)` and thus simplify this call ?

Target:
public static Tree firstAncestorOfKind(Tree tree, Kind... kinds) { return firstAncestor(tree, t -> t.is(kinds)); }
Source:
public void function_with_tuple_param() { FunctionDef functionTree = functionTreesByName.get("func_with_tuple_param"); Map<String, Symbol> symbolByName = getSymbolByName(functionTree); assertThat(symbolByName).hasSize(4); for (Map.Entry<String, Symbol> stringSymbolEntry : symbolByName.entrySet()) { START System.out.println(stringSymbolEntry.getKey()+"-"+stringSymbolEntry.getValue().name()); END } } I think you forgot to remove this.

Target:
public void function_with_tuple_param() { FunctionDef functionTree = functionTreesByName.get("func_with_tuple_param"); Map<String, Symbol> symbolByName = getSymbolByName(functionTree); assertThat(symbolByName).hasSize(4); }
Source:
private static List<List<Trivia>> groupTrivias(Token token) { START List<List<Trivia>> result = new LinkedList<>(); END List<Trivia> currentGroup = null; for (Trivia trivia : token.trivia()) { currentGroup = handleOneLineComment(result, currentGroup, trivia); } if (currentGroup != null) { result.add(currentGroup); } return result; } I know this is not from you, but can you change to use arrayList, there is no good usage of linked list.

Target:
private static List<List<Trivia>> groupTrivias(Token token) { List<List<Trivia>> result = new ArrayList<>(); List<Trivia> currentGroup = null; for (Trivia trivia : token.trivia()) { currentGroup = handleOneLineComment(result, currentGroup, trivia); } if (currentGroup != null) { result.add(currentGroup); } return result; }
Source:
private static Set<String> extractStringInterpolationIdentifiers(PyFunctionDefTree functionTree) { return functionTree.descendants(Kind.STRING_LITERAL) .map(PyStringLiteralTree.class::cast) .flatMap(str -> str.stringElements().stream()) START .filter(str -> str.prefix().equals("f")) END .map(PyStringElementTree::trimmedQuotesValue) .flatMap(UnusedLocalVariableCheck::extractInterpolations) .collect(Collectors.toSet()); } What about F-strings (with a capital F)?

Target:
private static Set<String> extractStringInterpolationIdentifiers(PyFunctionDefTree functionTree) { return functionTree.descendants(Kind.STRING_LITERAL) .map(PyStringLiteralTree.class::cast) .flatMap(str -> str.stringElements().stream()) .filter(str -> str.prefix().equalsIgnoreCase("f")) .map(PyStringElementTree::trimmedQuotesValue) .flatMap(UnusedLocalVariableCheck::extractInterpolations) .collect(Collectors.toSet()); }
Source:
public void initialize(Context context) { START context.registerSyntaxNodeConsumer(Tree.Kind.FILE_INPUT, ctx -> this.ignoreList = new LinkedList<>()); END context.registerSyntaxNodeConsumer(Tree.Kind.IF_STMT, ctx -> { PyIfStatementTree ifStatement = (PyIfStatementTree) ctx.syntaxNode(); if (ignoreList.contains(ifStatement)) { return; } List<PyExpressionTree> conditions = getConditionsToCompare(ifStatement); findSameConditions(conditions, ctx); }); } Why linked list ? plain old array list should be good.

Target:
public void initialize(Context context) { context.registerSyntaxNodeConsumer(Tree.Kind.FILE_INPUT, ctx -> this.ignoreList = new ArrayList<>()); context.registerSyntaxNodeConsumer(Tree.Kind.IF_STMT, ctx -> { PyIfStatementTree ifStatement = (PyIfStatementTree) ctx.syntaxNode(); if (ignoreList.contains(ifStatement)) { return; } List<PyExpressionTree> conditions = getConditionsToCompare(ifStatement); findSameConditions(conditions, ctx); }); }
Source:
private List<PyExpressionTree> getConditionsToCompare(PyIfStatementTree ifStatement) { START List<PyExpressionTree> conditions = new ArrayList<>(Collections.singletonList(ifStatement.condition())); END conditions.addAll(ifStatement.elifBranches().stream().map(PyIfStatementTree::condition).collect(Collectors.toList())); PyElseStatementTree elseStatement = ifStatement.elseBranch(); if (elseStatement != null) { lookForElseIfs(conditions, elseStatement); } return conditions; } This is a bit convoluted imo : what about adding the condition to the conditions list initialized empty. And so remove the Collections.singletonList call ?

Target:
private List<PyExpressionTree> getConditionsToCompare(PyIfStatementTree ifStatement) { List<PyExpressionTree> conditions = new ArrayList<>(); conditions.add(ifStatement.condition()); conditions.addAll(ifStatement.elifBranches().stream().map(PyIfStatementTree::condition).collect(Collectors.toList())); PyElseStatementTree elseStatement = ifStatement.elseBranch(); if (elseStatement != null) { lookForElseIfs(conditions, elseStatement); } return conditions; }
Source:
START private void handleNotOperator(SubscriptionContext ctx, PyUnaryExpressionTree unary) { END PyExpressionTree negatedExpr = unary.expression(); if (negatedExpr.is(Tree.Kind.PARENTHESIZED)) { negatedExpr = ((PyParenthesizedExpressionTree) negatedExpr).expression(); if (negatedExpr.is(Tree.Kind.COMPARISON) || !(negatedExpr instanceof PyBinaryExpressionTree)) { ctx.addIssue(negatedExpr, String.format(MESSAGE, "not")); } } } This method should be static

Target:
private static void handleNotOperator(SubscriptionContext ctx, PyUnaryExpressionTree unary) { PyExpressionTree negatedExpr = unary.expression(); if (negatedExpr.is(Tree.Kind.PARENTHESIZED)) { negatedExpr = ((PyParenthesizedExpressionTree) negatedExpr).expression(); if (negatedExpr.is(Tree.Kind.COMPARISON) || !(negatedExpr instanceof PyBinaryExpressionTree)) { ctx.addIssue(negatedExpr, String.format(MESSAGE, "not")); } } }
Source:
public PythonVisitorContext(AstNode rootAst, PyFileInputTree rootTree, PythonFile pythonFile) { this.rootAst = rootAst; START this.rootTree = (PyFileInputTreeImpl) rootTree; END this.pythonFile = pythonFile; this.parsingException = null; SymbolTableBuilderVisitor symbolTableBuilderVisitor = new SymbolTableBuilderVisitor(); symbolTableBuilderVisitor.scanFile(this); symbolTable = symbolTableBuilderVisitor.symbolTable(); } I don't get why the `rootTree` field is declared as `PyFileInputTreeImpl` instead of `PyFileInputTree`.

Target:
public PythonVisitorContext(AstNode rootAst, PyFileInputTree rootTree, PythonFile pythonFile) { this.rootAst = rootAst; this.rootTree = rootTree; this.pythonFile = pythonFile; this.parsingException = null; SymbolTableBuilderVisitor symbolTableBuilderVisitor = new SymbolTableBuilderVisitor(); symbolTableBuilderVisitor.scanFile(this); symbolTable = symbolTableBuilderVisitor.symbolTable(); }
Source:
START private PyExpressionTree getExpression(PyExpressionTree expr) { END if (expr.is(Tree.Kind.MODULO) || expr.is(Tree.Kind.PLUS)) { return getExpression(((PyBinaryExpressionTree) expr).leftOperand()); } return expr; } It's a small thing but SonarQube would like this method to be static :)

Target:
private static PyExpressionTree getExpression(PyExpressionTree expr) { if (expr.is(Tree.Kind.MODULO) || expr.is(Tree.Kind.PLUS)) { return getExpression(((PyBinaryExpressionTree) expr).leftOperand()); } return expr; }
Source:
public void visitCallExpression(PyCallExpressionTree pyCallExpressionTree) { super.visitCallExpression(pyCallExpressionTree); Symbol symbol = symbolTable.getSymbol(pyCallExpressionTree.callee()); if(symbol != null) { START System.out.println(symbol.qualifiedName()); END funcNames.add(symbol.qualifiedName()); } } I think you forgot to remove this line

Target:
public void visitCallExpression(PyCallExpressionTree pyCallExpressionTree) { super.visitCallExpression(pyCallExpressionTree); Symbol symbol = symbolTable.getSymbol(pyCallExpressionTree.callee()); if(symbol != null) { funcNames.add(symbol.qualifiedName()); } }
Source:
public PyCallExpressionTree callExpression(AstNode astNode) { PyExpressionTree callee = expression(astNode.getFirstChild()); AstNode argListNode = astNode.getFirstChild(PythonGrammar.ARGLIST); PyArgListTree argListTree = null; if (argListNode != null) { argListTree = new PyArgListTreeImpl(argListNode, argList(argListNode)); START } END return new PyCallExpressionTreeImpl(astNode, callee, argListTree, astNode.getFirstChild(PythonPunctuator.LPARENTHESIS), astNode.getFirstChild(PythonPunctuator.RPARENTHESIS)); } We could factorize that code in a "argList" method which could return null.

Target:
public PyCallExpressionTree callExpression(AstNode astNode) { PyExpressionTree callee = expression(astNode.getFirstChild()); AstNode argListNode = astNode.getFirstChild(PythonGrammar.ARGLIST); return new PyCallExpressionTreeImpl(astNode, callee, argList(argListNode), astNode.getFirstChild(PythonPunctuator.LPARENTHESIS), astNode.getFirstChild(PythonPunctuator.RPARENTHESIS)); }
Source:
PyClassDefTree getParentClassDef(Tree current) { if(current == null) { return null; START } else if (current.is(Tree.Kind.CLASSDEF)) { END return (PyClassDefTree) current; } else { return getParentClassDef(current.parent()); } } I would rather choose to have a while loop to implement this rather than a recursive call (call stack can grow quite big unecessarily because of this call depending on the level of nesting of the file) and moreover, I believe a while loop would be more readable.

Target:
private static PyClassDefTree getParentClassDef(Tree current) { while (current != null) { if (current.is(Tree.Kind.CLASSDEF)) { return (PyClassDefTree) current; } current = current.parent(); } return null; }
Source:
public void initialize(Context context) { context.registerSyntaxNodeConsumer(Tree.Kind.CLASSDEF, ctx -> { START PyClassDefTree pyClassDefTree = ((PyClassDefTree) ctx.syntaxNode()); END PyNameTree classNameTree = pyClassDefTree.name(); String className = classNameTree.name(); if(!pattern().matcher(className).matches()) { String message = String.format(MESSAGE, className, format); ctx.addIssue(classNameTree, message); } }); } unecessary parentheses.

Target:
public void initialize(Context context) { context.registerSyntaxNodeConsumer(Tree.Kind.CLASSDEF, ctx -> { PyClassDefTree pyClassDefTree = (PyClassDefTree) ctx.syntaxNode(); PyNameTree classNameTree = pyClassDefTree.name(); String className = classNameTree.name(); if(!pattern().matcher(className).matches()) { String message = String.format(MESSAGE, className, format); ctx.addIssue(classNameTree, message); } }); }
Source:
public void visitSetLiteral(PySetLiteralTree pySetLiteralTree) { START scan(new ArrayList<>(pySetLiteralTree.elements())); END } There's no need to instantiate a new list if you are not using a set in the interface.

Target:
public void visitSetLiteral(PySetLiteralTree pySetLiteralTree) { scan((pySetLiteralTree.elements())); }
Source:
START public Set<PyKeyValuePairTree> elements() { END return elements; } A set seems to be a not so good choice in terms of API : order is not guaranteed for API user whereas in the case of an AST order of elements matters.

Target:
public List<PyKeyValuePairTree> elements() { return elements; }
Source:
public void scan(@Nullable Tree element) { if (element != null) { currentElement = element; START List<SubscriptionContextImpl> elementConsumers = consumers.getOrDefault(element.getKind(), Collections.emptyList()); END for (SubscriptionContextImpl consumer : elementConsumers) { consumer.execute(); } } super.scan(element); } .forEach ?

Target:
public void scan(@Nullable Tree element) { if (element != null) { currentElement = element; consumers.getOrDefault(element.getKind(), Collections.emptyList()).forEach(SubscriptionContextImpl::execute); } super.scan(element); }
Source:
private static FileMetrics metrics(String fileName) { File baseDir = new File("src/test/resources/metrics/"); File file = new File(baseDir, fileName); String fileContent; try { fileContent = Files.toString(file, StandardCharsets.UTF_8); } catch (IOException e) { throw new IllegalStateException(e); } START PyFile pyFile = new org.sonar.python.frontend.PythonParser().parse(fileContent); END return new FileMetrics(TestPythonVisitorRunner.createContext(file), true, pyFile); } Now that the 7 lines above are duplicated in 3 tests in python-squid, maybe we can factorize them.

Target:
private static FileMetrics metrics(String fileName) { File baseDir = new File("src/test/resources/metrics/"); File file = new File(baseDir, fileName); return new FileMetrics(TestPythonVisitorRunner.createContext(file), true, PythonParser.parse(file)); }
Source:
START private JBIterable<PsiErrorElement> errorElements(PsiElement root) { END return SyntaxTraverser.psiTraverser(root).traverse().filter(PsiErrorElement.class); } There are two code smells regarding `errorElements` and `parseAs` not being static

Target:
private static JBIterable<PsiErrorElement> errorElements(PsiElement root) { return SyntaxTraverser.psiTraverser(root).traverse().filter(PsiErrorElement.class); }
Source:
public void initialize(Context context) { context.registerSyntaxNodeConsumer(PyElementTypes.REPR_EXPRESSION, ctx -> { PyReprExpression node = (PyReprExpression) ctx.syntaxNode(); START ctx.addIssue(node.getNode().getPsi(), "Use \"repr\" instead."); END }); } Why not `ctx.addIssue(ctx.syntaxNode(), "Use \"repr\" instead.")`?

Target:
public void initialize(Context context) { context.registerSyntaxNodeConsumer(PyElementTypes.REPR_EXPRESSION, ctx -> ctx.addIssue(ctx.syntaxNode(), "Use \"repr\" instead.")); }
Source:
private String getQualifiedName(AstNode node) { Symbol symbol = getContext().symbolTable().getSymbol(node); START if (symbol != null) { END return symbol.qualifiedName(); } return ""; } ``` return symbol != null ? symbol.qualifiedName() : "";

Target:
private String getQualifiedName(AstNode node) { Symbol symbol = getContext().symbolTable().getSymbol(node); return symbol != null ? symbol.qualifiedName() : ""; }
Source:
private void checkCreatingCustomHasher(AstNode classDef) { AstNode argList = classDef.getFirstChild(PythonGrammar.ARGLIST); if (argList != null) { argList.getDescendants(PythonGrammar.ATOM) START .forEach(atom -> { END if (questionableDjangoHashers.contains(getQualifiedName(atom))) { addIssue(atom, MESSAGE); } }); } } ```java .filter(atom -> questionableDjangoHashers.contains(getQualifiedName(atom))) .forEach(atom -> addIssue(atom, MESSAGE)); ```

Target:
private void checkCreatingCustomHasher(AstNode classDef) { AstNode argList = classDef.getFirstChild(PythonGrammar.ARGLIST); if (argList != null) { argList.getDescendants(PythonGrammar.ATOM) .stream() .filter(atom -> questionableDjangoHashers.contains(getQualifiedName(atom))) .forEach(atom -> addIssue(atom, MESSAGE)); } }
Source:
public void function_declaration(){ setRootRule(PythonGrammar.FUNCDEF); assertThat(p).matches("def fun()->'Returns some value': pass"); assertThat(p).matches("def fun(count:'Number of smth'=1, value:'Value of smth', type:Type): pass"); START assertThat(p).matches("async def fun(): pass"); END setRootRule(PythonGrammar.LAMBDEF); assertThat(p).matches("lambda x: x"); assertThat(p).notMatches("lambda x:Type: x"); } @ivandalbosco Could you create a separate test method testing added syntax? Like that it's more visible which syntax is new and what are supported constructions

Target:
public void function_declaration(){ setRootRule(PythonGrammar.FUNCDEF); assertThat(p).matches("def fun()->'Returns some value': pass"); assertThat(p).matches("def fun(count:'Number of smth'=1, value:'Value of smth', type:Type): pass"); setRootRule(PythonGrammar.LAMBDEF); assertThat(p).matches("lambda x: x"); assertThat(p).notMatches("lambda x:Type: x"); }
Source:
public void visitFile(@Nullable AstNode astNode) { newHighlighting = context.newHighlighting(); START System.out.println("high = " + newHighlighting); END System.out.println("fs = " + context.fileSystem()); InputFile inputFile = context.fileSystem().inputFile(context.fileSystem().predicates().is(getContext().getFile().getAbsoluteFile())); newHighlighting.onFile(inputFile); } @ivandalbosco do not forget to remove

Target:
public void visitFile(@Nullable AstNode astNode) { newHighlighting = context.newHighlighting(); InputFile inputFile = context.fileSystem().inputFile(context.fileSystem().predicates().is(getContext().getFile().getAbsoluteFile())); newHighlighting.onFile(inputFile); }
Source:
public void should_execute_on_python_project() { Project project = mock(Project.class); assertThat(sensor.toString()).isEqualTo("PythonSquidSensor"); assertThat(sensor.shouldExecuteOnProject(project)).isFalse(); START fs.add(new DefaultInputFile(TestUtils.MODULE, "test.py").setLanguage(Python.KEY)); END assertThat(sensor.shouldExecuteOnProject(project)).isTrue(); } @ivandalbosco imho this module key parameter is not important in unit tests. WDYT about dropping TestUtils (here and in squid module) and passing e.g. `"moduleKey"` instead `TestUtils.MODULE`? p.s. TestUtils contains method which is not used

Target:
public void should_execute_on_python_project() { Project project = mock(Project.class); assertThat(sensor.toString()).isEqualTo("PythonSquidSensor"); assertThat(sensor.shouldExecuteOnProject(project)).isFalse(); fs.add(new DefaultInputFile("", "test.py").setLanguage(Python.KEY)); assertThat(sensor.shouldExecuteOnProject(project)).isTrue(); }
Source:
public String getStoriesIdJsonStringInSprint() throws JSONException { START return new ConvertSprintBacklog().getStoriesIdJsonStringInSprint( END mSprintBacklogLogic.getStoriesSortedByIdInSprint()); } getStoriesIdJsonStringInSprint() 是否可以改成 static method

Target:
public String getStoriesIdJsonStringInSprint() throws JSONException { return ConvertSprintBacklog.getStoriesIdJsonStringInSprint( mSprintBacklogLogic.getStoriesSortedByIdInSprint()); }
Source:
public String getTasksIdJsonStringInStory(long storyId) throws JSONException { ArrayList<TaskObject> tasks = mSprintBacklogMapper.getStory(storyId).getTasks(); START return new ConvertSprintBacklog().getTasksIdJsonStringInStory(storyId, tasks); END } getTasksIdJsonStringInStory() 是否可以改成 static method

Target:
public String getTasksIdJsonStringInStory(long storyId) throws JSONException { ArrayList<TaskObject> tasks = mSprintBacklogMapper.getStory(storyId).getTasks(); return ConvertSprintBacklog.getTasksIdJsonStringInStory(storyId, tasks); }
Source:
public String getSprintBacklogJsonString() throws JSONException { SprintObject sprint = mSprintBacklogMapper.getSprint(); START return new ConvertSprintBacklog().getSprintBacklogJsonString(sprint); END } getSprintBacklogJsonString() 是否可以改成 static method

Target:
public String getSprintBacklogJsonString() throws JSONException { SprintObject sprint = mSprintBacklogMapper.getSprint(); return ConvertSprintBacklog.getSprintBacklogJsonString(sprint); }
Source:
public String getTasksJsonString(ArrayList<TaskObject> tasks) throws JSONException { JSONObject tasksJsonString = new JSONObject(); JSONArray tasksJsonArray = new JSONArray(); if (tasks == null) return ""; for (TaskObject task : tasks) { JSONObject taskJson = new JSONObject(getTaskJsonString(task)); tasksJsonArray.put(taskJson); } tasksJsonString.put(SprintBacklogUtil.TAG_TASKS, tasksJsonArray); START return tasksJsonString.toString(); END } 是否可直接 return tasksJsonArray.toString

Target:
static public String getTasksJsonString(ArrayList<TaskObject> tasks) throws JSONException { JSONObject tasksJsonString = new JSONObject(); JSONArray tasksJsonArray = new JSONArray(); if (tasks == null) return ""; for (TaskObject task : tasks) { JSONObject taskJson = new JSONObject(getTaskJsonString(task)); tasksJsonArray.put(taskJson); } tasksJsonString.put(SprintBacklogUtil.TAG_TASKS, tasksJsonArray); return tasksJsonString.toString(); }
Source:
public void openConnect() { getControl().connect(); mNoteService = new MantisNoteService(getControl(), getConfig()); mIssueService = new MantisIssueService(getControl(), getConfig()); START mAttachFileService = new MantisAttachFileService(getControl(), getConfig()); END } 要改用 attach file dao ，MantisAttachFileService 要拔掉

Target:
public void openConnect() { getControl().connect(); mNoteService = new MantisNoteService(getControl(), getConfig()); mIssueService = new MantisIssueService(getControl(), getConfig()); }
Source:
private void initialize(long projectId) { UserSession userSession = new UserSession(super.getAccount()); mProjectHelper = new ProjectHelper(); mProject = mProjectHelper.getProject(projectId); START IProject iProject = new ProjectMapper().getProjectByID(mProject.getName()); END mSprintBacklogHelper = new SprintBacklogHelper(iProject, userSession); mProductBacklogHelper = new ProductBacklogHelper(userSession, iProject); } project

Target:
private void initialize(long projectId) { UserSession userSession = new UserSession(super.getAccount()); mProjectHelper = new ProjectHelper(); mProject = mProjectHelper.getProject(projectId); IProject project = new ProjectMapper().getProjectByID(mProject.getName()); mSprintBacklogHelper = new SprintBacklogHelper(project, userSession); mProductBacklogHelper = new ProductBacklogHelper(userSession, project); }
Source:
public void parserNoteText(String text){ START this.mNoteText = text; END this.setImportance(getTagValue("Importance")); this.setEstimation(getTagValue("Estimation")); this.setValue(getTagValue("Value")); this.setHowToDemo(getTagValue("HowToDemo")); this.setNotes(getTagValue("Notes")); } remove "this."

Target:
public void parserNoteText(String text){ mNoteText = text; setImportance(getTagValue("Importance")); setEstimation(getTagValue("Estimation")); setValue(getTagValue("Value")); setHowToDemo(getTagValue("HowToDemo")); setNotes(getTagValue("Notes")); }
Source:
public Date getProjectStartDate() { START List<ISprintPlanDesc> sprintList = this.loadListPlans(); END return DateUtil.dayFilter(sprintList.get(0).getStartDate()); } I hate 'this'.

Target:
public Date getProjectStartDate() { List<ISprintPlanDesc> sprintList = loadListPlans(); return DateUtil.dayFilter(sprintList.get(0).getStartDate()); }
Source:
public IssueBacklog(IProject project, IUserSession userSession) { // 有些地方還是只能使用IProject 所以過度期使用此段程式碼 ezScrum v1.8 m_project = new ProjectObject(); START m_project.setNickName(project.getName()); END // m_project = project; m_userSession = userSession; // 初始Config設定 m_config = new Configuration(m_userSession); } setName(newName)

Target:
public IssueBacklog(IProject project, IUserSession userSession) { // 有些地方還是只能使用IProject 所以過度期使用此段程式碼 ezScrum v1.8 m_project = new ProjectObject(project.getName()); // m_project = project; m_userSession = userSession; // 初始Config設定 m_config = new Configuration(m_userSession); }
Source:
private void resetData(AccountObject account) { mId = account.getId(); mUsername = account.getUsername(); mPassword = account.getPassword(); mEmail = account.getEmail(); mNickName = account.getNickName(); mEnable = account.getEnable(); START mRoles = null; END } remove mRoles

Target:
private void resetData(AccountObject account) { mId = account.getId(); mUsername = account.getUsername(); mPassword = account.getPassword(); mEmail = account.getEmail(); mNickName = account.getNickName(); mEnable = account.getEnable(); }
Source:
START private static double mean(int[] m) { END double sum = 0; for (int i = 0; i < m.length; i++) { sum += m[i]; } return sum / m.length; } no need to be static

Target:
private double mean(int[] m) { double sum = 0; for (int i = 0; i < m.length; i++) { sum += m[i]; } return sum / m.length; }
Source:
public void write(byte[] data, int offset, int len) { if(!this.running) { return; } //Send audio data START requestObserver.onNext(StreamingRecognizeRequest.newBuilder().setAudioContent(ByteString.copyFrom(data)).build()); END } respect offset and data length

Target:
public void write(byte[] data, int offset, int len) { if(!this.running.get()) { return; } //Send audio data requestObserver.onNext(StreamingRecognizeRequest.newBuilder().setAudioContent(ByteString.copyFrom(data, offset, len)).build()); }
Source:
START public Iterator<String> getCodecs() { END return codecs; } Use array instead of iterator

Target:
public String[] getCodecs() { return codecs; }
Source:
protected List<PacketHandler> getHandlers() { START synchronized (this.handlers) { END return this.handlers; } } no need for synchronized here

Target:
protected List<PacketHandler> getHandlers() { return this.handlers; }
Source:
public Object create(String parentUniqueId, SimpleObject post, RequestContext context) throws ResponseException { if (post == null) { return null; } IdentifierSourceService service = Context.getService(IdentifierSourceService.class); String identifier = service.generateIdentifier(service.getIdentifierSourceByUuid(parentUniqueId), START post.containsKey("comment") ? String.valueOf((String)post.get("comment")) : ""); END SimpleObject response = new SimpleObject(); response.add(IDENTIFIER_KEY, identifier); return response; } Do you really need casting this to a String?

Target:
public Object create(String parentUniqueId, SimpleObject post, RequestContext context) throws ResponseException { if (post == null) { return null; } IdentifierSourceService service = Context.getService(IdentifierSourceService.class); String identifier = service.generateIdentifier(service.getIdentifierSourceByUuid(parentUniqueId), post.containsKey("comment") ? String.valueOf(post.get("comment")) : ""); SimpleObject response = new SimpleObject(); response.add(IDENTIFIER_KEY, identifier); return response; }
Source:
public String getUuid() { START return this.getIdentifierType().getUuid(); END } This is wrong. getUuid should return the uuid in the class. Since this one has none, you can just return the string version of its id

Target:
public String getUuid() { return this.getId().toString(); }
Source:
public String getUuidProperty() { START return getObject().getIdentifierType().getUuid(); END } As i said above, the uuid should be on the class itself instead of that of one of its children.

Target:
public String getUuidProperty() { return getObject().getUuid(); }
Source:
public void setUp() throws Exception { executeDataSet("org/openmrs/module/idgen/include/TestData.xml"); START this.service = Context.getService(IdentifierSourceService.class); END } When do you ever use the above service? And if you do, is it more than once?

Target:
public void setUp() throws Exception { executeDataSet("org/openmrs/module/idgen/include/TestData.xml"); }
Source:
public LogEntry newDelegate() throws ResourceDoesNotSupportOperationException { START throw new UnsupportedOperationException("method not supported"); END } Another lesson for you to learn. You do not need to ask for permission to try out anything. Always do what you think is best and wait for a review. 😊

Target:
public LogEntry newDelegate() throws ResourceDoesNotSupportOperationException { throw new ResourceDoesNotSupportOperationException(); }
Source:
public void shouldPurgeAnAutoGenerationOption() throws Exception { START MockHttpServletRequest req = request(RequestMethod.DELETE, getURI() + "/" + getUuid()); END req.addParameter("purge", ""); handle(req); assertNull(service.getAutoGenerationOption(Integer.parseInt(getUuid()))); } Can you create a test dataset file and edit an existing one?

Target:
public void shouldPurgeAnAutoGenerationOption() throws Exception { assertNotNull(service.getAutoGenerationOption(Integer.parseInt(getUuid()))); MockHttpServletRequest req = request(RequestMethod.DELETE, getURI() + "/" + getUuid()); req.addParameter("purge", ""); handle(req); assertNull(service.getAutoGenerationOption(Integer.parseInt(getUuid()))); }
Source:
public void validateDefaultRepresentation() throws Exception { START assertPropEquals("uuid", getUuidProperty()); END assertPropPresent("name"); assertPropPresent("description"); assertPropPresent("identifierType"); } Did you forget to add? super.validateFullRepresentation();

Target:
public void validateDefaultRepresentation() throws Exception { super.validateDefaultRepresentation(); assertPropEquals("uuid", getUuidProperty()); assertPropPresent("name"); assertPropPresent("description"); assertPropPresent("identifierType"); }
Source:
public DelegatingResourceDescription getUpdatableProperties() throws ResourceDoesNotSupportOperationException { DelegatingResourceDescription description = new DelegatingResourceDescription(); description.addProperty("name"); START description.addProperty("description"); END description.addProperty("identifierType"); return description; } Looking at this https://modules-refapp.openmrs.org/openmrs/module/idgen/editIdentifierSource.form?source=1 i think identifier type is not updatable. Not so?

Target:
public DelegatingResourceDescription getUpdatableProperties() throws ResourceDoesNotSupportOperationException { DelegatingResourceDescription description = new DelegatingResourceDescription(); description.addProperty("name"); description.addProperty("description"); return description; }
Source:
SlackService getSlackService(final String baseUrl, final String teamDomain, final String authTokenCredentialId, final boolean botUser, final String roomId, final Item item) { final String populatedToken = CredentialsObtainer.getTokenToUse(authTokenCredentialId, item,null ); if (populatedToken != null) { return new StandardSlackService( START new StandardSlackServiceBuilder() END .withBaseUrl(baseUrl) .withTeamDomain(teamDomain) .withBotUser(botUser) .withRoomId(roomId) .withPopulatedToken(populatedToken) ); } else { throw new NoSuchElementException("Could not obtain credentials with credential id: " + authTokenCredentialId); } } ```suggestion StandardSlackService.builder() ```

Target:
SlackService getSlackService(final String baseUrl, final String teamDomain, final String authTokenCredentialId, final boolean botUser, final String roomId, final Item item) { final String populatedToken = CredentialsObtainer.getTokenToUse(authTokenCredentialId, item,null ); if (populatedToken != null) { return new StandardSlackService( StandardSlackService.builder() .withBaseUrl(baseUrl) .withTeamDomain(teamDomain) .withBotUser(botUser) .withRoomId(roomId) .withPopulatedToken(populatedToken) ); } else { throw new NoSuchElementException("Could not obtain credentials with credential id: " + authTokenCredentialId); } }
Source:
public StandardSlackService(String baseUrl, String teamDomain, boolean botUser, String roomId, boolean replyBroadcast, String populatedToken) { START this(new StandardSlackServiceBuilder() END .withBaseUrl(baseUrl) .withTeamDomain(teamDomain) .withBotUser(botUser) .withRoomId(roomId) .withReplyBroadcast(replyBroadcast) .withPopulatedToken(populatedToken) ); if (populatedToken == null) { throw new IllegalArgumentException("No slack token found, setup a secret text credential and configure it to be used"); } this.populatedToken = populatedToken; } sorry I missed this before ```suggestion this(builder() ```

Target:
public StandardSlackService(String baseUrl, String teamDomain, boolean botUser, String roomId, boolean replyBroadcast, String populatedToken) { this(builder() .withBaseUrl(baseUrl) .withTeamDomain(teamDomain) .withBotUser(botUser) .withRoomId(roomId) .withReplyBroadcast(replyBroadcast) .withPopulatedToken(populatedToken) ); if (populatedToken == null) { throw new IllegalArgumentException("No slack token found, setup a secret text credential and configure it to be used"); } this.populatedToken = populatedToken; }
Source:
public MatrixTriggerMode getMatrixTriggerMode() { if (matrixTriggerMode == null) { START return MatrixTriggerMode.ONLY_CONFIGURATIONS; END } else { return matrixTriggerMode; } } can you initialise it to this and have the getter just be dumb?

Target:
public MatrixTriggerMode getMatrixTriggerMode() { return matrixTriggerMode; }