Merge branch 'skip_json_injection_for_PY_15074'

This commit is contained in:
Ilya.Kazakevich
2015-04-28 01:27:58 +03:00
5 changed files with 150 additions and 5 deletions
@@ -21,6 +21,11 @@
<extensionPoints>
<!-- EP to block language injection into script tag-->
<extensionPoint name="html.htmlScriptInjectionBlocker" beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.psi.impl.source.html.HtmlScriptInjectionBlocker"/>
</extensionPoint>
<extensionPoint name="xml.startTagEndToken"
interface="com.intellij.psi.xml.StartTagEndTokenProvider"/>
<extensionPoint name="xml.schemaProvider"
@@ -30,16 +30,19 @@ import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.impl.FilePropertyPusher;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.DirectoryProjectConfigurator;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.testFramework.LightProjectDescriptor;
@@ -55,6 +58,7 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.usages.Usage;
import com.intellij.usages.rules.PsiElementUsage;
import com.intellij.util.CommonProcessors.CollectProcessor;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.psi.LanguageLevel;
@@ -94,6 +98,24 @@ public abstract class PyTestCase extends UsefulTestCase {
return null;
}
/**
* Reformats currently configured file.
*/
protected final void reformatFile() {
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
doPerformFormatting();
}
});
}
private void doPerformFormatting() throws IncorrectOperationException {
final PsiFile file = myFixture.getFile();
final TextRange myTextRange = file.getTextRange();
CodeStyleManager.getInstance(myFixture.getProject()).reformatText(file, myTextRange.getStartOffset(), myTextRange.getEndOffset());
}
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.html;
import com.intellij.lang.Language;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
/**
* Interface to be implemented by extension point that wants to prevent some language from injection into script HTML tag
*
* @author Ilya.Kazakevich
*/
public interface HtmlScriptInjectionBlocker {
/**
* @param scriptTag &lt;script&gt; tag
* @param language language that should be injected according to <pre>type</pre> attribute
* @return true if language <strong>should not</strong> be injected
*/
boolean isLanguageInjectionDenied(@NotNull XmlTag scriptTag, @NotNull Language language);
}
@@ -0,0 +1,62 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.html;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageExtension;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* Language extension to block script injection into HTML tag &lt;script&gt; when this language exists on file's
* {@link com.intellij.psi.FileViewProvider}.
*
* @author Ilya.Kazakevich
*/
public final class HtmlScriptInjectionBlockerExtension extends LanguageExtension<HtmlScriptInjectionBlocker> {
private static final HtmlScriptInjectionBlockerExtension INSTANCE = new HtmlScriptInjectionBlockerExtension();
private HtmlScriptInjectionBlockerExtension() {
super("com.intellij.html.htmlScriptInjectionBlocker");
}
/**
* Checks if language injection to this tag is explicitly denied by one or more @link HtmlScriptInjectionBlocker extension points}
*
* @param xmlTag &lt;script&gt; tag
* @param language lang user wants to inject (probably obtained via {@link HtmlScriptLanguageInjector}
* @return true if injection denied by extension point
*/
public static boolean isInjectionBlocked(@NotNull XmlTag xmlTag, @NotNull Language language) {
Collection<Language> allFileLanguages = xmlTag.getContainingFile().getViewProvider().getLanguages();
for (Language fileLanguage : allFileLanguages) {
for (HtmlScriptInjectionBlocker blocker : INSTANCE.allForLanguage(fileLanguage)) {
if (blocker.isLanguageInjectionDenied(xmlTag, language)) {
// Language exists, but denied by EP
return true;
}
}
}
// Language exists and not denied
return false;
}
}
@@ -17,7 +17,6 @@ package com.intellij.psi.impl.source.html;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.util.TextRange;
@@ -27,24 +26,47 @@ import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlText;
import com.intellij.xml.util.HtmlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class HtmlScriptLanguageInjector implements MultiHostInjector {
/**
* Finds language to be injected into &lt;script&gt; tag
*
* @param xmlTag &lt;script&gt; tag
* @return language to inject or null if no language found or not a script tag at all
*/
@Nullable
public static Language getScriptLanguageToInject(@NotNull XmlTag xmlTag) {
if (!HtmlUtil.isScriptTag(xmlTag)) {
return null;
}
String mimeType = xmlTag.getAttributeValue("type");
Collection<Language> languages = Language.findInstancesByMimeType(mimeType);
return !languages.isEmpty() ? languages.iterator().next() : Language.ANY;
}
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement host) {
if (!host.isValid() || !(host instanceof XmlText) || !HtmlUtil.isHtmlTagContainingFile(host)) {
return;
}
XmlTag scriptTag = ((XmlText)host).getParentTag();
if (scriptTag == null || !HtmlUtil.isScriptTag(scriptTag)) {
if (scriptTag == null) {
return;
}
String mimeType = scriptTag.getAttributeValue("type");
Collection<Language> languages = Language.findInstancesByMimeType(mimeType);
Language language = !languages.isEmpty() ? languages.iterator().next() : Language.ANY;
final Language language = getScriptLanguageToInject(scriptTag);
if (language == null || HtmlScriptInjectionBlockerExtension.isInjectionBlocked(scriptTag, language)) {
return;
}
if (LanguageUtil.isInjectableLanguage(language)) {
registrar
.startInjecting(language)