/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.idea.blaze.base.lang.buildfile.parser;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.idea.blaze.base.lang.buildfile.BuildFileIntegrationTestCase;
import com.google.idea.blaze.base.lang.buildfile.psi.BuildElement;
import com.google.idea.blaze.base.lang.buildfile.psi.LoadStatement;
import com.intellij.lang.ASTNode;
import com.intellij.lang.FileASTNode;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.PsiParser;
import com.intellij.lang.impl.PsiBuilderAdapter;
import com.intellij.lang.impl.PsiBuilderImpl;
import com.intellij.lexer.Lexer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.CharTableImpl;
import com.intellij.psi.impl.source.tree.LeafElement;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Test for the BUILD file parser (converting lexical elements into PSI elements) */
@RunWith(JUnit4.class)
public class BuildParserTest extends BuildFileIntegrationTestCase {

  private final List<String> errors = Lists.newArrayList();

  @After
  public final void doTearDown() {
    errors.clear();
  }

  @Test
  public void testAugmentedAssign() throws Exception {
    assertThat(parse("x += 1")).isEqualTo("aug_assign(reference, int)");
    assertThat(parse("x -= 1")).isEqualTo("aug_assign(reference, int)");
    assertThat(parse("x *= 1")).isEqualTo("aug_assign(reference, int)");
    assertThat(parse("x /= 1")).isEqualTo("aug_assign(reference, int)");
    assertThat(parse("x %= 1")).isEqualTo("aug_assign(reference, int)");
    assertNoErrors();
  }

  @Test
  public void testAssign() throws Exception {
    assertThat(parse("a, b = 5\n")).isEqualTo("assignment(list(reference, target), int)");
    assertNoErrors();
  }

  @Test
  public void testAssign2() throws Exception {
    assertThat(parse("a = b;c = d\n"))
        .isEqualTo(
            Joiner.on("").join("assignment(target, reference), ", "assignment(target, reference)"));
    assertNoErrors();
  }

  @Test
  public void testInvalidAssign() throws Exception {
    parse("1 + (b = c)");
    assertContainsErrors();
  }

  @Test
  public void testTupleAssign() throws Exception {
    assertThat(parse("list[0] = 5; dict['key'] = value\n"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "assignment(function_call(reference, positional(int)), int), ",
                    "assignment(function_call(reference, positional(string)), reference)"));
    assertNoErrors();
  }

  @Test
  public void testPrimary() throws Exception {
    assertThat(parse("f(1 + 2)"))
        .isEqualTo("function_call(reference, arg_list(positional(binary_op(int, int))))");
    assertNoErrors();
  }

  @Test
  public void testSecondary() throws Exception {
    assertThat(parse("f(1 % 2)"))
        .isEqualTo("function_call(reference, arg_list(positional(binary_op(int, int))))");
    assertNoErrors();
  }

  @Test
  public void testDoesNotGetStuck() throws Exception {
    // Make sure the parser does not get stuck when trying
    // to parse an expression containing a syntax error.
    parse("f(1, ], 3)");
    parse("f(1, ), 3)");
    parse("[ ) for v in 3)");
    parse("f(1, [x for foo foo foo foo], 3)");
  }

  @Test
  public void testInvalidFunctionStatementDoesNotGetStuck() throws Exception {
    // Make sure the parser does not get stuck when trying
    // to parse a function statement containing a syntax error.
    parse("def is ");
    parse("def fn(");
    parse("def empty)");
  }

  @Test
  public void testSubstring() throws Exception {
    assertThat(parse("'FOO.CC'[:].lower()[1:]"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "function_call(",
                    "function_call(function_call(string), reference, arg_list), ",
                    "positional(int))"));
    assertNoErrors();
  }

  @Test
  public void testFuncallExpr() throws Exception {
    assertThat(parse("foo(1, 2, bar=wiz)"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "function_call(reference, arg_list(",
                    "positional(int), ",
                    "positional(int), ",
                    "keyword(reference)))"));
    assertNoErrors();
  }

  @Test
  public void testMethCallExpr() throws Exception {
    assertThat(parse("foo.foo(1, 2, bar=wiz)"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "function_call(reference, reference, ",
                    "arg_list(positional(int), positional(int), keyword(reference)))"));
    assertNoErrors();
  }

  @Test
  public void testChainedMethCallExpr() throws Exception {
    assertThat(parse("foo.replace().split(1)"))
        .isEqualTo(
            "function_call(function_call(reference, reference, arg_list), "
                + "reference, arg_list(positional(int)))");
    assertNoErrors();
  }

  @Test
  public void testPropRefExpr() throws Exception {
    assertThat(parse("foo.foo")).isEqualTo("dot_expr(reference, reference)");
    assertNoErrors();
  }

