<commit_before>package de.endrullis.idea.postfixtemplates.language;

import com.intellij.ide.DataManager;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightVirtualFile;
import de.endrullis.idea.postfixtemplates.language.psi.CptFile;
import de.endrullis.idea.postfixtemplates.language.psi.CptMapping;
import de.endrullis.idea.postfixtemplates.language.psi.CptTemplate;
import de.endrullis.idea.postfixtemplates.languages.SupportedLanguages;
import de.endrullis.idea.postfixtemplates.settings.*;
import de.endrullis.idea.postfixtemplates.utils.Tuple2;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static de.endrullis.idea.postfixtemplates.utils.CollectionUtils._List;
import static de.endrullis.idea.postfixtemplates.utils.StringUtils.replace;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

@SuppressWarnings("WeakerAccess")
public class CptUtil {
	public static final String PLUGIN_ID = "de.endrullis.idea.postfixtemplates";

	private static String templatesPathString = null;

	public static Project findProject(PsiElement element) {
		PsiFile containingFile = element.getContainingFile();
		if (containingFile == null) {
			if (!element.isValid()) {
				return null;
			}
		} else if (!containingFile.isValid()) {
			return null;
		}

		return (containingFile == null ? element : containingFile).getProject();
	}

	public static List<CptMapping> findMappings(Project project, String key) {
		List<CptMapping> result = null;

		val virtualFiles = FileTypeIndex.getFiles(CptFileType.INSTANCE, GlobalSearchScope.allScope(project));

		/*
		Collection<VirtualFile> virtualFiles =
			FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, CptFileType.INSTANCE,
				GlobalSearchScope.allScope(project));
		*/

		for (VirtualFile virtualFile : virtualFiles) {
			CptFile cptFile = (CptFile) PsiManager.getInstance(project).findFile(virtualFile);

			if (cptFile != null) {
				CptMapping[] mappings = PsiTreeUtil.getChildrenOfType(cptFile, CptMapping.class);
				if (mappings != null) {
					for (CptMapping mapping : mappings) {
						if (key.equals(mapping.getMatchingClassName())) {
							if (result == null) {
								result = new ArrayList<>();
							}
							result.add(mapping);
						}
					}
				}
			}
		}
		return result != null ? result : Collections.emptyList();
	}

	public static List<CptMapping> findMappings(Project project) {
		List<CptMapping> result = new ArrayList<>();

		val virtualFiles = FileTypeIndex.getFiles(CptFileType.INSTANCE, GlobalSearchScope.allScope(project));

		/*
		Collection<VirtualFile> virtualFiles =
			FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, CptFileType.INSTANCE,
				GlobalSearchScope.allScope(project));
		*/

		for (VirtualFile virtualFile : virtualFiles) {
			CptFile cptFile = (CptFile) PsiManager.getInstance(project).findFile(virtualFile);
			if (cptFile != null) {
				CptMapping[] mappings = PsiTreeUtil.getChildrenOfType(cptFile, CptMapping.class);
				if (mappings != null) {
					Collections.addAll(result, mappings);
				}
			}
		}
		return result;
	}

	/**
	 * Returns the predefined plugin templates for the given language.
	 *
	 * @param language programming language
	 * @return predefined plugin templates for the given language
	 */
	public static String getDefaultTemplates(String language) {
		InputStream stream = CptUtil.class.getResourceAsStream("defaulttemplates/" + language + ".postfixTemplates");
		return getContent(stream);
	}

	/**
	 * Returns the content of the given file.
	 *
	 * @param file file
	 * @return content of the given file
	 * @throws FileNotFoundException
	 */
	public static String getContent(@NotNull File file) throws FileNotFoundException {
		return getContent(new FileInputStream(file));
	}

