vscode#DefinitionProvider TypeScript Examples

The following examples show how to use vscode#DefinitionProvider. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ALInheritDocDefinitionProvider.ts    From vscode-alxmldocumentation with MIT License 5 votes vote down vote up
export class ALInheritDocDefinitionProvider implements DefinitionProvider {
    async provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Location | Location[] | LocationLink[] | null | undefined> {
        if (document.lineAt(position.line).text.trim().startsWith('///')) {
            // if code reference (cref) is found.
            let codeRef: RegExpMatchArray | null = document.lineAt(position.line).text.match(InheritDocRegEx);
            if (codeRef === null) {
                return;
            }

            // get actual AL Object.
            let alObject: ALObject | null = await ALSyntaxUtil.GetALObject(document);
            if ((alObject === null) || (alObject.Uri === undefined)) {
                return;
            }

            // split code reference.
            let codeRefProcedureCode: string = codeRef.groups!['CodeReference'];
            let codeRefObjectName: string|undefined = alObject?.ExtensionObject;
            if (!codeRefObjectName) {
                return;
            }

            let objDefinition: Array<Location> | undefined = await ALSyntaxUtil.GetObjectDefinition(ALObjectType.Interface, codeRefObjectName);
            if (objDefinition === undefined) {
                return;
            }

            if (((document.lineAt(position.line).text.indexOf(codeRefObjectName)) <= position.character) && 
                ((document.lineAt(position.line).text.indexOf(codeRefObjectName) + codeRefObjectName.length) >= position.character)) {
                // build object return definition.
                let definition: Location | undefined = new Location(objDefinition[0].uri, new Range(
                    new Position(alObject.LineNo, 0),
                    new Position(alObject.LineNo, 0)));            

                return definition;
            }

            if ((document.lineAt(position.line).text.indexOf(codeRefObjectName)) < position.character) {
                let interfaceObj: ALObject | undefined = ALObjectCache.ALObjects.find((interfaceObj) => (interfaceObj.Name === codeRefObjectName));
                if (!interfaceObj) {
                    return;
                }

                let alProcedure: ALProcedure | undefined = interfaceObj?.Procedures?.find((alProcedure) => /*(alProcedure.LineNo > position.line) && */(alProcedure.Code === codeRefProcedureCode));
                if (alProcedure === undefined) {
                    return;
                }

                // build return definition.
                let definition: Location | undefined = new Location(objDefinition[0].uri, new Range(
                    new Position(alProcedure.Range!.start.line, alProcedure.Range!.start.character),
                    new Position(alProcedure.Range!.end.line, alProcedure.Range!.end.character)));            

                return definition;
            }
        }
    }
}
Example #2
Source File: modelDefinitionProvider.ts    From vscode-dbt-power-user with MIT License 5 votes vote down vote up
@provideSingleton(ModelDefinitionProvider)
export class ModelDefinitionProvider implements DefinitionProvider, Disposable {
  private modelToLocationMap: Map<string, NodeMetaMap> = new Map();
  private static readonly IS_REF = /(ref)\([^)]*\)/;
  private static readonly GET_DBT_MODEL = /(?!'|")([^(?!'|")]*)(?='|")/gi;
  private disposables: Disposable[] = [];

  constructor(private dbtProjectContainer: DBTProjectContainer) {
    this.disposables.push(
      dbtProjectContainer.onManifestChanged((event) =>
        this.onManifestCacheChanged(event)
      )
    );
  }

  dispose() {
    this.disposables.forEach((disposable) => disposable.dispose());
  }

  provideDefinition(
    document: TextDocument,
    position: Position,
    token: CancellationToken
  ): ProviderResult<Definition | DefinitionLink[]> {
    return new Promise((resolve, reject) => {
      const hover = document.getText(document.getWordRangeAtPosition(position));
      const word = document.getText(
        document.getWordRangeAtPosition(
          position,
          ModelDefinitionProvider.IS_REF
        )
      );
      if (word !== undefined && hover !== "ref") {
        const dbtModel = word.match(ModelDefinitionProvider.GET_DBT_MODEL);
        if (dbtModel && dbtModel.length === 1) {
          const definition = this.getDefinitionFor(dbtModel[0], document.uri);
          resolve(definition);
          return;
        }
      }
      reject();
    });
  }

  private onManifestCacheChanged(event: ManifestCacheChangedEvent): void {
    event.added?.forEach((added) => {
      this.modelToLocationMap.set(added.projectRoot.fsPath, added.nodeMetaMap);
    });
    event.removed?.forEach((removed) => {
      this.modelToLocationMap.delete(removed.projectRoot.fsPath);
    });
  }

  private getDefinitionFor(
    name: string,
    currentFilePath: Uri
  ): Definition | undefined {
    const projectRootpath = this.dbtProjectContainer.getProjectRootpath(
      currentFilePath
    );
    if (projectRootpath === undefined) {
      return;
    }
    const nodeMap = this.modelToLocationMap.get(projectRootpath.fsPath);
    if (nodeMap === undefined) {
      return;
    }
    const location = nodeMap.get(name);
    if (location) {
      return new Location(Uri.file(location.path), new Range(0, 0, 0, 0));
    }
    return undefined;
  }
}
Example #3
Source File: macroDefinitionProvider.ts    From vscode-dbt-power-user with MIT License 4 votes vote down vote up
@provideSingleton(MacroDefinitionProvider)
export class MacroDefinitionProvider implements DefinitionProvider, Disposable {
  private macroToLocationMap: Map<string, MacroMetaMap> = new Map();
  private static readonly IS_MACRO = /\w+\.?\w+/;
  private disposables: Disposable[] = [];

