package fr.adrienbrault.idea.symfony2plugin.intentions.yaml;

import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.util.SymfonyUtil;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLTokenTypes;

/**
 * @author Daniel Espendiller <daniel@espendiller.net>
 */
public class YamlQuotedEscapedInspection extends LocalInspectionTool {

    @NotNull
    public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, boolean isOnTheFly) {

        if(!Symfony2ProjectComponent.isEnabled(holder.getProject())) {
            return super.buildVisitor(holder, isOnTheFly);
        }

        return new PsiElementVisitor() {
            @Override
            public void visitElement(PsiElement element) {
                if(element.getNode().getElementType() == YAMLTokenTypes.SCALAR_DSTRING && SymfonyUtil.isVersionGreaterThenEquals(element.getProject(), "2.8")) {
                    // "Foo\Foo" -> "Foo\\Foo"
                    String text = StringUtils.strip(element.getText(), "\"");

                    // dont check to long strings
                    // ascii chars that need to be escape; some @see Symfony\Component\Yaml\Unescaper
                    if(text.length() < 255 && text.matches(".*[^\\\\]\\\\[^\\\\0abtnvfre \"/N_LPxuU].*")) {
                        holder.registerProblem(element, "Not escaping a backslash in a double-quoted string is deprecated", ProblemHighlightType.WEAK_WARNING);
                    }
                } else if (element.getNode().getElementType() == YAMLTokenTypes.TEXT && SymfonyUtil.isVersionGreaterThenEquals(element.getProject(), "2.8")) {
                    // @foo -> "@foo"
                    String text = element.getText();
                    if(text.length() > 1) {
                        String startChar = text.substring(0, 1);
                        if(startChar.equals("@") || startChar.equals("`") || startChar.equals("|") || startChar.equals(">")) {
                            holder.registerProblem(element, String.format("Deprecated usage of '%s' at the beginning of unquoted string", startChar), ProblemHighlightType.WEAK_WARNING);
                        } else if(startChar.equals("%")) {
                            // deprecated in => "3.1"; but as most user will need to migrate in 2.8 let them know it already
                            holder.registerProblem(element, "Not quoting a scalar starting with the '%' indicator character is deprecated since Symfony 3.1", ProblemHighlightType.WEAK_WARNING);
                        }
                    }
                }
                super.visitElement(element);
            }
        };
    }

}

@@ -298,16 +298,57 @@
 isitor;%0A
+import com.intellij.psi.PsiErrorElement;%0A
 import f
@@ -859,16 +859,17 @@
       if
+ 
 (!Symfon
@@ -1131,16 +1131,17 @@
       if
+ 
 (element
@@ -1567,32 +1567,33 @@
               if
+ 
 (text.length() %3C
@@ -2076,29 +2076,261 @@
 text
- = element.getText();
+;%0A                    if (parentIsErrorAndHasPreviousElement(element)) %7B%0A                        text = element.getParent().getPrevSibling().getText();%0A                    %7D else %7B%0A                        text = element.getText();%0A                    %7D%0A
 %0A   
@@ -2348,16 +2348,17 @@
       if
+ 
 (text.le
@@ -2367,16 +2367,87 @@
 th() %3E 1
+ %7C%7C (parentIsErrorAndHasPreviousElement(element) && text.length() %3E= 1)
 ) %7B%0A    
@@ -2533,16 +2533,17 @@
       if
+ 
 (startCh
@@ -2854,16 +2854,17 @@
  else if
+ 
 (startCh
@@ -3343,10 +3343,237 @@
 %0A    %7D%0A%0A
+    private boolean parentIsErrorAndHasPreviousElement(@NotNull PsiElement element) %7B%0A        PsiElement parent = element.getParent();%0A%0A        return parent instanceof PsiErrorElement && parent.getPrevSibling() != null;%0A    %7D%0A
 %7D%0A

Fix Yaml Inspection for deprecated structure