<commit_before>/**
 * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at
 * http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at
 * http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */

import * as parse5 from 'parse5';

import {ParsedHtmlDocument} from '../html/html-document';
import {SourceRange} from '../model/model';

import {SourcePosition} from './editor-service';


export type LocationResult = LocatedAttribute | LocatedAttributeValue |
    LocatedTag | LocatedEndTag | LocatedInText | LocatedInScript |
    LocatedInStyle | LocatedInComment;
/** In the tagname of a start tag. */
export interface LocatedTag {
  kind: 'tagName';
  element: parse5.ASTNode;
}
/** In an end tag. */
export interface LocatedEndTag {
  kind: 'endTag';
  element: parse5.ASTNode;
}
/** In the attributes section of a start tag. Maybe in an attribute name. */
export interface LocatedAttribute {
  kind: 'attribute';
  attribute: string|null;
  element: parse5.ASTNode;
}
/** In the value of an attribute of a start tag. */
export interface LocatedAttributeValue {
  kind: 'attributeValue';
  attribute: string;
  element: parse5.ASTNode;
}
/** In a text node. */
export interface LocatedInText {
  kind: 'text';
  textNode?: parse5.ASTNode;
}
/** In the text of a <script> */
export interface LocatedInScript {
  kind: 'scriptTagContents';
  textNode?: parse5.ASTNode;
}
/** In the text of a <style> */
export interface LocatedInStyle {
  kind: 'styleTagContents';
  textNode?: parse5.ASTNode;
}
/** In a comment. */
export interface LocatedInComment {
  kind: 'comment';
  commentNode: parse5.ASTNode;
}
export function getLocationInfoForPosition(
    document: ParsedHtmlDocument, position: SourcePosition): LocationResult {
  const location =
      _getLocationInfoForPosition(document.ast, position, document);
  if (!location) {
    return {kind: 'text'};
  }
  return location;
}
function _getLocationInfoForPosition(
    node: parse5.ASTNode, position: SourcePosition,
    document: ParsedHtmlDocument): undefined|LocationResult {
  const sourceRange = document.sourceRangeForNode(node);
  const location = node.__location;
  if (!(sourceRange && location)) {
    return _findLocationInChildren(node, position, document);
  }

  if (!isPositionInsideRange(position, sourceRange)) {
    // definitively not in this node or any of its children
    return;
  }

  const locationInChildren = _findLocationInChildren(node, position, document);
  if (locationInChildren) {
    return locationInChildren;
  }<commit_msg>Document getLocationInfoForPosition<commit_after>/**
 * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at
 * http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at
 * http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */

import * as parse5 from 'parse5';

import {ParsedHtmlDocument} from '../html/html-document';
import {SourceRange} from '../model/model';

import {SourcePosition} from './editor-service';


export type LocationResult = LocatedAttribute | LocatedAttributeValue |
    LocatedTag | LocatedEndTag | LocatedInText | LocatedInScript |
    LocatedInStyle | LocatedInComment;
/** In the tagname of a start tag. */
export interface LocatedTag {
  kind: 'tagName';
  element: parse5.ASTNode;
}
/** In an end tag. */
export interface LocatedEndTag {
  kind: 'endTag';
  element: parse5.ASTNode;
}
/** In the attributes section of a start tag. Maybe in an attribute name. */
export interface LocatedAttribute {
  kind: 'attribute';
  attribute: string|null;
  element: parse5.ASTNode;
}
/** In the value of an attribute of a start tag. */
export interface LocatedAttributeValue {
  kind: 'attributeValue';
  attribute: string;
  element: parse5.ASTNode;
}
/** In a text node. */
export interface LocatedInText {
  kind: 'text';
  textNode?: parse5.ASTNode;
}
/** In the text of a <script> */
export interface LocatedInScript {
  kind: 'scriptTagContents';
  textNode?: parse5.ASTNode;
}
/** In the text of a <style> */
export interface LocatedInStyle {
  kind: 'styleTagContents';
  textNode?: parse5.ASTNode;
}
/** In a comment. */
export interface LocatedInComment {
  kind: 'comment';
  commentNode: parse5.ASTNode;
}

/**
 * Given a position and an HTML document, try to describe what new text typed
 * at the given position would be.
 *
 * Where possible we try to return the ASTNode describing that position, but
 * sometimes there does not actually exist one. (for a simple case, the empty
 * string should be interpreted as a text node, but there is no text node in
 * an empty document, but there would be after the first character was typed).
 */
export function getLocationInfoForPosition(
    document: ParsedHtmlDocument, position: SourcePosition): LocationResult {
  const location =
      _getLocationInfoForPosition(document.ast, position, document);
  if (!location) {
    return {kind: 'text'};
  }
  return location;
}
function _getLocationInfoForPosition(
    node: parse5.ASTNode, position: SourcePosition,
    document: ParsedHtmlDocument): undefined|LocationResult {
  const sourceRange = document.sourceRangeForNode(node);
  const location = node.__location;
  if (!(sourceRange && location)) {
    return _findLocationInChildren(node, position, document);
  }

  if (!isPositionInsideRange(position, sourceRange)) {
    // definitively not in this node or any of its children
    return;
  }

  const locationInChildren = _findLocationInChildren(node, position, document);
  if (locationInChildren) {
    return locationInChildren;
  }
{'fraction_non_alphanumeric': 0.10125765881973557, 'fraction_numerical': 0.004837149306675266, 'mean_word_length': 4.230185497470489, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1879587', 'n_tokens_mistral': 1773, 'n_tokens_neox': 1738, 'n_words': 620}