/*
* Copyright 2016 Nokia Solutions and Networks
* Licensed under the Apache License, Version 2.0,
* see license.txt file for details.
*/
package org.robotframework.ide.eclipse.main.plugin.project.build.validation;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.rf.ide.core.testdata.model.table.exec.descs.TextPosition;
import org.rf.ide.core.testdata.model.table.exec.descs.VariableExtractor;
import org.rf.ide.core.testdata.model.table.exec.descs.ast.mapping.VariableDeclaration;
import org.rf.ide.core.testdata.model.table.exec.descs.ast.mapping.VariableDeclaration.Number;
import org.rf.ide.core.testdata.model.table.variables.names.VariableNamesSupport;
import org.rf.ide.core.testdata.text.read.recognizer.RobotToken;
import org.rf.ide.core.testdata.text.read.recognizer.RobotTokenType;
import org.rf.ide.core.validation.ProblemPosition;
import org.robotframework.ide.eclipse.main.plugin.project.build.AdditionalMarkerAttributes;
import org.robotframework.ide.eclipse.main.plugin.project.build.ProblemsReportingStrategy;
import org.robotframework.ide.eclipse.main.plugin.project.build.RobotProblem;
import org.robotframework.ide.eclipse.main.plugin.project.build.causes.VariablesProblem;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Range;
class UnknownVariables {
private final FileValidationContext validationContext;
private final ProblemsReportingStrategy reporter;
UnknownVariables(final FileValidationContext validationContext, final ProblemsReportingStrategy reporter) {
this.validationContext = validationContext;
this.reporter = reporter;
}
void reportUnknownVars(final List<RobotToken> tokens, final Set<String> variables) {
final String filename = validationContext.getFile().getName();
final Predicate<VariableDeclaration> isInvalid = new Predicate<VariableDeclaration>() {
@Override
public boolean apply(final VariableDeclaration variableDeclaration) {
return isInvalidVariableDeclaration(variables, variableDeclaration);
}
};
for (final RobotToken token : tokens) {
final List<VariableDeclaration> declarations = new VariableExtractor().extract(token, filename)
.getCorrectVariables();
if (!declarations.isEmpty()) {
reportUnknownVariables(declarations, isInvalid);
}
}
}
static boolean isInvalidVariableDeclaration(final Set<String> definedVariables,
final VariableDeclaration variableDeclaration) {
return !variableDeclaration.asToken().getTypes().contains(RobotTokenType.VARIABLES_ENVIRONMENT_DECLARATION)
&& !variableDeclaration.isDynamic()
&& !VariableNamesSupport.isDefinedVariable(variableDeclaration, definedVariables)
&& !isSpecificVariableDeclaration(definedVariables, variableDeclaration);
}
private static boolean isSpecificVariableDeclaration(final Set<String> definedVariables,
final VariableDeclaration variableDeclaration) {
return variableDeclaration.getVariableType() instanceof Number
|| VariableNamesSupport.isDefinedVariableInsideComputation(variableDeclaration, definedVariables);
}
void reportUnknownVariables(final List<VariableDeclaration> variablesDeclarations,
final Predicate<VariableDeclaration> isInvalid) {
for (final VariableDeclaration variableDeclaration : variablesDeclarations) {
if (isInvalid.apply(variableDeclaration)) {
final String variableName = getVariableName(variableDeclaration);
final RobotProblem problem = RobotProblem.causedBy(VariablesProblem.UNDECLARED_VARIABLE_USE)
.formatMessageWith(variableName);
final int variableOffset = variableDeclaration.getStartFromFile().getOffset();
final ProblemPosition position = new ProblemPosition(variableDeclaration.getStartFromFile().getLine(),
Range.closed(variableOffset, variableOffset
+ ((variableDeclaration.getEndFromFile().getOffset() + 1) - variableOffset)));
final Map<String, Object> additionalArguments = ImmutableMap
.<String, Object> of(AdditionalMarkerAttributes.NAME,
getVariableNameWithBrackets(variableDeclaration));
reporter.handleProblem(problem, validationContext.getFile(), position, additionalArguments);
}
}
}
private String getVariableName(final VariableDeclaration variableDeclaration) {
final Optional<TextPosition> extractVariableName = variableDeclaration.getTextWithoutComputation();
if (extractVariableName.isPresent()) {
return extractVariableName.get().getText();
}
return variableDeclaration.getVariableName().getText();
}
private String getVariableNameWithBrackets(final VariableDeclaration variableDeclaration) {
final String name = variableDeclaration.asToken().getText();
final Optional<TextPosition> extractVariableName = variableDeclaration.getTextWithoutComputation();
if (extractVariableName.isPresent()) {
return name.substring(0, 2) + extractVariableName.get().getText() + name.charAt(name.length() - 1);
}
return name;
}
}