	/**
	 * Returns the content of the given input stream.
	 *
	 * @param stream input stream
	 * @return content of the given input stream
	 */
	private static String getContent(@NotNull InputStream stream) {
		StringBuilder sb = new StringBuilder();

		// convert system newlines into UNIX newlines, because IDEA works only with UNIX newlines
		try (BufferedReader in = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
			String line;
			while ((line = in.readLine()) != null) {
				sb.append(line).append("\n");
			}

			return sb.toString();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return "";
	}

	/**
	 * Returns the path of the CPT plugin settings directory.
	 *
	 * @return path of the CPT plugin settings directory
	 */
	public static File getPluginPath() {
		File path = PluginManager.getPlugin(PluginId.getId(CptUtil.PLUGIN_ID)).getPath();

		if (path.getName().endsWith(".jar")) {
			path = new File(path.getParentFile(), path.getName().substring(0, path.getName().length() - 4));
		}

		return path;
	}

	/**
	 * Returns the path "$CPT_PLUGIN_SETTINGS/templates".
	 *
	 * @return path "$CPT_PLUGIN_SETTINGS/templates"
	 */
	public static File getTemplatesPath() {
		return new File(getPluginPath(), "templates");
	}

	public static String getTemplatesPathString() {
		if (templatesPathString != null) {
			templatesPathString = getTemplatesPath().getAbsolutePath().replace('\\', '/');
		}

		return templatesPathString;
	}

	public static void createTemplateFile(@NotNull String language, @NotNull String filename, @NotNull String content) {
		File file = new File(CptUtil.getTemplatesPath() + "/" + language, filename + ".postfixTemplates");

		if (file.exists()) return;

		//noinspection ResultOfMethodCallIgnored
		file.getParentFile().mkdirs();

		try (PrintStream out = new PrintStream(file, "UTF-8")) {
			out.println(content);
		} catch (FileNotFoundException e) {
			throw new RuntimeException(language + " template file could not copied to " + file.getAbsolutePath(), e);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("UTF-8 not supported", e);
		}
	}

	public static void moveOldTemplateFile(@NotNull String language) {<commit_msg>fixed FileNotFoundException<commit_after>package de.endrullis.idea.postfixtemplates.language;

import com.intellij.ide.DataManager;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightVirtualFile;
import de.endrullis.idea.postfixtemplates.language.psi.CptFile;
import de.endrullis.idea.postfixtemplates.language.psi.CptMapping;
import de.endrullis.idea.postfixtemplates.language.psi.CptTemplate;
import de.endrullis.idea.postfixtemplates.languages.SupportedLanguages;
import de.endrullis.idea.postfixtemplates.settings.*;
import de.endrullis.idea.postfixtemplates.utils.Tuple2;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static de.endrullis.idea.postfixtemplates.utils.CollectionUtils._List;
import static de.endrullis.idea.postfixtemplates.utils.StringUtils.replace;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

@SuppressWarnings("WeakerAccess")
public class CptUtil {
	public static final String PLUGIN_ID = "de.endrullis.idea.postfixtemplates";

	private static String templatesPathString = null;

	public static Project findProject(PsiElement element) {
		PsiFile containingFile = element.getContainingFile();
		if (containingFile == null) {
			if (!element.isValid()) {
				return null;
			}
		} else if (!containingFile.isValid()) {
			return null;
		}

		return (containingFile == null ? element : containingFile).getProject();
	}

	public static List<CptMapping> findMappings(Project project, String key) {
		List<CptMapping> result = null;

		val virtualFiles = FileTypeIndex.getFiles(CptFileType.INSTANCE, GlobalSearchScope.allScope(project));

		/*
		Collection<VirtualFile> virtualFiles =
			FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, CptFileType.INSTANCE,
				GlobalSearchScope.allScope(project));
		*/

		for (VirtualFile virtualFile : virtualFiles) {
			CptFile cptFile = (CptFile) PsiManager.getInstance(project).findFile(virtualFile);

			if (cptFile != null) {
				CptMapping[] mappings = PsiTreeUtil.getChildrenOfType(cptFile, CptMapping.class);
				if (mappings != null) {
					for (CptMapping mapping : mappings) {
						if (key.equals(mapping.getMatchingClassName())) {
							if (result == null) {
								result = new ArrayList<>();
							}
							result.add(mapping);
						}
					}
				}
			}
		}
		return result != null ? result : Collections.emptyList();
	}

	public static List<CptMapping> findMappings(Project project) {
		List<CptMapping> result = new ArrayList<>();

		val virtualFiles = FileTypeIndex.getFiles(CptFileType.INSTANCE, GlobalSearchScope.allScope(project));

		/*
		Collection<VirtualFile> virtualFiles =
			FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, CptFileType.INSTANCE,
				GlobalSearchScope.allScope(project));
		*/

		for (VirtualFile virtualFile : virtualFiles) {
			CptFile cptFile = (CptFile) PsiManager.getInstance(project).findFile(virtualFile);
			if (cptFile != null) {
				CptMapping[] mappings = PsiTreeUtil.getChildrenOfType(cptFile, CptMapping.class);
				if (mappings != null) {
					Collections.addAll(result, mappings);
				}
			}
		}
		return result;
	}

	/**
	 * Returns the predefined plugin templates for the given language.
	 *
	 * @param language programming language
	 * @return predefined plugin templates for the given language
	 */
	public static String getDefaultTemplates(String language) {
		InputStream stream = CptUtil.class.getResourceAsStream("defaulttemplates/" + language + ".postfixTemplates");
		return getContent(stream);
	}

	/**
	 * Returns the content of the given file.
	 *
	 * @param file file
	 * @return content of the given file
	 * @throws FileNotFoundException
	 */
	public static String getContent(@NotNull File file) throws FileNotFoundException {
		return getContent(new FileInputStream(file));
	}

	/**
	 * Returns the content of the given input stream.
	 *
	 * @param stream input stream
	 * @return content of the given input stream
	 */
	private static String getContent(@NotNull InputStream stream) {
		StringBuilder sb = new StringBuilder();

		// convert system newlines into UNIX newlines, because IDEA works only with UNIX newlines
		try (BufferedReader in = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
			String line;
			while ((line = in.readLine()) != null) {
				sb.append(line).append("\n");
			}

			return sb.toString();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return "";
	}

	/**
	 * Returns the path of the CPT plugin settings directory.
	 *
	 * @return path of the CPT plugin settings directory
	 */
	public static File getPluginPath() {
		File path = PluginManager.getPlugin(PluginId.getId(CptUtil.PLUGIN_ID)).getPath();

		if (path.getName().endsWith(".jar")) {
			path = new File(path.getParentFile(), path.getName().substring(0, path.getName().length() - 4));
		}

		return path;
	}

	/**
	 * Returns the path "$CPT_PLUGIN_SETTINGS/templates".
	 *
	 * @return path "$CPT_PLUGIN_SETTINGS/templates"
	 */
	public static File getTemplatesPath() {
		final File templates = new File(getPluginPath(), "templates");
		templates.mkdirs();

		return templates;
	}

	public static String getTemplatesPathString() {
		if (templatesPathString != null) {
			templatesPathString = getTemplatesPath().getAbsolutePath().replace('\\', '/');
		}

		return templatesPathString;
	}

	public static void createTemplateFile(@NotNull String language, @NotNull String filename, @NotNull String content) {
		File file = new File(CptUtil.getTemplatesPath() + "/" + language, filename + ".postfixTemplates");

		if (file.exists()) return;

		//noinspection ResultOfMethodCallIgnored
		file.getParentFile().mkdirs();

		try (PrintStream out = new PrintStream(file, "UTF-8")) {
			out.println(content);
		} catch (FileNotFoundException e) {
			throw new RuntimeException(language + " template file could not copied to " + file.getAbsolutePath(), e);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("UTF-8 not supported", e);
		}
	}

	public static void moveOldTemplateFile(@NotNull String language) {
{'fraction_non_alphanumeric': 0.11290437255599005, 'fraction_numerical': 0.0008531816565943832, 'mean_word_length': 4.745915032679738, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, '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': '1461153', 'n_tokens_mistral': 4643, 'n_tokens_neox': 4200, 'n_words': 930}