diff --git a/docs/codacy-rules-ai.yaml b/docs/codacy-rules-ai.yaml index cccebf7..d58dc0b 100644 --- a/docs/codacy-rules-ai.yaml +++ b/docs/codacy-rules-ai.yaml @@ -12,7 +12,7 @@ rules: $CLIENT.GenerateContentAsync(model: "$MODEL", ...) - metavariable-regex: metavariable: $MODEL - regex: "" + regex: metadata: category: security subcategory: ai @@ -20,5 +20,5 @@ rules: technology: - csharp impact: MEDIUM - confidence: MEDIUM + confidence: LOW likelihood: MEDIUM \ No newline at end of file diff --git a/docs/codacy-rules-i18n.yaml b/docs/codacy-rules-i18n.yaml index 60d30d6..cba4477 100644 --- a/docs/codacy-rules-i18n.yaml +++ b/docs/codacy-rules-i18n.yaml @@ -38,6 +38,90 @@ rules: technology: - java impact: MEDIUM - confidence: HIGH + confidence: LOW likelihood: HIGH + + - id: codacy.js.i18n.no-hardcoded-alert-concat + severity: WARNING + languages: + - js + - ts + pattern-either: + # Direct hardcoded alert strings + - pattern: alert("...") + - pattern: window.alert("...") + # String concatenation in alerts + - pattern: alert("..." + ...) + - pattern: alert(... + "...") + - pattern: window.alert("..." + ...) + - pattern: window.alert(... + "...") + pattern-not: alert(t(...)) + message: >- + Avoid hardcoded or concatenated strings in alerts. Use an i18n translation function (e.g., t("key")) with interpolation. + metadata: + category: codestyle + subcategory: i18n + description: Flags hardcoded and concatenated strings in alert dialogs to enforce localization + technology: + - javascript + - typescript + impact: MEDIUM + confidence: LOW + likelihood: HIGH + + - id: codacy.js.i18n.no-hardcoded-locale-date + severity: WARNING + languages: + - js + - ts + pattern-regex: "\\.(toLocale(Date|Time)?String)\\(\"[^\"]+\"" + message: Avoid hardcoded locale strings in date/time formatting. + metadata: + category: codestyle + subcategory: i18n + description: Flags explicit locale strings in date/time formatting which can break localization + technology: + - javascript + - typescript + impact: MEDIUM + confidence: LOW + likelihood: HIGH + + - id: codacy.js.i18n.no-hardcoded-number-format + severity: WARNING + languages: + - js + - ts + pattern-regex: "\\.toFixed\\([^)]*\\)" + message: >- + Avoid using toFixed for user-visible number formatting. Use locale-aware formatting or translation helpers. + metadata: + category: codestyle + subcategory: i18n + description: Flags toFixed used for UI number formatting; recommends locale-aware alternatives + technology: + - javascript + - typescript + impact: MEDIUM + confidence: LOW + likelihood: HIGH + + - id: codacy.js.i18n.no-raw-jsx-text + severity: WARNING + languages: + - js + - ts + pattern-regex: "<(h1|h2|h3|h4|h5|h6|p|span|div|td|th)[^>]*>[^<{]*[A-Za-z][^<{]*" + message: >- + Avoid raw text in JSX for user-facing content. Use i18n translation functions (e.g., t("key")) with interpolation. + metadata: + category: codestyle + subcategory: i18n + description: Flags raw text nodes in JSX elements to enforce localization of UI strings + technology: + - javascript + - typescript + impact: MEDIUM + confidence: LOW + likelihood: MEDIUM \ No newline at end of file diff --git a/docs/multiple-tests/ai/patterns.xml b/docs/multiple-tests/ai/patterns.xml index 6821449..e87962a 100644 --- a/docs/multiple-tests/ai/patterns.xml +++ b/docs/multiple-tests/ai/patterns.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/docs/multiple-tests/ai/results.xml b/docs/multiple-tests/ai/results.xml index bd884b1..cf09e18 100644 --- a/docs/multiple-tests/ai/results.xml +++ b/docs/multiple-tests/ai/results.xml @@ -2,7 +2,7 @@ diff --git a/docs/multiple-tests/ai/src/cs/GeminiExample.cs b/docs/multiple-tests/ai/src/cs/GeminiExample.cs index e6324f3..b487990 100644 --- a/docs/multiple-tests/ai/src/cs/GeminiExample.cs +++ b/docs/multiple-tests/ai/src/cs/GeminiExample.cs @@ -7,6 +7,9 @@ public static async Task main() { // The client gets the API key from the environment variable `GEMINI_API_KEY`. var client = new Client(); var response = await client.Models.GenerateContentAsync( + model: "deepseek-v3.2", contents: "Explain how AI works in a few words" + ); + var response2 = await client.Models.GenerateContentAsync( model: "gemini-2.5-flash", contents: "Explain how AI works in a few words" ); Console.WriteLine(response.Candidates[0].Content.Parts[0].Text); diff --git a/docs/multiple-tests/i18n/patterns.xml b/docs/multiple-tests/i18n/patterns.xml index 3b9847d..823ff8c 100644 --- a/docs/multiple-tests/i18n/patterns.xml +++ b/docs/multiple-tests/i18n/patterns.xml @@ -1,4 +1,7 @@ + + + \ No newline at end of file diff --git a/docs/multiple-tests/i18n/results.xml b/docs/multiple-tests/i18n/results.xml index 800463d..a1bdcb0 100644 --- a/docs/multiple-tests/i18n/results.xml +++ b/docs/multiple-tests/i18n/results.xml @@ -29,5 +29,21 @@ message="Use localized messages instead of hardcoded strings." severity="warning" /> + + + + + + + + \ No newline at end of file diff --git a/internal/tool/configuration.go b/internal/tool/configuration.go index 2730760..8bb2346 100644 --- a/internal/tool/configuration.go +++ b/internal/tool/configuration.go @@ -167,9 +167,9 @@ func replaceParameterPlaceholders(line string, pattern *codacy.Pattern) string { paramName := matches[1] // Convert UPPER_CASE to camelCase to match parameter name format formattedParamName := formatParameterName(paramName) - // Find the parameter in the pattern for _, param := range pattern.Parameters { + if param.Name == formattedParamName { // Use Value if set, otherwise use Default value := param.Value @@ -177,7 +177,13 @@ func replaceParameterPlaceholders(line string, pattern *codacy.Pattern) string { value = param.Default } if value != nil { - return fmt.Sprintf("%v", value) + valueStr := fmt.Sprintf("%v", value) + + // If parameter name ends with _ALLOW_LIST, convert comma-separated list to regex pattern + if strings.HasSuffix(paramName, "_ALLOW_LIST") { + return convertListToRegex(valueStr, false) + } + return valueStr } } } @@ -189,6 +195,27 @@ func replaceParameterPlaceholders(line string, pattern *codacy.Pattern) string { return result } +// convertListToRegex converts a comma-separated list into a regex alternation pattern +// Example: "gemini-2.5-flash,gpt-3.5-turbo,old-llama-model" -> "^(gemini-2\\.5-flash|gpt-3\\.5-turbo|old-llama-model)$" +func convertListToRegex(list string, include bool) string { + // Split by comma and trim spaces + items := strings.Split(list, ",") + for i, item := range items { + // Trim whitespace + item = strings.TrimSpace(item) + // Escape dots for regex + item = strings.ReplaceAll(item, ".", "\\.") + items[i] = item + } + + // Join with pipe separator and wrap in regex anchors + if include { + return fmt.Sprintf("^(%s)$", strings.Join(items, "|")) + } + + return fmt.Sprintf("^(?!(%s)$).*", strings.Join(items, "|")) +} + // formatParameterName converts UPPER_CASE to camelCase func formatParameterName(name string) string { parts := strings.Split(strings.ToLower(name), "_")