  @Test
  public void testStringMethExpr() throws Exception {
    assertThat(parse("'foo'.foo()")).isEqualTo("function_call(string, reference, arg_list)");
    assertNoErrors();
  }

  @Test
  public void testFuncallLocation() throws Exception {
    assertThat(parse("a(b);c = d\n"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "function_call(reference, arg_list(positional(reference))), ",
                    "assignment(target, reference)"));
    assertNoErrors();
  }

  @Test
  public void testList() throws Exception {
    assertThat(parse("[0,f(1),2]"))
        .isEqualTo("list(int, function_call(reference, arg_list(positional(int))), int)");
    assertNoErrors();
  }

  @Test
  public void testDict() throws Exception {
    assertThat(parse("{1:2,2:f(1),3:4}"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "dict(",
                    "dict_entry(int, int), ",
                    "dict_entry(int, function_call(reference, arg_list(positional(int)))), ",
                    "dict_entry(int, int)",
                    ")"));
    assertNoErrors();
  }

  @Test
  public void testArgumentList() throws Exception {
    assertThat(parse("f(0,g(1,2),2)"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "function_call(reference, arg_list(",
                    "positional(int), ",
                    "positional("
                        + "function_call(reference, arg_list(positional(int), positional(int)))), ",
                    "positional(int)))"));
    assertNoErrors();
  }

  @Test
  public void testForBreakContinue() throws Exception {
    String parsed =
        parse("def foo():", "  for i in [1, 2]:", "    break", "    continue", "    break");
    assertThat(parsed)
        .isEqualTo(
            Joiner.on("")
                .join(
                    "function_def(parameter_list, ",
                    "stmt_list(for(target, list(int, int), ",
                    "stmt_list(flow, flow, flow))))"));
    assertNoErrors();
  }

  @Test
  public void testEmptyTuple() throws Exception {
    assertThat(parse("()")).isEqualTo("list");
    assertNoErrors();
  }

  @Test
  public void testTupleTrailingComma() throws Exception {
    assertThat(parse("(42,)")).isEqualTo("list(int)");
    assertNoErrors();
  }

  @Test
  public void testSingleton() throws Exception {
    assertThat(parse("(42)")) // not a tuple!
        .isEqualTo("list(int)");
    assertNoErrors();
  }

  @Test
  public void testDictionaryLiterals() throws Exception {
    assertThat(parse("{1:42}")).isEqualTo("dict(dict_entry(int, int))");
    assertNoErrors();
  }

  @Test
  public void testDictionaryLiterals1() throws Exception {
    assertThat(parse("{}")).isEqualTo("dict");
    assertNoErrors();
  }

  @Test
  public void testDictionaryLiterals2() throws Exception {
    assertThat(parse("{1:42,}")).isEqualTo("dict(dict_entry(int, int))");
    assertNoErrors();
  }

  @Test
  public void testDictionaryLiterals3() throws Exception {
    assertThat(parse("{1:42,2:43,3:44}"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "dict(",
                    "dict_entry(int, int), ",
                    "dict_entry(int, int), ",
                    "dict_entry(int, int))"));
    assertNoErrors();
  }

  @Test
  public void testInvalidListComprehensionSyntax() throws Exception {
    assertThat(parse("[x for x for y in ['a']]")).isEqualTo("list_comp(reference, reference)");
    assertContainsErrors();
  }

  @Test
  public void testListComprehensionEmptyList() throws Exception {
    // At the moment, we just parse the components of comprehension suffixes.
    assertThat(parse("['foo/%s.java' % x for x in []]"))
        .isEqualTo("list_comp(binary_op(string, reference), target, list)");
    assertNoErrors();
  }

  @Test
  public void testListComprehension() throws Exception {
    assertThat(parse("['foo/%s.java' % x for x in ['bar', 'wiz', 'quux']]"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "list_comp(binary_op(string, reference), ",
                    "target, ",
                    "list(string, string, string))"));
    assertNoErrors();
  }

  @Test
  public void testDoesntGetStuck2() throws Exception {
    parse(
        "def foo():",
        "  a = 2 for 4", // parse error
        "  b = [3, 4]",
        "",
        "d = 4 ada", // parse error
        "",
        "def bar():",
        "  a = [3, 4]",
        "  b = 2 + + 5", // parse error
        "");
    assertContainsErrors();
  }

  @Test
  public void testDoesntGetStuck3() throws Exception {
    parse("load(*)");
    parse("load()");
    parse("load(,)");
    parse("load)");
    parse("load(,");
    parse("load(,\"string\"");
    assertContainsErrors();
  }