  constructor(private dbtProjectContainer: DBTProjectContainer) {
    this.disposables.push(
      dbtProjectContainer.onManifestChanged((event) =>
        this.onManifestCacheChanged(event)
      )
    );
  }

  dispose() {
    this.disposables.forEach((disposable) => disposable.dispose());
  }

  provideDefinition(
    document: TextDocument,
    position: Position
  ): ProviderResult<Definition | DefinitionLink[]> {
    return new Promise((resolve, reject) => {
      const textLine = document.lineAt(position).text;
      const range = document.getWordRangeAtPosition(
        position,
        MacroDefinitionProvider.IS_MACRO
      );
      const word = document.getText(range);
      if (
        range &&
        textLine[range.end.character] === "(" &&
        isEnclosedWithinCodeBlock(document, range)
      ) {
        const packageName = this.dbtProjectContainer.getPackageName(
          document.uri
        );

        const macroName =
          packageName !== undefined && !word.includes(".")
            ? `${packageName}.${word}`
            : word;

        const definition = this.getMacroDefinition(macroName, document.uri);
        if (definition !== undefined) {
          resolve(definition);
          return;
        }
      }
      reject();
    });
  }

  private onManifestCacheChanged(event: ManifestCacheChangedEvent): void {
    event.added?.forEach((added) => {
      this.macroToLocationMap.set(added.projectRoot.fsPath, added.macroMetaMap);
    });
    event.removed?.forEach((removed) => {
      this.macroToLocationMap.delete(removed.projectRoot.fsPath);
    });
  }

  private getMacroDefinition(
    macroName: string,
    currentFilePath: Uri
  ): Definition | undefined {
    const projectRootpath = this.dbtProjectContainer.getProjectRootpath(
      currentFilePath
    );
    if (projectRootpath === undefined) {
      return;
    }
    const macroMap = this.macroToLocationMap.get(projectRootpath.fsPath);
    if (macroMap === undefined) {
      return;
    }
    const location = macroMap.get(macroName);
    if (location) {
      return new Location(
        Uri.file(location.path),
        new Position(location.line, location.character)
      );
    }
    return undefined;
  }
}
Example #4
Source File: sourceDefinitionProvider.ts    From vscode-dbt-power-user with MIT License 4 votes vote down vote up
@provideSingleton(SourceDefinitionProvider)
export class SourceDefinitionProvider
  implements DefinitionProvider, Disposable {
  private sourceMetaMap: Map<string, SourceMetaMap> = new Map();
  private static readonly IS_SOURCE = /(source)\([^)]*\)/;
  private static readonly GET_SOURCE_INFO = /(?!['"])(\w+)(?=['"])/g;
  private disposables: Disposable[] = [];

  constructor(private dbtProjectContainer: DBTProjectContainer) {
    this.disposables.push(
      dbtProjectContainer.onManifestChanged((event) =>
        this.onManifestCacheChanged(event)
      )
    );
  }

  dispose() {
    this.disposables.forEach((disposable) => disposable.dispose());
  }

  provideDefinition(
    document: TextDocument,
    position: Position,
    token: CancellationToken
  ): ProviderResult<Definition | DefinitionLink[]> {
    return new Promise((resolve, reject) => {
      const hover = document.getText(document.getWordRangeAtPosition(position));
      const range = document.getWordRangeAtPosition(
        position,
        SourceDefinitionProvider.IS_SOURCE
      );
      const word = document.getText(range);

      const linePrefix = document
        .lineAt(position)
        .text.substr(0, position.character);

      if (
        !isEnclosedWithinCodeBlock(document, position) ||
        !linePrefix.includes("source") ||
        hover === "source"
      ) {
        reject();
        return;
      }

      const source = word.match(SourceDefinitionProvider.GET_SOURCE_INFO);
      if (source === null || source === undefined) {
        reject();
        return;
      }
      if (source.length < 2) {
        reject();
        return;
      }
      const definition = this.getSourceDefinition(
        source[0],
        document.uri,
        source[1],
      );
      resolve(definition);
    });
  }

  private onManifestCacheChanged(event: ManifestCacheChangedEvent): void {
    event.added?.forEach((added) => {
      this.sourceMetaMap.set(added.projectRoot.fsPath, added.sourceMetaMap);
    });
    event.removed?.forEach((removed) => {
      this.sourceMetaMap.delete(removed.projectRoot.fsPath);
    });
  }

  private getSourceDefinition(
    sourceName: string,
    currentFilePath: Uri,
    tableName: string
  ): Definition | undefined {
    const projectRootpath = this.dbtProjectContainer.getProjectRootpath(
      currentFilePath
    );
    if (projectRootpath === undefined) {
      return;
    }
    const sourceMap = this.sourceMetaMap.get(projectRootpath.fsPath);
    if (sourceMap === undefined) {
      return;
    }
    const location = sourceMap
      .get(sourceName)
      ?.tables.find((table) => table.name === tableName);
    if (location) {
      const sourceFile: string = readFileSync(location.path).toString("utf8");
      const sourceFileLines = sourceFile.split("\n");
      for (let index = 0; index < sourceFileLines.length; index++) {
        const currentLine = sourceFileLines[index];
        if (currentLine.includes(tableName)) {
          return new Location(
            Uri.file(location.path),
            new Position(index, currentLine.indexOf(tableName))
          );
        }
      }
    }
    return undefined;
  }
}