final Map<String, GoLiteralIdentifier> labelDeclarations = new HashMap<String, GoLiteralIdentifier>();
final List<GoLiteralIdentifier> labelUsages = new ArrayList<GoLiteralIdentifier>();
new GoRecursiveElementVisitor() {
@Override
public void visitLabeledStatement(GoLabeledStatement statement) {
GoLiteralIdentifier label = statement.getLabel();
String name = label.getName();
if (labelDeclarations.containsKey(name)) {
result.addProblem(label, GoBundle.message("error.label.already.defined", name));
} else {
labelDeclarations.put(name, label);
}
super.visitLabeledStatement(statement);
}
@Override
public void visitBreakStatement(GoBreakStatement statement) {
checkLabelUsage(statement.getLabel());
}
@Override
public void visitContinueStatement(GoContinueStatement statement) {
checkLabelUsage(statement.getLabel());
}
@Override
public void visitGotoStatement(GoGotoStatement statement) {
checkLabelUsage(statement.getLabel());
}
private void checkLabelUsage(GoLiteralIdentifier label) {
if (label == null) {
return;
}
String name = label.getName();
if (name == null || name.isEmpty()) {
return;
}
labelUsages.add(label);
}
@Override
public void visitFunctionLiteral(GoLiteralFunction literal) {
checkFunction(result, literal);
}
}.visitElement(function);
Set<String> usedLabels = new HashSet<String>();
for (GoLiteralIdentifier label : labelUsages) {
String name = label.getName();
if (labelDeclarations.containsKey(name)) {
usedLabels.add(name);
}
}
for (Map.Entry<String, GoLiteralIdentifier> e : labelDeclarations.entrySet()) {
String name = e.getKey();
if (!usedLabels.contains(name)) {
result.addProblem(e.getValue(), GoBundle.message("error.label.defined.and.not.used", name));
}
}
for (GoLiteralIdentifier label : labelUsages) {
String name = label.getName();
if (name == null || !labelDeclarations.containsKey(name)) {
continue;
}
checkUsage(label, labelDeclarations.get(name), result);
}