/* * Copyright 2016 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.rf.ide.core.testdata.text.read.postfixes; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import org.rf.ide.core.testdata.model.FilePosition; import org.rf.ide.core.testdata.model.RobotFile; import org.rf.ide.core.testdata.model.RobotFileOutput; import org.rf.ide.core.testdata.model.table.KeywordTable; import org.rf.ide.core.testdata.model.table.SettingTable; import org.rf.ide.core.testdata.model.table.TestCaseTable; import org.rf.ide.core.testdata.model.table.keywords.KeywordDocumentation; import org.rf.ide.core.testdata.model.table.keywords.UserKeyword; import org.rf.ide.core.testdata.model.table.setting.SuiteDocumentation; import org.rf.ide.core.testdata.model.table.testcases.TestCase; import org.rf.ide.core.testdata.model.table.testcases.TestDocumentation; import org.rf.ide.core.testdata.text.read.IRobotLineElement; import org.rf.ide.core.testdata.text.read.IRobotTokenType; import org.rf.ide.core.testdata.text.read.RobotLine; 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.testdata.text.read.separators.Separator.SeparatorType; import com.google.common.annotations.VisibleForTesting; /** * @author wypych */ public class DocumentationLineContinueMissingFixer implements IPostProcessFixAction { @Override public void applyFix(final RobotFileOutput parsingOutput) { final RobotFile model = parsingOutput.getFileModel(); final List<RobotLine> fileContent = model.getFileContent(); final SettingTable settingTable = model.getSettingTable(); if (settingTable.isPresent()) { suiteDocumentationApplyContinueTokens(fileContent, settingTable); } final KeywordTable keywordTable = model.getKeywordTable(); if (keywordTable.isPresent()) { keywordsDocumentationApplyContinueTokens(fileContent, keywordTable); } final TestCaseTable testCaseTable = model.getTestCaseTable(); if (testCaseTable.isPresent()) { testsDocumentationApplyContinueTokens(fileContent, testCaseTable); } } private void suiteDocumentationApplyContinueTokens(final List<RobotLine> fileContent, final SettingTable settingTable) { final List<SuiteDocumentation> docDeclarations = settingTable.getDocumentation(); for (final SuiteDocumentation docDec : docDeclarations) { final RobotToken declaration = docDec.getDeclaration(); docDec.clearDocumentation(); final List<RobotToken> docTokens = tokensBelongs(fileContent, declaration, RobotTokenType.SETTING_DOCUMENTATION_TEXT, RobotTokenType.PRETTY_ALIGN_SPACE, RobotTokenType.PREVIOUS_LINE_CONTINUE); for (final RobotToken textDoc : docTokens) { docDeclarations.get(0).addDocumentationText(textDoc); } } } private void keywordsDocumentationApplyContinueTokens(final List<RobotLine> fileContent, final KeywordTable keywordTable) { final List<UserKeyword> keywords = keywordTable.getKeywords(); for (final UserKeyword keyword : keywords) { final List<KeywordDocumentation> documentation = keyword.getDocumentation(); for (final KeywordDocumentation keywordDocumentation : documentation) { final RobotToken declaration = keywordDocumentation.getDeclaration(); keywordDocumentation.clearDocumentation(); final List<RobotToken> docTokens = tokensBelongs(fileContent, declaration, RobotTokenType.KEYWORD_SETTING_DOCUMENTATION_TEXT, RobotTokenType.PRETTY_ALIGN_SPACE, RobotTokenType.PREVIOUS_LINE_CONTINUE); for (final RobotToken textDoc : docTokens) { documentation.get(0).addDocumentationText(textDoc); } } } } private void testsDocumentationApplyContinueTokens(final List<RobotLine> fileContent, final TestCaseTable testCaseTable) { final List<TestCase> testCases = testCaseTable.getTestCases(); for (final TestCase testCase : testCases) { final List<TestDocumentation> documentation = testCase.getDocumentation(); for (final TestDocumentation testDocumentation : documentation) { final RobotToken declaration = testDocumentation.getDeclaration(); testDocumentation.clearDocumentation(); final List<RobotToken> docTokens = tokensBelongs(fileContent, declaration, RobotTokenType.TEST_CASE_SETTING_DOCUMENTATION_TEXT, RobotTokenType.PRETTY_ALIGN_SPACE, RobotTokenType.PREVIOUS_LINE_CONTINUE); for (final RobotToken textDoc : docTokens) { documentation.get(0).addDocumentationText(textDoc); } } } } @VisibleForTesting protected List<RobotToken> tokensBelongs(final List<RobotLine> fileContent, final RobotToken declaration, final IRobotTokenType... acceptable) { final FilePosition declarationPosition = declaration.getFilePosition(); if (declarationPosition.isNotSet()) { return tokensBelongsByToken(fileContent, 0, declaration, acceptable); } else { return tokensBelongsByToken(fileContent, declarationPosition.getLine() - 1, declaration, acceptable); } } private List<RobotToken> tokensBelongsByToken(final List<RobotLine> fileContent, final int searchStartNumber, final RobotToken declaration, final IRobotTokenType... acceptable) { final List<RobotToken> toks = new ArrayList<>(0); Optional<Integer> elementPositionInLine = Optional.empty(); final int lines = fileContent.size(); boolean fetchMode = false; for (int lineNumber = searchStartNumber; lineNumber < lines; lineNumber++) { final RobotLine line = fileContent.get(lineNumber); if (fetchMode) { final List<IRobotLineElement> lineElements = line.getLineElements(); for (int i = 0; i < lineElements.size(); i++) { final IRobotLineElement elem = lineElements.get(i); final List<IRobotTokenType> elemTypes = elem.getTypes(); if (isAnyOfType(elemTypes, SeparatorType.PIPE, SeparatorType.TABULATOR_OR_DOUBLE_SPACE, RobotTokenType.START_HASH_COMMENT, RobotTokenType.COMMENT_CONTINUE)) { continue; } else if (isAnyOfType(elemTypes, acceptable)) { if (elemTypes.contains(RobotTokenType.PREVIOUS_LINE_CONTINUE) && !elem.getText().trim().equals("...")) { return toks; } toks.add((RobotToken) elem); } else { return toks; } } } else if (elementPositionInLine.isPresent()) { // line with declaration final List<IRobotLineElement> lineElements = line.getLineElements(); for (int i = elementPositionInLine.get() + 1; i < lineElements.size(); i++) { final IRobotLineElement elem = lineElements.get(i); final List<IRobotTokenType> elemTypes = elem.getTypes(); if (isAnyOfType(elemTypes, SeparatorType.PIPE, SeparatorType.TABULATOR_OR_DOUBLE_SPACE, RobotTokenType.START_HASH_COMMENT, RobotTokenType.COMMENT_CONTINUE)) { continue; } else if (isAnyOfType(elemTypes, acceptable)) { toks.add((RobotToken) elem); } else { return toks; } } fetchMode = true; } else { elementPositionInLine = line.getElementPositionInLine(declaration); if (elementPositionInLine.isPresent()) { lineNumber--; } } } return toks; } private boolean isAnyOfType(final List<IRobotTokenType> elemTypes, final IRobotTokenType... acceptable) { final List<IRobotTokenType> accept = Arrays.asList(acceptable); for (final IRobotTokenType e : elemTypes) { if (accept.contains(e)) { return true; } } return false; } }