// Copyright 2018 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.devtools.build.lib.includescanning;

import com.google.common.base.CharMatcher;
import com.google.devtools.build.lib.includescanning.IncludeParser.Inclusion.Kind;

/** Parses swig files and extracts their includes (%include / %extern / %import). */
class SwigIncludeParser extends IncludeParser {

  SwigIncludeParser() {
    // There are no preprocessor-macro hints for swig.
    super(/* hints= */ null);
  }

  private static int skipParentheses(byte[] chars, int pos, int end) {
    // TODO(bazel-team): In theory this could be multiline, but the include scanner currently works
    // on a single line.
    int openedParentheses = 1;
    if (pos >= end || chars[pos] != '(') {
      return pos;
    }
    pos++;
    while (openedParentheses > 0 && pos < end) {
      if (chars[pos] == '(') {
        openedParentheses++;
      } else if (chars[pos] == ')') {
        openedParentheses--;
      }
      pos++;
    }
    return pos;
  }

  @Override
  /** See javadoc for {@link IncludeParser#getFileType()} */
  protected GrepIncludesFileType getFileType() {
    return GrepIncludesFileType.SWIG;
  }

  @Override
  protected IncludesKeywordData expectIncludeKeyword(byte[] chars, int pos, int end) {
    int start = skipWhitespace(chars, pos, end);
    if ((pos = expect(chars, start, end, "%include")) == -1
        && (pos = expect(chars, start, end, "%extern")) == -1
        && (pos = expect(chars, start, end, "%import")) == -1) {
      return IncludesKeywordData.NONE;
    }
    int npos = skipWhitespace(chars, pos, end);
    npos = skipParentheses(chars, npos, end);
    npos = skipWhitespace(chars, npos, end);
    if (npos > pos) {
      return IncludesKeywordData.importOrSwig(npos);
    }
    return IncludesKeywordData.NONE;
  }

  @Override
  protected boolean isValidInclusionKind(Kind kind) {
    return !kind.isNext();
  }

  @Override
  protected Inclusion createOtherInclusion(String inclusionContent) {
    if (inclusionContent.startsWith("/")) {
      return null; // Ignore absolute path names.
    }

    // Truncate comments after filename.
    int index = inclusionContent.indexOf("//");
    if (index > 0) {
      inclusionContent = inclusionContent.substring(0, index);
    }
    index = inclusionContent.indexOf("/*");
    if (index > 0) {
      inclusionContent = inclusionContent.substring(0, index);
    }
    // Trim whitespace.
    inclusionContent = CharMatcher.whitespace().trimFrom(inclusionContent);

    // Treat swig inclusions w/o quotes or angle brackets as quoted inclusions.
    return inclusionContent.length() > 0 ? new Inclusion(inclusionContent, Kind.QUOTE) : null;
  }
}