  @Test
  public void testExprAsStatement() throws Exception {
    String parsed =
        parse("li = []", "li.append('a.c')", "\"\"\" string comment \"\"\"", "foo(bar)");
    assertThat(parsed)
        .isEqualTo(
            Joiner.on("")
                .join(
                    "assignment(target, list), ",
                    "function_call(reference, reference, arg_list(positional(string))), ",
                    "string, ",
                    "function_call(reference, arg_list(positional(reference)))"));
    assertNoErrors();
  }

  @Test
  public void testPrecedence1() {
    assertThat(parse("'%sx' % 'foo' + 'bar'"))
        .isEqualTo("binary_op(binary_op(string, string), string)");
    assertNoErrors();
  }

  @Test
  public void testPrecedence2() {
    assertThat(parse("('%sx' + 'foo') * 'bar'"))
        .isEqualTo("binary_op(list(binary_op(string, string)), string)");
    assertNoErrors();
  }

  @Test
  public void testPrecedence3() {
    assertThat(parse("'%sx' % ('foo' + 'bar')"))
        .isEqualTo("binary_op(string, list(binary_op(string, string)))");
    assertNoErrors();
  }

  @Test
  public void testPrecedence4() throws Exception {
    assertThat(parse("1 + - (2 - 3)"))
        .isEqualTo("binary_op(int, positional(list(binary_op(int, int))))");
    assertNoErrors();
  }

  @Test
  public void testPrecedence5() throws Exception {
    assertThat(parse("2 * x | y + 1"))
        .isEqualTo("binary_op(binary_op(int, reference), binary_op(reference, int))");
    assertNoErrors();
  }

  @Test
  public void testNotIsIgnored() throws Exception {
    assertThat(parse("not 'b'")).isEqualTo("string");
    assertNoErrors();
  }

  @Test
  public void testNotIn() throws Exception {
    assertThat(parse("'a' not in 'b'")).isEqualTo("binary_op(string, string)");
    assertNoErrors();
  }

  @Test
  public void testParseBuildFileWithSingeRule() throws Exception {
    ASTNode tree =
        createAST(
            "genrule(name = 'foo',",
            "   srcs = ['input.csv'],",
            "   outs = [ 'result.txt',",
            "           'result.log'],",
            "   cmd = 'touch result.txt result.log')");
    List<BuildElement> stmts = getTopLevelNodesOfType(tree, BuildElement.class);
    assertThat(stmts).hasSize(1);
    assertNoErrors();
  }

  @Test
  public void testParseBuildFileWithMultipleRules() throws Exception {
    ASTNode tree =
        createAST(
            "genrule(name = 'foo',",
            "   srcs = ['input.csv'],",
            "   outs = [ 'result.txt',",
            "           'result.log'],",
            "   srcs = ['input.csv'],",
            "   cmd = 'touch result.txt result.log')",
            "",
            "genrule(name = 'bar',",
            "   outs = [ 'graph.svg'],",
            "   cmd = 'touch graph.svg')");
    List<BuildElement> stmts = getTopLevelNodesOfType(tree, BuildElement.class);
    assertThat(stmts).hasSize(2);
    assertNoErrors();
  }

  @Test
  public void testMissingComma() throws Exception {
    // missing comma after name='foo'
    parse("genrule(name = 'foo'", "   srcs = ['in'])");
    assertContainsError("',' expected");
  }

  @Test
  public void testDoubleSemicolon() throws Exception {
    parse("x = 1; ; x = 2;");
    assertContainsError("expected an expression");
  }

  @Test
  public void testMissingBlock() throws Exception {
    parse("x = 1;", "def foo(x):", "x = 2;\n");
    assertContainsError("'indent' expected");
  }

  @Test
  public void testFunCallBadSyntax() throws Exception {
    parse("f(1,\n");
    assertContainsError("')' expected");
  }

  @Test
  public void testFunCallBadSyntax2() throws Exception {
    parse("f(1, 5, ,)\n");
    assertContainsError("expected an expression");
  }

  @Test
  public void testLoad() throws Exception {
    ASTNode tree = createAST("load('file', 'foo', 'bar',)\n");
    List<LoadStatement> stmts = getTopLevelNodesOfType(tree, LoadStatement.class);
    assertThat(stmts).hasSize(1);

    LoadStatement stmt = stmts.get(0);
    assertThat(stmt.getImportedPath()).isEqualTo("file");
    assertThat(stmt.getVisibleSymbolNames()).isEqualTo(new String[] {"foo", "bar"});
    assertNoErrors();
  }

  @Test
  public void testLoadWithAlias() throws Exception {
    ASTNode tree = createAST("load('file', 'foo', baz = 'bar',)\n");
    List<LoadStatement> stmts = getTopLevelNodesOfType(tree, LoadStatement.class);
    assertThat(stmts).hasSize(1);

    LoadStatement stmt = stmts.get(0);
    assertThat(stmt.getImportedPath()).isEqualTo("file");
    assertThat(stmt.getVisibleSymbolNames()).isEqualTo(new String[] {"foo", "baz"});
    assertNoErrors();
  }

