@Override public void visitLabeledStatement(@NotNull GrLabeledStatement labeledStatement) { super.visitLabeledStatement(labeledStatement); final String name = labeledStatement.getName(); GrLabeledStatement existing = ResolveUtil.resolveLabeledStatement(name, labeledStatement, true); if (existing != null && PsiTreeUtil.isAncestor(existing, labeledStatement, true)) { registerError(labeledStatement.getLabel(), name); } }
// See org.spockframework.compiler.WhereBlockRewriter public static Map<String, SpockVariableDescriptor> createVariableMap(GrMethod method) { GrOpenBlock block = method.getBlock(); if (block == null) return Collections.emptyMap(); PsiElement elementUnderLabel = null; PsiElement elementAfterLabel = null; main: for (PsiElement e = block.getFirstChild(); e != null; e = e.getNextSibling()) { if (e instanceof GrLabeledStatement) { GrLabeledStatement l = (GrLabeledStatement) e; elementAfterLabel = l.getNextSibling(); while (true) { GrStatement statement = l.getStatement(); if ("where".equals(l.getName())) { elementUnderLabel = statement; break main; } if (statement instanceof GrLabeledStatement) { l = (GrLabeledStatement) statement; continue; } break; } } } if (elementUnderLabel == null) return Collections.emptyMap(); Map<String, SpockVariableDescriptor> res = new HashMap<>(); PsiElement e = elementUnderLabel; while (e != null) { if (e instanceof GrBinaryExpression && ((GrBinaryExpression) e).getOperationTokenType() == GroovyElementTypes.COMPOSITE_LSHIFT_SIGN) { GrBinaryExpression shift = (GrBinaryExpression) e; GrExpression leftOperand = shift.getLeftOperand(); GrExpression rightOperand = shift.getRightOperand(); if (leftOperand instanceof GrReferenceExpression) { String name = getNameByReference(leftOperand); if (name != null) { SpockVariableDescriptor descriptor = new SpockVariableDescriptor(leftOperand, name); descriptor.addExpressionOfCollection(rightOperand); res.put(name, descriptor); } } else if (leftOperand instanceof GrListOrMap) { GrExpression[] variableDefinitions = ((GrListOrMap) leftOperand).getInitializers(); SpockVariableDescriptor[] variables = createVariables(res, Arrays.asList(variableDefinitions)); if (rightOperand instanceof GrListOrMap) { for (GrExpression expression : ((GrListOrMap) rightOperand).getInitializers()) { if (expression instanceof GrListOrMap) { add(variables, Arrays.asList(((GrListOrMap) expression).getInitializers())); } else { for (SpockVariableDescriptor variable : variables) { if (variable != null) { variable.addExpressionOfCollection(expression); } } } } } } } else if (e instanceof GrAssignmentExpression) { GrAssignmentExpression assExpr = (GrAssignmentExpression) e; GrExpression lValue = assExpr.getLValue(); String name = getNameByReference(lValue); if (name != null) { res.put( name, new SpockVariableDescriptor(lValue, name).addExpression(assExpr.getRValue())); } } else if (isOrStatement(e)) { // See org.spockframework.compiler.WhereBlockRewriter#rewriteTableLikeParameterization() List<GrExpression> variableDefinitions = new ArrayList<>(); splitOr(variableDefinitions, (GrExpression) e); SpockVariableDescriptor[] variables = createVariables(res, variableDefinitions); List<GrExpression> row = new ArrayList<>(); PsiElement rowElement = getNext(e, elementUnderLabel, elementAfterLabel); while (isOrStatement(rowElement)) { row.clear(); splitOr(row, (GrExpression) rowElement); add(variables, row); rowElement = getNext(rowElement, elementUnderLabel, elementAfterLabel); } e = rowElement; continue; } e = getNext(e, elementUnderLabel, elementAfterLabel); } return res; }
private static GrForStatement updateReturnStatements(GrForStatement forStatement) { GrStatement body = forStatement.getBody(); assert body != null; final Set<String> usedLabels = ContainerUtil.newHashSet(); final Ref<Boolean> needLabel = Ref.create(false); body.accept( new GroovyRecursiveElementVisitor() { private int myLoops = 0; @Override public void visitReturnStatement(GrReturnStatement returnStatement) { if (returnStatement.getReturnValue() != null) return; if (myLoops > 0) needLabel.set(true); } @Override public void visitLabeledStatement(GrLabeledStatement labeledStatement) { super.visitLabeledStatement(labeledStatement); usedLabels.add(labeledStatement.getName()); } @Override public void visitForStatement(GrForStatement forStatement) { myLoops++; super.visitForStatement(forStatement); myLoops--; } @Override public void visitWhileStatement(GrWhileStatement whileStatement) { myLoops++; super.visitWhileStatement(whileStatement); myLoops--; } @Override public void visitClosure(GrClosableBlock closure) { // don't go into closures } @Override public void visitAnonymousClassDefinition( GrAnonymousClassDefinition anonymousClassDefinition) { // don't go into anonymous } }); GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(forStatement.getProject()); final String continueText; if (needLabel.get()) { int i = 0; String label = OUTER; while (usedLabels.contains(label)) { label = OUTER + i; i++; } continueText = "continue " + label; GrLabeledStatement labeled = (GrLabeledStatement) factory.createStatementFromText(label + ": while (true){}"); labeled.getStatement().replaceWithStatement(forStatement); labeled = forStatement.replaceWithStatement(labeled); forStatement = (GrForStatement) labeled.getStatement(); body = forStatement.getBody(); assert body != null; } else { continueText = "continue"; } final GrStatement continueStatement = factory.createStatementFromText(continueText); body.accept( new GroovyRecursiveElementVisitor() { @Override public void visitReturnStatement(GrReturnStatement returnStatement) { if (returnStatement.getReturnValue() == null) { returnStatement.replaceWithStatement(continueStatement); } } @Override public void visitClosure(GrClosableBlock closure) { // don't go into closures } @Override public void visitAnonymousClassDefinition( GrAnonymousClassDefinition anonymousClassDefinition) { // don't go into anonymous } }); return forStatement; }