/* * Copyright 2015 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 static com.google.common.collect.Maps.newHashMap; import static com.google.common.collect.Maps.newLinkedHashMap; import static com.google.common.collect.Sets.newHashSet; import static com.google.common.collect.Sets.newLinkedHashSet; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.resources.IFile; import org.rf.ide.core.executor.RobotRuntimeEnvironment; import org.rf.ide.core.executor.SuiteExecutor; import org.rf.ide.core.project.RobotProjectConfig; import org.rf.ide.core.project.RobotProjectConfig.LibraryType; import org.rf.ide.core.project.RobotProjectConfig.ReferencedLibrary; import org.rf.ide.core.project.RobotProjectConfig.ReferencedVariableFile; import org.rf.ide.core.testdata.model.RobotVersion; import org.rf.ide.core.testdata.model.search.keyword.KeywordScope; import org.rf.ide.core.testdata.model.table.keywords.names.QualifiedKeywordName; import org.rf.ide.core.testdata.model.table.variables.names.VariableNamesSupport; import org.rf.ide.core.testdata.text.read.recognizer.RobotToken; import org.robotframework.ide.eclipse.main.plugin.model.RobotFileInternalElement; import org.robotframework.ide.eclipse.main.plugin.model.RobotKeywordDefinition; import org.robotframework.ide.eclipse.main.plugin.model.RobotModel; import org.robotframework.ide.eclipse.main.plugin.model.RobotProject; import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile; import org.robotframework.ide.eclipse.main.plugin.model.RobotVariable; import org.robotframework.ide.eclipse.main.plugin.model.locators.ContinueDecision; import org.robotframework.ide.eclipse.main.plugin.model.locators.KeywordDefinitionLocator; import org.robotframework.ide.eclipse.main.plugin.model.locators.KeywordDefinitionLocator.KeywordDetector; import org.robotframework.ide.eclipse.main.plugin.model.locators.KeywordEntity; import org.robotframework.ide.eclipse.main.plugin.model.locators.VariableDefinitionLocator; import org.robotframework.ide.eclipse.main.plugin.model.locators.VariableDefinitionLocator.VariableDetector; import org.robotframework.ide.eclipse.main.plugin.project.build.BuildLogger; import org.robotframework.ide.eclipse.main.plugin.project.build.validation.FileValidationContext.ValidationKeywordEntity; import org.robotframework.ide.eclipse.main.plugin.project.library.KeywordSpecification; import org.robotframework.ide.eclipse.main.plugin.project.library.LibrarySpecification; import com.google.common.annotations.VisibleForTesting; import com.google.common.io.Files; /** * @author Michal Anglart */ public class ValidationContext { private final RobotModel model; private final SuiteExecutor executorInUse; private final RobotVersion version; private RobotProjectConfig projectConfig; private final Map<String, LibrarySpecification> accessibleLibraries; private final Map<ReferencedLibrary, LibrarySpecification> referencedAccessibleLibraries; private BuildLogger logger; private boolean isValidatingChangedFiles; public ValidationContext(final RobotProject robotProject, final BuildLogger logger) { this.model = (RobotModel) robotProject.getParent(); this.logger = logger; this.projectConfig = robotProject.getRobotProjectConfig(); final RobotRuntimeEnvironment runtimeEnvironment = robotProject.getRuntimeEnvironment(); final String versionGot = robotProject.getVersion(); this.version = (runtimeEnvironment != null && versionGot != null) ? RobotVersion.from(versionGot) : null; this.executorInUse = runtimeEnvironment != null ? runtimeEnvironment.getInterpreter() : null; this.accessibleLibraries = collectLibraries(robotProject); this.referencedAccessibleLibraries = newHashMap(robotProject.getReferencedLibraries()); } @VisibleForTesting public ValidationContext(final RobotModel model, final RobotVersion version, final SuiteExecutor executor, final Map<String, LibrarySpecification> libs, final Map<ReferencedLibrary, LibrarySpecification> refLibs) { this.model = model; this.version = version; this.executorInUse = executor; this.accessibleLibraries = libs; this.referencedAccessibleLibraries = refLibs; } private static Map<String, LibrarySpecification> collectLibraries(final RobotProject robotProject) { final Map<String, LibrarySpecification> libs = newLinkedHashMap(); libs.putAll(robotProject.getStandardLibraries()); for (final Entry<ReferencedLibrary, LibrarySpecification> entry : robotProject.getReferencedLibraries() .entrySet()) { if (entry.getKey().provideType() == LibraryType.VIRTUAL && entry.getValue() != null) { libs.put(entry.getValue().getName(), entry.getValue()); } else { libs.put(entry.getKey().getName(), entry.getValue()); } } return libs; } BuildLogger getLogger() { return logger; } @VisibleForTesting public RobotModel getModel() { return model; } public RobotProjectConfig getProjectConfiguration() { return projectConfig; } public SuiteExecutor getExecutorInUse() { return executorInUse; } public RobotVersion getVersion() { return version; } public LibrarySpecification getLibrarySpecification(final String libName) { return accessibleLibraries.get(libName); } public Map<ReferencedLibrary, LibrarySpecification> getReferencedLibrarySpecifications() { return referencedAccessibleLibraries; } public boolean isValidatingChangedFiles() { return isValidatingChangedFiles; } public void setIsValidatingChangedFiles(final boolean isValidatingChangedFiles) { this.isValidatingChangedFiles = isValidatingChangedFiles; } public FileValidationContext createUnitContext(final IFile file) { return new FileValidationContext(this, file); } public Set<String> collectAccessibleVariables(final IFile file) { final Set<String> variables = newHashSet(); new VariableDefinitionLocator(file, model).locateVariableDefinition(new VariableDetector() { @Override public ContinueDecision variableDetected(final RobotVariable variable) { final String name = variable.getPrefix() + VariableNamesSupport.extractUnifiedVariableName(variable.getName()) + variable.getSuffix(); variables.add(name.toLowerCase()); return ContinueDecision.CONTINUE; } @Override public ContinueDecision localVariableDetected(final RobotFileInternalElement element, final RobotToken variable) { // local variables will be added to context during validation return ContinueDecision.CONTINUE; } @Override public ContinueDecision globalVariableDetected(final String name, final Object value) { variables.add(VariableNamesSupport.extractUnifiedVariableName(name)); return ContinueDecision.CONTINUE; } @Override public ContinueDecision varFileVariableDetected(final ReferencedVariableFile file, final String name, final Object value) { variables.add(VariableNamesSupport.extractUnifiedVariableName(name)); return ContinueDecision.CONTINUE; } }); return variables; } public Map<String, Collection<KeywordEntity>> collectAccessibleKeywordNames(final IFile file) { final Map<String, Collection<KeywordEntity>> accessibleKeywords = newHashMap(); new KeywordDefinitionLocator(file, model).locateKeywordDefinition(new KeywordDetector() { @Override public ContinueDecision libraryKeywordDetected(final LibrarySpecification libSpec, final KeywordSpecification kwSpec, final Set<String> libraryAliases, final RobotSuiteFile exposingFile) { final KeywordScope scope = libSpec.isReferenced() ? KeywordScope.REF_LIBRARY : KeywordScope.STD_LIBRARY; for (final String libraryAlias : libraryAliases) { final ValidationKeywordEntity keyword = new ValidationKeywordEntity(scope, libSpec.getName(), kwSpec.getName(), libraryAlias, kwSpec.isDeprecated(), exposingFile.getFile().getFullPath(), 0, kwSpec.createArgumentsDescriptor()); addAccessibleKeyword(kwSpec.getName(), keyword); } return ContinueDecision.CONTINUE; } @Override public ContinueDecision keywordDetected(final RobotSuiteFile suiteFile, final RobotKeywordDefinition kwDefinition) { final ValidationKeywordEntity keyword = new ValidationKeywordEntity(null, Files.getNameWithoutExtension(suiteFile.getName()), kwDefinition.getName(), "", kwDefinition.isDeprecated(), suiteFile.getFile().getFullPath(), kwDefinition.getDefinitionPosition().getOffset(), kwDefinition.createArgumentsDescriptor()); addAccessibleKeyword(kwDefinition.getName(), keyword); return ContinueDecision.CONTINUE; } private void addAccessibleKeyword(final String keywordName, final ValidationKeywordEntity keyword) { final String unifiedName = QualifiedKeywordName.unifyDefinition(keywordName); if (accessibleKeywords.containsKey(unifiedName)) { accessibleKeywords.get(unifiedName).add(keyword); } else { final LinkedHashSet<KeywordEntity> setOfKeywords = newLinkedHashSet(); setOfKeywords.add(keyword); accessibleKeywords.put(unifiedName, setOfKeywords); } } }); return accessibleKeywords; } }