<commit_before>/* --------------------------------------------------------------------------------------------
 * Copyright (c) <NAME>. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 * ------------------------------------------------------------------------------------------ */
'use strict';

import {
	TextDocument, TextDocumentPositionParams, Hover, Position
} from 'vscode-languageserver';
import { DockerfileParser, Arg, Env, Instruction, ModifiableInstruction, Onbuild, Directive } from 'dockerfile-ast';
import { Util } from './docker';
import { MarkdownDocumentation } from './dockerMarkdown';
import { DockerDefinition } from './dockerDefinition';

export class DockerHover {

	private markdown: MarkdownDocumentation;

	constructor(markdown: MarkdownDocumentation) {
		this.markdown = markdown;
	}

	onHover(document: TextDocument, textDocumentPosition: TextDocumentPositionParams): Hover | null {
		let dockerfile = DockerfileParser.parse(document.getText());
		let directive = dockerfile.getDirective();
		let image = dockerfile.getContainingImage(textDocumentPosition.position);

		if (textDocumentPosition.position.line === 0 && directive !== null && directive.getDirective() === Directive.escape) {
			let range = directive.getNameRange();
			if (Util.isInsideRange(textDocumentPosition.position, range)) {
				return this.markdown.getMarkdown(Directive.escape);
			}
		}

		for (let instruction of image.getInstructions()) {
			for (let variable of instruction.getVariables()) {
				// are we hovering over a variable
				if (Util.isInsideRange(textDocumentPosition.position, variable.getNameRange())) {
					let instructions = image.getInstructions();
					for (let i = instructions.length - 1; i >= 0; i--) {
						// only look for variables defined before the current instruction
						if (instruction.isAfter(instructions[i]) && instructions[i] instanceof Env) {
							for (let property of (instructions[i] as Env).getProperties()) {
								// check that the names match
								if (property.getName() === variable.getName()) {
									return property.getValue() !== null ? { contents: property.getValue() } : null;
								}
							}
						}
					}
				}
			}
		}

		for (let instruction of image.getInstructions()) {
			let instructionRange = instruction.getInstructionRange();
			if (Util.isInsideRange(textDocumentPosition.position, instructionRange)) {
				return this.markdown.getMarkdown(instruction.getKeyword());
			}

			if (instruction instanceof Onbuild) {
				// hovering over a trigger instruction of an ONBUILD
				let range = instruction.getTriggerRange();
				if (Util.isInsideRange(textDocumentPosition.position, range)) {
					return this.markdown.getMarkdown(instruction.getTrigger());
				}
			}

			if (instruction instanceof Arg) {
				// hovering over an argument defined by ARG
				let property = instruction.getProperty();
				if (property && Util.isInsideRange(textDocumentPosition.position, property.getNameRange()) && property.getValue() !== null) {
					return {
						contents: property.getValue()
					};
				}
			}

			if (instruction instanceof Env) {
				// hovering over an argument defined by ENV
				for (let property of instruction.getProperties()) {
					if (Util.isInsideRange(textDocumentPosition.position, property.getNameRange()) && property.getValue() !== null) {
						return {
							contents: property.getValue()
						};
					}
				}
			}

			let hover = this.getFlagsHover(textDocumentPosition.position, instruction);
			if (hover !== undefined) {
				return hover;
			}
		}

		let property = DockerDefinition.findDefinition(dockerfile, textDocumentPosition.position);
		if (property && property.getValue() !== null) {
			return { contents: property.getValue() };
		}

		return null;
	}

	private getFlagsHover(position: Position, instruction: Instruction): Hover {
		switch (instruction.getKeyword()) {
			case "ADD":
				let addFlags = (instruction as ModifiableInstruction).getFlags();
				for (let flag of addFlags) {
					if (Util.isInsideRange(position, flag.getNameRange())) {
						switch (flag.getName()) {
							case "chown":
								return this.markdown.getMarkdown("ADD_FlagChown");
						}
					}
				}
				break;
			case "COPY":
				let copyFlags = (instruction as ModifiableInstruction).getFlags();
				for (let flag of copyFlags) {
					if (Util.isInsideRange(position, flag.getNameRange())) {
						switch (flag.getName()) {
							case "chown":
								return this.markdown.getMarkdown("COPY_FlagChown");
							case "from":
								return this.markdown.getMarkdown("COPY_FlagFrom");
						}
					}
				}
				break;
			case "HEALTHCHECK":
				let flags = (instruction as ModifiableInstruction).getFlags();
				for (let flag of flags) {
					if (Util.isInsideRange(position, flag.getNameRange())) {
						switch (flag.getName()) {
							case "interval":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagInterval");
							case "retries":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagRetries");
							case "start-period":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagStartPeriod");
							case "timeout":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagTimeout");
						}
						return null;
					}
				}
				break;
			case "ONBUILD":
				let trigger = (instruction as Onbuild).getTriggerInstruction();
				if (trigger !== null) {
					return this.getFlagsHover(position, trigger);
				}
				break;
		}
		return undefined;
	}
}
<commit_msg>Replace handwritten code with dockerfile-ast's API<commit_after>/* --------------------------------------------------------------------------------------------
 * Copyright (c) <NAME>. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 * ------------------------------------------------------------------------------------------ */
