<commit_before>package plugin

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"

	plugin "github.com/hashicorp/go-plugin"
	"github.com/mitchellh/go-homedir"
	tfplugin "github.com/terraform-linters/tflint-plugin-sdk/plugin"
	"github.com/terraform-linters/tflint/tflint"
)

// Discovery searches plugins according the passed configuration
// The search priority of plugins is as follows:
//
//   1. Current directory (./.tflint.d/plugins)
//   2. Home directory (~/.tflint.d/plugins)
//
// Files under these directories that satisfy the "tflint-ruleset-*" naming rules
// enabled in the configuration are treated as plugins.
func Discovery(config *tflint.Config) (*Plugin, error) {
	if _, err := os.Stat(localPluginRoot); !os.IsNotExist(err) {
		return findPlugins(config, localPluginRoot)
	}

	pluginDir, err := homedir.Expand(PluginRoot)
	if err != nil {
		return nil, err
	}
	return findPlugins(config, pluginDir)
}

func findPlugins(config *tflint.Config, dir string) (*Plugin, error) {
	clients := []*plugin.Client{}
	rulesets := []*tfplugin.Client{}

	for _, cfg := range config.Plugins {
		pluginPath := filepath.Join(dir, pluginFileName(cfg.Name))
		if _, err := os.Stat(pluginPath); os.IsNotExist(err) {
			return nil, fmt.Errorf("Plugin `%s` not found in %s", cfg.Name, dir)
		}

		if cfg.Enabled {
			log.Printf("[INFO] Plugin `%s` found", cfg.Name)

			client := tfplugin.NewClient(&tfplugin.ClientOpts{
				Cmd: exec.Command(pluginPath),
			})
			rpcClient, err := client.Client()
			if err != nil {
				return nil, err
			}
			raw, err := rpcClient.Dispense("ruleset")
			if err != nil {
				return nil, err
			}
			ruleset := raw.(*tfplugin.Client)

			clients = append(clients, client)
			rulesets = append(rulesets, ruleset)
		} else {
			log.Printf("[INFO] Plugin `%s` found, but the plugin is disabled", cfg.Name)
		}
	}

	return &Plugin{RuleSets: rulesets, clients: clients}, nil
}

func pluginFileName(name string) string {
	if runtime.GOOS == "windows" {
		return fmt.Sprintf("tflint-ruleset-%s.exe", name)
	}
	return fmt.Sprintf("tflint-ruleset-%s", name)
}<commit_msg>Allow no extensions on windows<commit_after>package plugin

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"

	plugin "github.com/hashicorp/go-plugin"
	"github.com/mitchellh/go-homedir"
	tfplugin "github.com/terraform-linters/tflint-plugin-sdk/plugin"
	"github.com/terraform-linters/tflint/tflint"
)

// Discovery searches plugins according the passed configuration
// The search priority of plugins is as follows:
//
//   1. Current directory (./.tflint.d/plugins)
//   2. Home directory (~/.tflint.d/plugins)
//
// Files under these directories that satisfy the "tflint-ruleset-*" naming rules
// enabled in the configuration are treated as plugins.
func Discovery(config *tflint.Config) (*Plugin, error) {
	if _, err := os.Stat(localPluginRoot); !os.IsNotExist(err) {
		return findPlugins(config, localPluginRoot)
	}

	pluginDir, err := homedir.Expand(PluginRoot)
	if err != nil {
		return nil, err
	}
	return findPlugins(config, pluginDir)
}

func findPlugins(config *tflint.Config, dir string) (*Plugin, error) {
	clients := []*plugin.Client{}
	rulesets := []*tfplugin.Client{}

	for _, cfg := range config.Plugins {
		pluginPath, err := getPluginPath(dir, cfg.Name)
		if os.IsNotExist(err) {
			return nil, fmt.Errorf("Plugin `%s` not found in %s", cfg.Name, dir)
		}

		if cfg.Enabled {
			log.Printf("[INFO] Plugin `%s` found", cfg.Name)

			client := tfplugin.NewClient(&tfplugin.ClientOpts{
				Cmd: exec.Command(pluginPath),
			})
			rpcClient, err := client.Client()
			if err != nil {
				return nil, err
			}
			raw, err := rpcClient.Dispense("ruleset")
			if err != nil {
				return nil, err
			}
			ruleset := raw.(*tfplugin.Client)

			clients = append(clients, client)
			rulesets = append(rulesets, ruleset)
		} else {
			log.Printf("[INFO] Plugin `%s` found, but the plugin is disabled", cfg.Name)
		}
	}

	return &Plugin{RuleSets: rulesets, clients: clients}, nil
}

func getPluginPath(dir string, name string) (string, error) {
	pluginPath := filepath.Join(dir, fmt.Sprintf("tflint-ruleset-%s", name))

	_, err := os.Stat(pluginPath)
	if os.IsNotExist(err) && runtime.GOOS != "windows" {
		return "", os.ErrNotExist
	} else if !os.IsNotExist(err) {
		return pluginPath, nil
	}

	if _, err := os.Stat(pluginPath + ".exe"); !os.IsNotExist(err) {
		return pluginPath + ".exe", nil
	}

	return "", os.ErrNotExist
}
{'fraction_non_alphanumeric': 0.1491031390134529, 'fraction_numerical': 0.0008968609865470852, 'mean_word_length': 3.875409836065574, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '7348940', 'n_tokens_mistral': 1689, 'n_tokens_neox': 1571, 'n_words': 384}