  @Test
  public void testLoadNoSymbol() throws Exception {
    parse("load('/foo/bar/file')\n");
    assertContainsError("'load' statements must include at least one loaded function");
  }

  @Test
  public void testFunctionDefinition() throws Exception {
    ASTNode tree =
        createAST(
            "def function(name = 'foo', srcs, outs, *args, **kwargs):",
            "   native.java_library(",
            "     name = name,",
            "     srcs = srcs,",
            "   )",
            "   return");
    List<BuildElement> stmts = getTopLevelNodesOfType(tree, BuildElement.class);
    assertThat(stmts).hasSize(1);
    assertNoErrors();
  }

  @Test
  public void testFunctionCall() throws Exception {
    ASTNode tree = createAST("function(name = 'foo', srcs, *args, **kwargs)");
    List<BuildElement> stmts = getTopLevelNodesOfType(tree, BuildElement.class);
    assertThat(stmts).hasSize(1);
    assertThat(treeToString(tree))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "function_call(reference, arg_list(",
                    "keyword(string), ",
                    "positional(reference), ",
                    "*(reference), ",
                    "**(reference)))"));
    assertNoErrors();
  }

  @Test
  public void testConditionalStatement() throws Exception {
    // we don't yet bother specifying which kind of conditionals we hit
    assertThat(parse("if x : y elif a : b else c"))
        .isEqualTo(
            Joiner.on("")
                .join(
                    "if(",
                    "if_part(reference, reference), ",
                    "else_if_part(reference, reference), ",
                    "else_part(reference))"));
  }

  private ASTNode createAST(String... lines) {
    StringBuilder builder = new StringBuilder();
    for (String line : lines) {
      builder.append(line).append("\n");
    }
    return createAST(builder.toString());
  }

  private ASTNode createAST(String text) {
    ParserDefinition definition = new BuildParserDefinition();
    PsiParser parser = definition.createParser(getProject());
    Lexer lexer = definition.createLexer(getProject());
    PsiBuilderImpl psiBuilder =
        new PsiBuilderImpl(
            getProject(), null, definition, lexer, new CharTableImpl(), text, null, null);
    PsiBuilderAdapter adapter =
        new PsiBuilderAdapter(psiBuilder) {
          @Override
          public void error(String messageText) {
            super.error(messageText);
            errors.add(messageText);
          }
        };
    return parser.parse(definition.getFileNodeType(), adapter);
  }

  private String parse(String... lines) {
    StringBuilder builder = new StringBuilder();
    for (String line : lines) {
      builder.append(line).append("\n");
    }
    return parse(builder.toString());
  }

  private String parse(String text) {
    ASTNode tree = createAST(text);
    return treeToString(tree);
  }

  private String treeToString(ASTNode tree) {
    StringBuilder builder = new StringBuilder();
    nodeToString(tree, builder);
    return builder.toString();
  }

  private void nodeToString(ASTNode node, StringBuilder builder) {
    if (node instanceof LeafElement || node.getPsi() == null) {
      return;
    }
    PsiElement[] childPsis = getChildBuildPsis(node);
    if (node instanceof FileASTNode) {
      appendChildren(childPsis, builder, false);
      return;
    }
    builder.append(node.getElementType());
    appendChildren(childPsis, builder, true);
  }

  private void appendChildren(PsiElement[] childPsis, StringBuilder builder, boolean bracket) {
    if (childPsis.length == 0) {
      return;
    }
    if (bracket) {
      builder.append("(");
    }
    nodeToString(childPsis[0].getNode(), builder);
    for (int i = 1; i < childPsis.length; i++) {
      builder.append(", ");
      nodeToString(childPsis[i].getNode(), builder);
    }
    if (bracket) {
      builder.append(")");
    }
  }

  private static <T> List<T> getTopLevelNodesOfType(ASTNode node, Class<T> clazz) {
    return (List)
        Arrays.stream(node.getChildren(null))
            .map(ASTNode::getPsi)
            .filter(psiElement -> clazz.isInstance(psiElement))
            .collect(Collectors.toList());
  }

  private PsiElement[] getChildBuildPsis(ASTNode node) {
    return Arrays.stream(node.getChildren(null))
        .map(ASTNode::getPsi)
        .filter(psiElement -> psiElement instanceof BuildElement)
        .toArray(PsiElement[]::new);
  }

  private void assertNoErrors() {
    assertThat(errors).isEmpty();
  }

  private void assertContainsErrors() {
    assertThat(errors).isNotEmpty();
  }

  private void assertContainsError(String message) {
    assertThat(errors).contains(message);
  }
}