'use strict';

import {
	TextDocument, TextDocumentPositionParams, Hover, Position
} from 'vscode-languageserver';
import { DockerfileParser, Arg, Env, Instruction, ModifiableInstruction, Onbuild, Directive } from 'dockerfile-ast';
import { Util } from './docker';
import { MarkdownDocumentation } from './dockerMarkdown';
import { DockerDefinition } from './dockerDefinition';

export class DockerHover {

	private markdown: MarkdownDocumentation;

	constructor(markdown: MarkdownDocumentation) {
		this.markdown = markdown;
	}

	onHover(document: TextDocument, textDocumentPosition: TextDocumentPositionParams): Hover | null {
		let dockerfile = DockerfileParser.parse(document.getText());
		let directive = dockerfile.getDirective();
		let image = dockerfile.getContainingImage(textDocumentPosition.position);

		if (textDocumentPosition.position.line === 0 && directive !== null && directive.getDirective() === Directive.escape) {
			let range = directive.getNameRange();
			if (Util.isInsideRange(textDocumentPosition.position, range)) {
				return this.markdown.getMarkdown(Directive.escape);
			}
		}

		for (let instruction of image.getInstructions()) {
			for (let variable of instruction.getVariables()) {
				// are we hovering over a variable
				if (Util.isInsideRange(textDocumentPosition.position, variable.getNameRange())) {
					let resolved = image.resolveVariable(variable.getName(), variable.getNameRange().start.line);
					if (resolved || resolved === "") {
						return { contents: resolved };
					} else if (resolved === null) {
						return null;
					}
				}
			}
		}

		for (let instruction of image.getInstructions()) {
			let instructionRange = instruction.getInstructionRange();
			if (Util.isInsideRange(textDocumentPosition.position, instructionRange)) {
				return this.markdown.getMarkdown(instruction.getKeyword());
			}

			if (instruction instanceof Onbuild) {
				// hovering over a trigger instruction of an ONBUILD
				let range = instruction.getTriggerRange();
				if (Util.isInsideRange(textDocumentPosition.position, range)) {
					return this.markdown.getMarkdown(instruction.getTrigger());
				}
			}

			if (instruction instanceof Arg) {
				// hovering over an argument defined by ARG
				let property = instruction.getProperty();
				if (property && Util.isInsideRange(textDocumentPosition.position, property.getNameRange()) && property.getValue() !== null) {
					return {
						contents: property.getValue()
					};
				}
			}

			if (instruction instanceof Env) {
				// hovering over an argument defined by ENV
				for (let property of instruction.getProperties()) {
					if (Util.isInsideRange(textDocumentPosition.position, property.getNameRange()) && property.getValue() !== null) {
						return {
							contents: property.getValue()
						};
					}
				}
			}

			let hover = this.getFlagsHover(textDocumentPosition.position, instruction);
			if (hover !== undefined) {
				return hover;
			}
		}

		let property = DockerDefinition.findDefinition(dockerfile, textDocumentPosition.position);
		if (property && property.getValue() !== null) {
			return { contents: property.getValue() };
		}

		return null;
	}

	private getFlagsHover(position: Position, instruction: Instruction): Hover {
		switch (instruction.getKeyword()) {
			case "ADD":
				let addFlags = (instruction as ModifiableInstruction).getFlags();
				for (let flag of addFlags) {
					if (Util.isInsideRange(position, flag.getNameRange())) {
						switch (flag.getName()) {
							case "chown":
								return this.markdown.getMarkdown("ADD_FlagChown");
						}
					}
				}
				break;
			case "COPY":
				let copyFlags = (instruction as ModifiableInstruction).getFlags();
				for (let flag of copyFlags) {
					if (Util.isInsideRange(position, flag.getNameRange())) {
						switch (flag.getName()) {
							case "chown":
								return this.markdown.getMarkdown("COPY_FlagChown");
							case "from":
								return this.markdown.getMarkdown("COPY_FlagFrom");
						}
					}
				}
				break;
			case "HEALTHCHECK":
				let flags = (instruction as ModifiableInstruction).getFlags();
				for (let flag of flags) {
					if (Util.isInsideRange(position, flag.getNameRange())) {
						switch (flag.getName()) {
							case "interval":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagInterval");
							case "retries":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagRetries");
							case "start-period":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagStartPeriod");
							case "timeout":
								return this.markdown.getMarkdown("HEALTHCHECK_FlagTimeout");
						}
						return null;
					}
				}
				break;
			case "ONBUILD":
				let trigger = (instruction as Onbuild).getTriggerInstruction();
				if (trigger !== null) {
					return this.getFlagsHover(position, trigger);
				}
				break;
		}
		return undefined;
	}
}

{'fraction_non_alphanumeric': 0.14837755385042065, 'fraction_numerical': 0.00036978829620042526, 'mean_word_length': 3.062335711603455, 'pattern_counts': {'":': 22, '<': 5, '<?xml version=': 0, '>': 6, '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': '3555655', 'n_tokens_mistral': 3783, 'n_tokens_neox': 2838, 'n_words': 709}