<commit_before>import { extname, join } from 'path';
import { readFileSync, existsSync } from 'fs';

import { RequestHandler, TextDocumentPositionParams, Definition, Location, Range } from 'vscode-languageserver';
import { uriToFilePath } from 'vscode-languageserver/lib/files';

import { toPosition } from './estree-utils';
import Server from './server';
import { findFocusPath } from './glimmer-utils';

const { preprocess } = require('@glimmer/syntax');

export default class DefinitionProvider {
  constructor(private server: Server) {}

  handle(params: TextDocumentPositionParams): Definition | null {
    let uri = params.textDocument.uri;
    let filePath = uriToFilePath(uri);
    if (!filePath) {
      return null;
    }

    let root = this.server.projectRoots.rootForPath(filePath);
    let extension = extname(filePath);

    if (extension === '.hbs') {
      let content = readFileSync(filePath, 'utf-8');
      let ast = preprocess(content);
      let focusPath = findFocusPath(ast, toPosition(params.position));
      if (this.isComponentName(focusPath)) {
        let componentPath = focusPath[focusPath.length - 1].original;
        console.log(`looking up component: ${componentPath}`);

        let definition: Location[] = [];

        let jsPath = join(root, 'app', 'components', `${componentPath}.js`);
        if (existsSync(jsPath)) {
          console.log(`found ${jsPath}`);
          definition.push(Location.create(`file:${jsPath}`, Range.create(0, 0, 0, 0)));
        }

        let hbsPath = join(root, 'app', 'templates', 'components', `${componentPath}.hbs`);
        if (existsSync(hbsPath)) {
          console.log(`found ${hbsPath}`);
          definition.push(Location.create(`file:${hbsPath}`, Range.create(0, 0, 0, 0)));
        }

        return definition;
      }
    }

    return null;
  }

  get handler(): RequestHandler<TextDocumentPositionParams, Definition, void> {
    return this.handle.bind(this);
  }

  isComponentName(path: any[]) {
    let node = path[path.length - 1];
    if (!node || node.type !== 'PathExpression') {
      return false;<commit_msg>Use the module index for definition provider<commit_after>import { extname } from 'path';
import { readFileSync } from 'fs';

import { RequestHandler, TextDocumentPositionParams, Definition, Location, Range } from 'vscode-languageserver';
import { uriToFilePath } from 'vscode-languageserver/lib/files';

import { toPosition } from './estree-utils';
import Server from './server';
import { findFocusPath } from './glimmer-utils';

import { ModuleType, Module } from './module-index';

const { preprocess } = require('@glimmer/syntax');

export default class DefinitionProvider {
  constructor(private server: Server) {}

  handle(params: TextDocumentPositionParams): Definition | null {
    let uri = params.textDocument.uri;
    let filePath = uriToFilePath(uri);
    if (!filePath) {
      return null;
    }

    let extension = extname(filePath);

    if (extension === '.hbs') {
      let content = readFileSync(filePath, 'utf-8');
      let ast = preprocess(content);
      let focusPath = findFocusPath(ast, toPosition(params.position));

      if (this.isComponentName(focusPath)) {
        const componentName = focusPath[focusPath.length - 1].original;
        const moduleIndex = this.server.projectRoots.modulesForPath(filePath);

        if (!moduleIndex) {
          return null;
        }

        const templates = moduleIndex.getModules(ModuleType.ComponentTemplate);
        const template = templates.find(module => module.name === componentName);
        const components = moduleIndex.getModules(ModuleType.Component);
        const component = components.find(module => module.name === componentName);

        return [template, component]
          .filter(module => module)
          .map((module: Module) => Location.create(`file:${module.path}`, Range.create(0, 0, 0, 0)));
      }
    }

    return null;
  }

  get handler(): RequestHandler<TextDocumentPositionParams, Definition, void> {
    return this.handle.bind(this);
  }

  isComponentName(path: any[]) {
    let node = path[path.length - 1];
    if (!node || node.type !== 'PathExpression') {
      return false;
{'fraction_non_alphanumeric': 0.13739006417874972, 'fraction_numerical': 0.004278583313525077, 'mean_word_length': 3.486140724946695, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, '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': '502406', 'n_tokens_mistral': 1216, 'n_tokens_neox': 1188, 'n_words': 290}