@Test
  public void variablesDefinedInVariablesFilesAreLocated_onlyUntilDetectorWantsToContinue()
      throws Exception {
    final IFile sourceFile =
        projectProvider.createFile(
            "importingFile.robot", createVariablesImportSettingsSection("vars.py"));

    final RobotModel model = new RobotModel();
    final RobotSuiteFile suiteFile = model.createSuiteFile(sourceFile);

    final RobotSettingsSection settings = suiteFile.findSection(RobotSettingsSection.class).get();
    final RobotSetting varSetting = (RobotSetting) settings.findChild("Variables");
    final VariablesImport varsImport = (VariablesImport) varSetting.getLinkedElement();

    final VariablesFileImportReference varsImportRef = new VariablesFileImportReference(varsImport);
    varsImportRef.map(ImmutableMap.of("var_a", 42, "var_b", 1729));

    final RobotFileOutput output = suiteFile.getLinkedElement().getParent();
    output.setVariablesImportReferences(newArrayList(varsImportRef));

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(sourceFile, model);
    locator.locateVariableDefinition(limitedVarFileVariableDetector(visitedVars));
    assertThat(visitedVars).containsOnly("${var_a}");
  }
  @Test
  public void variablesDefinedInKeywordArgumentsSettingAreLocatedByOffset() throws Exception {
    final IFile file = projectProvider.createFile("resource.robot", createKeywordsSection());

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(file, new RobotModel());
    locator.locateVariableDefinitionWithLocalScope(localVariableDetector(visitedVars), 55);
    assertThat(visitedVars).containsOnly("${x}", "${y}");
  }
  @Test
  public void variablesDefinedInPreviousCallsAreLocatedByOffset_1() throws Exception {
    final IFile file = projectProvider.createFile("resource.robot", createTestCasesSection());

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(file, new RobotModel());
    locator.locateVariableDefinitionWithLocalScope(localVariableDetector(visitedVars), 48);
    assertThat(visitedVars).containsOnly("${x}");
  }
  @Test
  public void locallyDefinedVariablesAreLocated() throws Exception {
    final IFile file = projectProvider.createFile("resource.robot", createVariablesSection("1"));

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(file, new RobotModel());
    locator.locateVariableDefinition(variableDetector(visitedVars));
    assertThat(visitedVars).containsOnly("scalar_1", "list_1", "dict_1", "invalid_1");
  }
  @Test
  public void
      variablesDefinedInEmbeddedKeywordNameAreLocatedByOffset_onlyUntilDetectorWantsToContinue()
          throws Exception {
    final IFile file = projectProvider.createFile("resource.robot", createKeywordsSection());

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(file, new RobotModel());
    locator.locateVariableDefinitionWithLocalScope(limitedLocalVariableDetector(visitedVars), 90);
    assertThat(visitedVars).containsOnly("${e}");
  }
  @Test
  public void variablesDefinedInResourceFilesAreLocated_onlyUntilDetectorWantsToContinue()
      throws Exception {
    projectProvider.createFile("resource.robot", createVariablesSection("1"));
    final IFile sourceFile =
        projectProvider.createFile(
            "importingFile.robot", createResourceImportSettingsSection("resource.robot"));

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator =
        new VariableDefinitionLocator(sourceFile, new RobotModel());
    locator.locateVariableDefinition(limitedVariableDetector(visitedVars));
    assertThat(visitedVars).containsOnly("scalar_1", "list_1");
  }
  @Test
  public void variablesDefinedInGlobalVariablesFilesLinkedInRedXmlAreLocated()
      throws IOException, CoreException {
    final IFile sourceFile = projectProvider.createFile("importingFile.robot", "");

    final RobotModel model = new RobotModel();
    final RobotProject robotProject = model.createRobotProject(sourceFile.getProject());

    final ReferencedVariableFile varsImportRef = new ReferencedVariableFile();
    varsImportRef.setVariables(ImmutableMap.<String, Object>of("var_a", 42, "var_b", 1729));

    robotProject.setReferencedVariablesFiles(newArrayList(varsImportRef));

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(sourceFile, model);
    locator.locateVariableDefinition(varFileVariableDetector(visitedVars));
    assertThat(visitedVars).containsOnly("${var_a}", "${var_b}");
  }
  @Test
  public void variablesAreImportedProperly_whenResourcesAreImportingThemselvesInLoop()
      throws Exception {

    // those files imports forms a cycle
    final IFile sourceFile =
        projectProvider.createFile(
            "res1.robot",
            ObjectArrays.concat(
                createVariablesSection("1"),
                createResourceImportSettingsSection("res2.robot"),
                String.class));
    projectProvider.createFile(
        "res2.robot",
        ObjectArrays.concat(
            createVariablesSection("2"),
            createResourceImportSettingsSection("res3.robot"),
            String.class));
    projectProvider.createFile(
        "res3.robot",
        ObjectArrays.concat(
            createVariablesSection("3"),
            createResourceImportSettingsSection("res1.robot"),
            String.class));

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator =
        new VariableDefinitionLocator(sourceFile, new RobotModel());
    locator.locateVariableDefinition(variableDetector(visitedVars));
    assertThat(visitedVars)
        .containsOnly(
            "scalar_1",
            "list_1",
            "dict_1",
            "invalid_1",
            "scalar_2",
            "list_2",
            "dict_2",
            "invalid_2",
            "scalar_3",
            "list_3",
            "dict_3",
            "invalid_3");
  }
  @Test
  public void variablesDefinedInEmbeddedKeywordNameAreLocatedByElement() throws Exception {
    final IFile file = projectProvider.createFile("resource.robot", createKeywordsSection());

    final RobotModel model = new RobotModel();
    final RobotFileInternalElement startingElement =
        model
            .createSuiteFile(file)
            .findSection(RobotKeywordsSection.class)
            .get()
            .getChildren()
            .get(1) // keyword
            .getChildren()
            .get(0); // first call after args

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(file, model);
    locator.locateVariableDefinitionWithLocalScope(
        localVariableDetector(visitedVars), startingElement);
    assertThat(visitedVars).containsOnly("${e}", "${f}");
  }
  @Test
  public void variablesDefinedInPreviousCallsAreLocatedByElement_2() throws Exception {
    final IFile file = projectProvider.createFile("resource.robot", createTestCasesSection());

    final RobotModel model = new RobotModel();
    final RobotFileInternalElement startingElement =
        model
            .createSuiteFile(file)
            .findSection(RobotCasesSection.class)
            .get()
            .getChildren()
            .get(0) // test case
            .getChildren()
            .get(3); // fourth call in case

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(file, model);
    locator.locateVariableDefinitionWithLocalScope(
        localVariableDetector(visitedVars), startingElement);
    assertThat(visitedVars).containsOnly("${x}", "${y}");
  }
  @SuppressWarnings("unchecked")
  @Test
  public void globalVariablesAreLocated_onlyUntilDetectorWantsToContinue() throws Exception {
    final IFile sourceFile = projectProvider.createFile("source.robot", "");

    final RobotModel model = new RobotModel();
    final RobotSuiteFile suiteFile = model.createSuiteFile(sourceFile);
    final RobotProjectHolder projectHolder = suiteFile.getProject().getRobotProjectHolder();
    projectHolder.getGlobalVariables().clear();
    projectHolder
        .getGlobalVariables()
        .addAll(
            newArrayList(
                new ScalarRobotInternalVariable("global_scalar", null),
                new ListRobotInternalVariable("global_list", null),
                new DictionaryRobotInternalVariable("global_dict", null)));

    final Set<String> visitedVars = new HashSet<>();
    final VariableDefinitionLocator locator = new VariableDefinitionLocator(sourceFile, model);
    locator.locateVariableDefinition(limitedGlobalVarDetector(visitedVars));
    assertThat(visitedVars).containsOnly("global_scalar", "global_list");
  }