Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2013-08-07 13:07:16 +04:00
131 changed files with 3898 additions and 853 deletions
@@ -26,7 +26,7 @@ public interface CompilationStatusListener extends EventListener {
/**
* Invoked in a Swing dispatch thread after the compilation is finished.
*
* @param aborted true if compilatioin has been cancelled
* @param aborted true if compilation has been cancelled
* @param errors error count
* @param warnings warning count
* @param compileContext context for the finished compilation
@@ -99,7 +99,7 @@ public class ModuleConfigurable extends ProjectStructureElementConfigurable<Modu
@Override
public Icon getIcon(final boolean open) {
return ModuleType.get(myModule).getIcon();
return myModule.isDisposed() ? null : ModuleType.get(myModule).getIcon();
}
public Module getModule() {
@@ -18,15 +18,13 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.scope.CompletionElement;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.editorActions.wordSelection.DocTagSelectioner;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
@@ -171,13 +169,16 @@ public class JavaDocCompletionContributor extends CompletionContributor {
result.addElement(LookupElementBuilder.create(description).withInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
if (context.getCompletionChar() != Lookup.REPLACE_SELECT_CHAR) return;
context.commitDocument();
PsiDocTag docTag = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiDocTag.class, false);
if (docTag != null) {
int tagEnd = docTag.getTextRange().getEndOffset();
Document document = context.getDocument();
int tagEnd = DocTagSelectioner.getDocTagRange(docTag, document.getCharsSequence(), 0).getEndOffset();
int tail = context.getTailOffset();
if (tail < tagEnd) {
context.getDocument().deleteString(tail, tagEnd);
document.deleteString(tail, tagEnd);
}
}
}
@@ -36,7 +36,11 @@ public class DocTagSelectioner extends WordSelectioner {
@Override
public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
result.add(getDocTagRange((PsiDocTag)e, editorText, cursorOffset));
return result;
}
public static TextRange getDocTagRange(PsiDocTag e, CharSequence documentText, int minOffset) {
TextRange range = e.getTextRange();
int endOffset = range.getEndOffset();
@@ -49,7 +53,7 @@ public class DocTagSelectioner extends WordSelectioner {
int childStartOffset = child.getTextRange().getStartOffset();
if (childStartOffset <= cursorOffset) {
if (childStartOffset <= minOffset) {
break;
}
@@ -71,10 +75,8 @@ public class DocTagSelectioner extends WordSelectioner {
endOffset = Math.min(childStartOffset, endOffset);
}
startOffset = CharArrayUtil.shiftBackward(editorText, startOffset - 1, "* \t") + 1;
startOffset = CharArrayUtil.shiftBackward(documentText, startOffset - 1, "* \t") + 1;
result.add(new TextRange(startOffset, endOffset));
return result;
return new TextRange(startOffset, endOffset);
}
}
@@ -1,45 +0,0 @@
/*
* Copyright 2000-2009 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.lang.java;
import com.intellij.lang.LiteralEscaper;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaToken;
import com.intellij.psi.JavaTokenType;
import com.intellij.openapi.util.text.StringUtil;
/**
* @author yole
*/
public class JavaLiteralEscaper implements LiteralEscaper {
@Override
public String getEscapedText(final PsiElement context, final String originalText) {
if (context instanceof PsiJavaToken && ((PsiJavaToken)context).getTokenType() == JavaTokenType.STRING_LITERAL) {
return StringUtil.escapeStringCharacters(originalText);
}
return originalText;
}
@Override
public String escapeText(String originalText) {
return StringUtil.escapeStringCharacters(originalText);
}
@Override
public String unescapeText(String originalText) {
return StringUtil.unescapeStringCharacters(originalText);
}
}
@@ -120,7 +120,7 @@ public class GenericsUtil {
PsiType mapping2 = subst2.substitute(parameter);
if (mapping1 != null && mapping2 != null) {
substitutor = substitutor.put(parameter, getLeastContainingTypeArgument(mapping1, mapping2, compared, manager));
substitutor = substitutor.put(parameter, getLeastContainingTypeArgument(mapping1, mapping2, compared, manager, type1.equals(mapping1) && type2.equals(mapping2) ? aSuper : null, parameter));
}
else {
substitutor = substitutor.put(parameter, null);
@@ -150,9 +150,23 @@ public class GenericsUtil {
private static PsiType getLeastContainingTypeArgument(PsiType type1,
PsiType type2,
Set<Pair<PsiType, PsiType>> compared,
PsiManager manager) {
PsiManager manager,
PsiClass nestedLayer,
PsiTypeParameter parameter) {
Pair<PsiType, PsiType> types = new Pair<PsiType, PsiType>(type1, type2);
if (compared.contains(types)) return PsiWildcardType.createUnbounded(manager);
if (compared.contains(types)) {
if (nestedLayer != null) {
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
for (PsiTypeParameter param : PsiUtil.typeParametersIterable(nestedLayer)) {
subst = subst.put(param, PsiWildcardType.createUnbounded(manager));
}
subst = subst.put(parameter, getLeastContainingTypeArgument(type1, type2, compared, manager, null, null));
final PsiClassType boundType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(nestedLayer, subst);
return PsiWildcardType.createExtends(manager, boundType);
}
return PsiWildcardType.createUnbounded(manager);
}
compared.add(types);
try {
@@ -180,7 +194,7 @@ public class GenericsUtil {
}
}
else if (type2 instanceof PsiWildcardType) {
return getLeastContainingTypeArgument(type2, type1, compared, manager);
return getLeastContainingTypeArgument(type2, type1, compared, manager, null, null);
}
//Done with wildcards
@@ -87,7 +87,12 @@ public class LambdaHighlightingUtil {
@Nullable
public static String checkInterfaceFunctional(PsiType functionalInterfaceType) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
if (functionalInterfaceType instanceof PsiIntersectionType) {
for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) {
if (checkInterfaceFunctional(type) == null) return null;
}
}
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(functionalInterfaceType));
final PsiClass aClass = resolveResult.getElement();
if (aClass != null) {
if (checkReturnTypeApplicable(resolveResult, aClass)) {
@@ -95,7 +100,7 @@ public class LambdaHighlightingUtil {
}
return checkInterfaceFunctional(aClass);
}
return null;
return functionalInterfaceType.getPresentableText() + " is not a functional interface";
}
private static boolean checkReturnTypeApplicable(PsiClassType.ClassResolveResult resolveResult, final PsiClass aClass) {
@@ -484,23 +484,30 @@ public class LambdaUtil {
}
}
else if (parent instanceof PsiReturnStatement) {
final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
if (method != null) {
return method.getReturnType();
final PsiLambdaExpression gParent = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class);
if (gParent != null) {
return getFunctionalInterfaceTypeByContainingLambda(gParent);
} else {
final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
if (method != null) {
return method.getReturnType();
}
}
}
else if (parent instanceof PsiLambdaExpression) {
final PsiType parentInterfaceType = ((PsiLambdaExpression)parent).getFunctionalInterfaceType();
if (parentInterfaceType != null) {
return getFunctionalInterfaceReturnType(parentInterfaceType);
}
return getFunctionalInterfaceTypeByContainingLambda((PsiLambdaExpression)parent);
}
return null;
}
private static PsiType getFunctionalInterfaceTypeByContainingLambda(@NotNull PsiLambdaExpression parentLambda) {
final PsiType parentInterfaceType = parentLambda.getFunctionalInterfaceType();
return parentInterfaceType != null ? getFunctionalInterfaceReturnType(parentInterfaceType) : null;
}
private static int adjustLambdaIdx(int lambdaIdx, PsiMethod resolve, PsiParameter[] parameters) {
final int finalLambdaIdx;
if (((PsiMethod)resolve).isVarArgs() && lambdaIdx >= parameters.length) {
if (resolve.isVarArgs() && lambdaIdx >= parameters.length) {
finalLambdaIdx = parameters.length - 1;
} else {
finalLambdaIdx = lambdaIdx;
@@ -524,7 +531,6 @@ public class LambdaUtil {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(param, PsiLambdaExpression.class);
if (lambdaExpression != null) {
final PsiParameterList parameterList = lambdaExpression.getParameterList();
PsiType type = getFunctionalInterfaceType(lambdaExpression, true, parameterIndex);
if (type == null) {
type = getFunctionalInterfaceType(lambdaExpression, false);
@@ -541,7 +541,7 @@ public class ExceptionUtil {
List<PsiClassType> result = ContainerUtil.newArrayList();
for (PsiClassType referencedType : referencedTypes) {
final PsiType type = substitutor.substitute(referencedType);
final PsiType type = GenericsUtil.eliminateWildcards(substitutor.substitute(referencedType), false);
if (!(type instanceof PsiClassType)) continue;
PsiClassType classType = (PsiClassType)type;
PsiClass exceptionClass = ((PsiClassType)type).resolve();
@@ -863,7 +863,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
PsiType patternType,
final ConstraintType constraintType,
final int depth) {
if (arg instanceof PsiCapturedWildcardType) arg = ((PsiCapturedWildcardType)arg).getWildcard(); //reopen
if (arg instanceof PsiCapturedWildcardType && (depth < 2 || constraintType != ConstraintType.EQUALS)) arg = ((PsiCapturedWildcardType)arg).getWildcard(); //reopen
if (patternType.equals(param)) {
return processArgType(arg, constraintType, depth < 2);
@@ -382,7 +382,8 @@ public class PsiLiteralExpressionImpl
@Override
@NotNull
public PsiReference[] getReferences() {
return PsiReferenceService.getService().getContributedReferences(this);
PsiReference[] references = PsiReferenceService.getService().getContributedReferences(this);
return references;
}
@Override
@@ -0,0 +1,13 @@
interface I<T extends Exception> {
void m() throws T;
}
class C {
void x(I<?> i) {
<error descr="Unhandled exception: java.lang.Exception">i.m();</error>
}
void y(I<? extends Exception> i) {
<error descr="Unhandled exception: java.lang.Exception">i.m();</error>
}
}
@@ -4,7 +4,7 @@ class A<T> {
}
void bar(A<?> x){
baz<error descr="'baz(A<A<?>>)' in 'A' cannot be applied to '(A<A<capture<?>>>)'">(x.foo())</error>;
baz<error descr="'baz(A<A<? extends S>>)' in 'A' cannot be applied to '(A<A<capture<?>>>)'">(x.foo())</error>;
}
<S> void baz(A<A<? extends S>> x){}
@@ -0,0 +1,11 @@
class A<T> {
A<A<? super A<T>>> foo(){
return null;
}
void bar(A<?> x){
baz(x.foo());
}
<S> void baz(A<A<? super A<S>>> x){}
}
@@ -0,0 +1,43 @@
class A<T> {}
class B<T> extends A<A<T>> {
void bar(B<?> b, B<? extends String> eb, B<? super String> sb, B<String> s) {
foo(b);
foo(eb);
foo(sb);
foo(s);
<error descr="Inferred type 'capture<?>' for type parameter 'T' is not within its bound; should extend 'java.lang.String'">foo1(b)</error>;
foo1(eb);
<error descr="Inferred type 'capture<? super java.lang.String>' for type parameter 'T' is not within its bound; should extend 'java.lang.String'">foo1(sb)</error>;
foo1(s);
foo2(b);
foo2(eb);
foo2(sb);
foo2(s);
foo3<error descr="'foo3(A<A<? extends T>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
foo3<error descr="'foo3(A<A<? extends T>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
foo3<error descr="'foo3(A<A<? extends T>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
foo3<error descr="'foo3(A<A<? extends java.lang.String>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
foo4<error descr="'foo4(A<A<? super T>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
foo4<error descr="'foo4(A<A<? super T>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
foo4<error descr="'foo4(A<A<? super T>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
foo4<error descr="'foo4(A<A<? super java.lang.String>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
foo5(b);
foo5(eb);
foo5(sb);
foo5(s);
}
<T> void foo(A<A<T>> x) {}
<T extends String> void foo1(A<A<T>> x) {}
<T> void foo2(A<? extends A<T>> x) {}
<T> void foo3(A<A<? extends T>> x) {}
<T> void foo4(A<A<? super T>> x) {}
<T> void foo5(A<? super A<T>> x) {}
}
@@ -8,7 +8,7 @@ class Test {
}
void foo() {
<error descr="Incompatible types. Found: 'java.util.List<java.lang.Class<? extends java.io.Serializable & java.lang.Comparable<?>>>', required: 'java.util.List<java.lang.Class<? extends java.io.Serializable>>'">List<Class<? extends Serializable>> l = <warning descr="Unchecked generics array creation for varargs parameter">this.asList</warning>(String.class, Integer.class);</error>
<error descr="Incompatible types. Found: 'java.util.List<java.lang.Class<? extends java.io.Serializable & java.lang.Comparable<? extends java.lang.Comparable<?>>>>', required: 'java.util.List<java.lang.Class<? extends java.io.Serializable>>'">List<Class<? extends Serializable>> l = <warning descr="Unchecked generics array creation for varargs parameter">this.asList</warning>(String.class, Integer.class);</error>
l.size();
List<? extends Object> objects = this.asList(new String(), new Integer(0));
objects.size();
@@ -146,7 +146,7 @@ class IDEADEV25515 {
}
public static final
<error descr="Incompatible types. Found: 'java.util.List<java.lang.Class<? extends java.io.Serializable & java.lang.Comparable<?>>>', required: 'java.util.List<java.lang.Class<? extends java.io.Serializable>>'">List<Class<? extends Serializable>> SIMPLE_TYPES =
<error descr="Incompatible types. Found: 'java.util.List<java.lang.Class<? extends java.io.Serializable & java.lang.Comparable<? extends java.lang.Comparable<?>>>>', required: 'java.util.List<java.lang.Class<? extends java.io.Serializable>>'">List<Class<? extends Serializable>> SIMPLE_TYPES =
<warning descr="Unchecked generics array creation for varargs parameter">asList</warning>(String.class, Integer.class ,Long.class, Double.class, /*Date.class,*/
Boolean.class, Boolean.TYPE /*,String[].class */ /*,BigDecimal.class*/);</error>
@@ -179,3 +179,43 @@ public class MaximalType {
class M extends MaximalType implements L{}
class M2 extends MaximalType implements L{}
/////////////
class IDEA67676 {
interface I<<warning descr="Type parameter 'T' is never used">T</warning>> {}
interface A<T> extends I<A<T>>{}
interface Com2<T, U> {
void foo(T t, U u);
}
interface Com1<T> {
void foo(T t);
}
abstract class X {
abstract <T> T foo(T x, T y);
void bar(A<A2> x, A<B2> y) {
A<? extends Com2<? extends Com2<?, ?>, ? extends Com2<?, ?>>> f = foo(x, y);
f.hashCode();
}
void boo(A<A3> x, A<B3> y) {
A<? extends Com2<? extends Com2<?, ?>, ? extends Com2<?, ?>>> f = foo(x, y);
f.hashCode();
}
void baz(A<A1> x, A<B1> y) {
A<? extends Com1<? extends Com1<?>>> f = foo(x, y);
f.hashCode();
}
}
abstract class A1 implements Com1<A1> {}
abstract class B1 implements Com1<B1> {}
abstract class A2 implements Com2<A2, A2> {}
abstract class B2 implements Com2<B2, B2> {}
abstract class A3 implements Com2<A3, B3> {}
abstract class B3 implements Com2<B3, A3> {}
}
@@ -22,6 +22,6 @@ class CastInContexts {
}
{
int i = <error descr="Inconvertible types; cannot cast '<lambda expression>' to 'int'">(int) ()-> 1</error>;
int i = (int) <error descr="int is not a functional interface">()-> 1</error>;
}
}
@@ -0,0 +1,5 @@
class Demo {
public static void main(String[] args) {
Runnable r = () -> <error descr="void is not a functional interface">() -> () -> {}</error>;
}
}
@@ -16,7 +16,7 @@ class NoInferenceResult {
void test() {
m((String s1) -> <error descr="Target type of a lambda conversion must be an interface">(String s2) -> s1 + s2</error>);
m(<error descr="Incompatible return type <lambda expression> in lambda expression">(String s1) -> {return (String s2) -> s1 + s2;}</error>);
m((String s1) -> {return <error descr="Target type of a lambda conversion must be an interface">(String s2) -> s1 + s2</error>;});
m((String s1) -> s1.length());
m((String s1) -> s1);
@@ -48,7 +48,7 @@ class Test2 {
}
{
X<?> x = <error descr="No instance of type X<?> exists so that lambda expression can be type-checked">() -> 123</error>;
X<?> x = () -> 123;
X<? extends Number> x1 = () -> 123;
}
@@ -221,6 +221,7 @@ class Foo {
class Foo {
/**
* @param intParam so<caret> xxx
* @throws Foo
*/
void foo2(int intParam, Object param2) { }
@@ -234,7 +235,20 @@ class Foo {
myFixture.assertPreferredCompletionItems 0, 'some', 'some integer param'
myFixture.lookup.currentItem = myFixture.lookupElements[1]
myFixture.type('\t')
assert !myFixture.editor.document.text.contains('xxx')
myFixture.checkResult '''
class Foo {
/**
* @param intParam some integer param<caret>
* @throws Foo
*/
void foo2(int intParam, Object param2) { }
/**
* @param intParam some integer param
*/
void foo(int intParam, Object param2) { }
}
'''
}
public void "test see super class"() {
@@ -307,6 +307,8 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA109556() { doTest5(false); }
public void testIDEA107440() { doTest5(false); }
public void testIDEA57289() { doTest5(false); }
public void testIDEA57439() { doTest5(false); }
public void testIDEA57312() { doTest5(false); }
public void testJavaUtilCollections_NoVerify() throws Exception {
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
@@ -58,4 +58,5 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase {
public void testClassObjectAccessibility() throws Exception { setLanguageLevel(LanguageLevel.JDK_1_6); doTest(false, false); }
public void testRedundantCastInConditionalExpression() throws Exception { setLanguageLevel(LanguageLevel.JDK_1_6); doTest(true, false); }
public void testJava5CastConventions() { setLanguageLevel(LanguageLevel.JDK_1_5); doTest(true, false); }
public void testUnhandledExceptions() { doTest(true, false); }
}
@@ -89,6 +89,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testConflictResolution() throws Exception {doTest();}
public void testIDEA108195() throws Exception {doTest();}
public void testDiamondInference() throws Exception { doTest();}
public void testFunctionalInterfaceCheck() throws Exception { doTest();}
private void doTest() {
doTest(false);
@@ -35,7 +35,7 @@ public class Bootstrap {
}
public static void main(String[] args, String mainClass, String methodName, List<URL> classpathElements) throws Exception {
UrlClassLoader newClassLoader = ClassloaderUtil.initClassloader(classpathElements);
UrlClassLoader newClassLoader = ClassloaderUtil.initClassloader(classpathElements, args.length == 0);
WindowsCommandLineProcessor.ourMirrorClass = Class.forName(WindowsCommandLineProcessor.class.getName(), true, newClassLoader);
Class<?> klass = Class.forName(PLUGIN_MANAGER, true, newClassLoader);
@@ -49,7 +49,7 @@ public class ClassloaderUtil extends ClassUtilCore {
return Logger.getInstance("ClassloaderUtil");
}
public static UrlClassLoader initClassloader(final List<URL> classpathElements) throws Exception {
public static UrlClassLoader initClassloader(final List<URL> classpathElements, boolean updatePlugins) throws Exception {
PathManager.loadProperties();
addParentClasspath(classpathElements);
@@ -60,7 +60,7 @@ public class ClassloaderUtil extends ClassUtilCore {
UrlClassLoader newClassLoader = new UrlClassLoader(classpathElements, null, true, true);
// prepare plugins
if (!isLoadingOfExternalPluginsDisabled()) {
if (updatePlugins && !isLoadingOfExternalPluginsDisabled()) {
try {
StartupActionScriptManager.executeActionScript();
}
@@ -59,12 +59,14 @@ public class Main {
throw new HeadlessException("Unable to detect graphics environment");
}
try {
installPatch();
}
catch (Throwable t) {
showMessage("Update Failed", t);
System.exit(UPDATE_FAILED);
if (args.length == 0) {
try {
installPatch();
}
catch (Throwable t) {
showMessage("Update Failed", t);
System.exit(UPDATE_FAILED);
}
}
}
@@ -221,4 +221,11 @@ public abstract class Language extends UserDataHolderBase {
}
return null;
}
/** Fake language identifier without registering */
protected Language(String id, @SuppressWarnings("UnusedParameters") boolean register) {
myID = id;
myBaseLanguage = null;
myMimeTypes = null;
}
}
@@ -405,11 +405,22 @@ public class ExternalSystemApiUtil {
@NotNull
public static String getProjectRepresentationName(@NotNull String targetProjectPath, @Nullable String rootProjectPath) {
if (rootProjectPath == null) {
return new File(targetProjectPath).getParentFile().getName();
File rootProjectDir = new File(targetProjectPath);
if (rootProjectDir.isFile()) {
rootProjectDir = rootProjectDir.getParentFile();
}
return rootProjectDir.getName();
}
File rootProjectDir = new File(rootProjectPath);
if (rootProjectDir.isFile()) {
rootProjectDir = rootProjectDir.getParentFile();
}
File targetProjectDir = new File(targetProjectPath);
if (targetProjectDir.isFile()) {
targetProjectDir = targetProjectDir.getParentFile();
}
File rootProjectDir = new File(rootProjectPath).getParentFile();
StringBuilder buffer = new StringBuilder();
for (File f = new File(targetProjectPath).getParentFile(); f != null && !FileUtil.filesEqual(f, rootProjectDir); f = f.getParentFile()) {
for (File f = targetProjectDir; f != null && !FileUtil.filesEqual(f, rootProjectDir); f = f.getParentFile()) {
buffer.insert(0, f.getName()).insert(0, ":");
}
buffer.insert(0, rootProjectDir.getName());
@@ -117,7 +117,7 @@ public class ExternalSystemTaskSettingsControl implements ExternalSystemSettings
String path = myOriginalSettings.getExternalProjectPath();
if (StringUtil.isEmpty(path)) {
path = ExternalSystemApiUtil.getLastUsedExternalProjectPath(myExternalSystemId);
path = "";
}
myProjectPathField.setText(path);
myTasksTextField.setText(StringUtil.join(myOriginalSettings.getTaskNames(), " "));
@@ -241,6 +241,9 @@ public class ExternalProjectPathField extends ComponentWithBrowseButton<External
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
for (FoldRegion region : foldingModel.getAllFoldRegions()) {
foldingModel.removeFoldRegion(region);
}
FoldRegion region = foldingModel.addFoldRegion(0, editor.getDocument().getTextLength(), placeholder);
if (region != null) {
region.setExpanded(false);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

@@ -1,45 +0,0 @@
/*
* Copyright 2000-2009 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.lang;
import com.intellij.psi.PsiElement;
/**
* @author yole
*/
public class LanguageLiteralEscapers extends LanguageExtension<LiteralEscaper> {
public static final LanguageLiteralEscapers INSTANCE = new LanguageLiteralEscapers();
private LanguageLiteralEscapers() {
super("com.intellij.lang.literalEscaper", new LiteralEscaper() {
@Override
public String getEscapedText(final PsiElement context, final String originalText) {
return originalText;
}
@Override
public String escapeText(String originalText) {
return originalText;
}
@Override
public String unescapeText(String originalText) {
return originalText;
}
});
}
}
@@ -1,28 +0,0 @@
/*
* Copyright 2000-2009 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.lang;
import com.intellij.psi.PsiElement;
/**
* @author yole
*/
public interface LiteralEscaper {
String getEscapedText(PsiElement context, String originalText);
String escapeText(String originalText);
String unescapeText(String originalText);
}
@@ -13,20 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.plugins.intelliLang.references;
package com.intellij.psi.injection;
import com.intellij.lang.Language;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.util.ui.EmptyIcon;
import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author Dmitry Avdeev
@@ -41,6 +36,11 @@ public abstract class Injectable implements Comparable<Injectable> {
@NotNull
public abstract String getDisplayName();
@Nullable
public String getAdditionalDescription() {
return null;
}
@NotNull
public Icon getIcon() {
return EmptyIcon.ICON_16;
@@ -57,15 +57,13 @@ public abstract class Injectable implements Comparable<Injectable> {
@Nullable
public abstract Language getLanguage();
public static List<Injectable> getAllInjectables() {
Language[] languages = InjectedLanguage.getAvailableLanguages();
List<Injectable> list = new ArrayList<Injectable>();
for (Language language : languages) {
list.add(fromLanguage(language));
}
list.addAll(Arrays.asList(ReferenceInjector.EXTENSION_POINT_NAME.getExtensions()));
Collections.sort(list);
return list;
public Language toLanguage() {
return getLanguage() == null ? new Language(getId(), false) {
@Override
public String getDisplayName() {
return Injectable.this.getDisplayName();
}
} : getLanguage();
}
public static Injectable fromLanguage(final Language language) {
@@ -79,8 +77,14 @@ public abstract class Injectable implements Comparable<Injectable> {
@NotNull
@Override
public String getDisplayName() {
return language.getDisplayName();
}
@Nullable
@Override
public String getAdditionalDescription() {
final FileType ft = language.getAssociatedFileType();
return language.getDisplayName() + (ft != null ? " (" + ft.getDescription() + ")" : "");
return ft != null ? " (" + ft.getDescription() + ")" : null;
}
@NotNull
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.plugins.intelliLang.references;
package com.intellij.psi.injection;
import com.intellij.lang.Language;
import com.intellij.openapi.extensions.ExtensionPointName;
@@ -26,18 +26,23 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
/**
* This will work only in presence of IntelliLang plugin.
*
* @author Dmitry Avdeev
* Date: 01.08.13
*/
public abstract class ReferenceInjector extends Injectable {
final static ExtensionPointName<ReferenceInjector> EXTENSION_POINT_NAME = ExtensionPointName.create("org.intellij.intelliLang.referenceInjector");
public final static ExtensionPointName<ReferenceInjector> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.referenceInjector");
@Override
public final Language getLanguage() {
return null;
}
/**
* Generated references should be soft ({@link com.intellij.psi.PsiReference#isSoft()})
*/
@NotNull
public abstract PsiReference[] getReferences(@NotNull PsiElement element, @NotNull final ProcessingContext context, @NotNull TextRange range);
@@ -15,11 +15,7 @@
*/
package com.intellij.codeEditor.printing;
import com.intellij.CommonBundle;
import com.intellij.ide.highlighter.HighlighterFactory;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
@@ -160,8 +156,7 @@ class PrintManager {
printerJob.cancel();
}
catch (Exception e) {
Notifications.Bus.notify(new Notification("Print", CommonBundle.getErrorTitle(), e.getMessage(), NotificationType.ERROR));
LOG.warn(e);
LOG.error(e);
}
}
});
@@ -341,7 +341,7 @@ class ParameterInfoComponent extends JPanel {
myLabel.setForeground(FOREGROUND_COLOR);
if (flagsMap.isEmpty()) {
myLabel.setText(XmlStringUtil.wrapInHtml(text));
myLabel.setText(XmlStringUtil.wrapInHtml(XmlStringUtil.escapeString(text)));
}
else {
String labelText = buildLabelText(text, flagsMap);
@@ -21,6 +21,7 @@ import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.SearchTopHitProvider;
import com.intellij.ide.ui.LafManager;
import com.intellij.ide.ui.LafManagerListener;
import com.intellij.ide.ui.search.BooleanOptionDescription;
import com.intellij.ide.ui.search.OptionDescription;
import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
import com.intellij.ide.util.gotoByName.*;
@@ -58,6 +59,7 @@ import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.*;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.OnOffButton;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
@@ -330,11 +332,19 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component cmp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (myLocationString != null) {
if (myLocationString != null || value instanceof BooleanOptionDescription) {
final JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(UIUtil.getListBackground());
panel.setBackground(UIUtil.getListBackground(isSelected));
panel.add(cmp, BorderLayout.CENTER);
panel.add(myLocation.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus), BorderLayout.EAST);
final Component rightComponent;
if (value instanceof BooleanOptionDescription) {
final OnOffButton button = new OnOffButton();
button.setSelected(((BooleanOptionDescription)value).isOptionEnabled());
rightComponent = button;
} else {
rightComponent = myLocation.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
panel.add(rightComponent, BorderLayout.EAST);
cmp = panel;
}
@@ -59,7 +59,9 @@ public class MarkRootAction extends DumbAwareAction {
public void actionPerformed(AnActionEvent e) {
Module module = e.getData(LangDataKeys.MODULE);
VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
assert vFiles != null;
if (module == null || vFiles == null) {
return;
}
final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
for (VirtualFile vFile : vFiles) {
ContentEntry entry = findContentEntry(model, vFile);
@@ -138,10 +138,7 @@ public class ScopeViewPane extends AbstractProjectViewPane {
@Override
@NotNull
public String[] getSubIds() {
NamedScope[] scopes = myDependencyValidationManager.getScopes();
scopes = ArrayUtil.mergeArrays(scopes, myNamedScopeManager.getScopes());
scopes = NonProjectFilesScope.removeFromList(scopes);
scopes = ArrayUtil.remove(scopes, CustomScopesProviderEx.getAllScope());
NamedScope[] scopes = getShownScopes();
String[] ids = new String[scopes.length];
for (int i = 0; i < scopes.length; i++) {
final NamedScope scope = scopes[i];
@@ -150,6 +147,14 @@ public class ScopeViewPane extends AbstractProjectViewPane {
return ids;
}
private NamedScope[] getShownScopes() {
NamedScope[] scopes = myDependencyValidationManager.getScopes();
scopes = ArrayUtil.mergeArrays(scopes, myNamedScopeManager.getScopes());
scopes = NonProjectFilesScope.removeFromList(scopes);
scopes = ArrayUtil.remove(scopes, CustomScopesProviderEx.getAllScope());
return scopes;
}
@Override
@NotNull
public String getPresentableSubIdName(@NotNull final String subId) {
@@ -183,15 +188,13 @@ public class ScopeViewPane extends AbstractProjectViewPane {
if (psiFile == null) return;
if (!(element instanceof PsiElement)) return;
List<NamedScope> allScopes = new ArrayList<NamedScope>();
ContainerUtil.addAll(allScopes, myDependencyValidationManager.getScopes());
ContainerUtil.addAll(allScopes, myNamedScopeManager.getScopes());
for (int i = 0; i < allScopes.size(); i++) {
final NamedScope scope = allScopes.get(i);
NamedScope[] allScopes = getShownScopes();
for (int i = 0; i < allScopes.length; i++) {
final NamedScope scope = allScopes[i];
String name = scope.getName();
if (name.equals(getSubId())) {
allScopes.set(i, allScopes.get(0));
allScopes.set(0, scope);
allScopes[i] = allScopes[0];
allScopes[0] = scope;
break;
}
}
@@ -45,6 +45,7 @@ import com.intellij.util.Query;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
@@ -300,4 +301,9 @@ public abstract class CallerChooserBase<M extends PsiElement> extends DialogWrap
return myTree;
}
@Nullable
@Override
protected String getDimensionServiceKey() {
return "caller.chooser.dialog";
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -17,6 +17,7 @@ package com.intellij.ide;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.Key;
@@ -29,7 +30,8 @@ import java.awt.*;
public abstract class DataManager {
public static DataManager getInstance() {
return ApplicationManager.getApplication().getComponent(DataManager.class);
Application application = ApplicationManager.getApplication();
return application != null ? application.getComponent(DataManager.class) : null;
}
@NonNls public static final String CLIENT_PROPERTY_DATA_PROVIDER = "DataProvider";
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -24,10 +24,7 @@ import java.awt.*;
public abstract class DnDManager {
public static DnDManager getInstance() {
Application application = ApplicationManager.getApplication();
if (application == null) {
return null;
}
return (DnDManager)application.getPicoContainer().getComponentInstance(DnDManager.class.getName());
return application != null ? (DnDManager)application.getPicoContainer().getComponentInstance(DnDManager.class.getName()) : null;
}
public abstract void registerSource(DnDSource source, JComponent component);
@@ -41,6 +38,6 @@ public abstract class DnDManager {
public abstract void registerTarget(DnDTarget target, JComponent component);
public abstract void unregisterTarget(DnDTarget target, JComponent component);
public abstract Component getLastDropHandler();
}
@@ -23,10 +23,25 @@ import com.intellij.util.Consumer;
*/
public class UISimpleSettingsProvider implements SearchTopHitProvider {
private static UISettingsOptionDescription CYCLING_SCROLLING = new UISettingsOptionDescription("CYCLING_SCROLLING", "Cyclic scrolling", "appearance");
private static UISettingsOptionDescription MEMORY_INDICATOR = new UISettingsOptionDescription("SHOW_MEMORY_INDICATOR", "Show Memory Indicator", "appearance");
@Override
public void consumeTopHits(String pattern, Consumer<Object> collector) {
pattern = pattern.trim().toLowerCase();
if (pattern.startsWith("cyc") || pattern.startsWith("scr") || patternContains(pattern, "scroll")) {
collector.consume(CYCLING_SCROLLING);
} else if (patternContains(pattern, "memo")) {
collector.consume(MEMORY_INDICATOR);
}
}
private static boolean patternContains(String pattern, String search) {
for (String s : pattern.split(" ")) {
if (s.contains(search)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,128 @@
/*
* Copyright 2000-2013 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.ui.components;
import com.intellij.ui.Gray;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicToggleButtonUI;
import java.awt.*;
/**
* @author Konstantin Bulenkov
*/
public class OnOffButton extends JToggleButton {
private String myOnText;
private String myOffText;
public OnOffButton() {
setUI(OnOffButtonUI.createUI(this));
setOpaque(false);
setBorder(null);
}
public String getOnText() {
return myOnText == null ? "ON" : myOnText;
}
public void setOnText(String onText) {
myOnText = onText;
}
public String getOffText() {
return myOffText == null ? "OFF" : myOffText;
}
public void setOffText(String offText) {
myOffText = offText;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
public static class OnOffButtonUI extends BasicToggleButtonUI {
private final OnOffButton myButton;
public OnOffButtonUI(OnOffButton checkBox) {
myButton = checkBox;
}
@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
public static ComponentUI createUI(JComponent c) {
return new OnOffButtonUI((OnOffButton)c);
}
@Override
public Dimension getPreferredSize(JComponent c) {
final OnOffButton button = (OnOffButton)c;
String text = button.getOffText().length() > button.getOnText().length() ? button.getOffText() : button.getOnText();
text = text.toUpperCase();
final FontMetrics fm = c.getFontMetrics(c.getFont());
int w = fm.stringWidth(text);
int h = fm.getHeight();
h += 2*4;
w += 3 * h / 2 + 4;
return new Dimension(w, h);
}
@Override
public void paint(Graphics gr, JComponent c) {
final OnOffButton button = (OnOffButton)c;
final Dimension size = button.getSize();
int w = size.width-4;
int h = size.height-4;
if (h % 2 == 1) {
h--;
}
Graphics2D g = ((Graphics2D)gr);
GraphicsUtil.setupAAPainting(g);
g.translate(1,1);
if (button.isSelected()) {
g.setColor(new Color(13, 41, 62));
g.fillRoundRect(0, 0, w, h, h, h);
g.setColor(UIUtil.getBorderColor());
g.drawRoundRect(0, 0, w, h, h, h);
g.setColor(Gray._128);
g.fillOval(w - h + 1, 1, h - 1, h - 1);
g.setColor(UIUtil.getListForeground(true));
g.drawString(button.getOnText(), h/2, h - 4);
} else {
g.setColor(UIUtil.getPanelBackground());
g.fillRoundRect(0, 0, w, h, h, h);
g.setColor(UIUtil.getBorderColor());
g.drawRoundRect(0, 0, w, h, h, h);
g.setColor(UIUtil.getLabelDisabledForeground());
g.drawString(button.getOffText(), h + 4 , h - 4);
g.setColor(Gray._128);
g.fillOval(0, 0, h - 1, h - 1);
}
g.translate(-1, -1);
}
@Override
public Dimension getMinimumSize(JComponent c) {
return getPreferredSize(c);
}
@Override
public Dimension getMaximumSize(JComponent c) {
return getPreferredSize(c);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -284,21 +284,16 @@ public class Alarm implements Disposable {
myFuture = null;
}
if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) {
try {
try {
if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) {
SwingUtilities.invokeAndWait(task);
}
catch (Exception e) {
LOG.error(e);
}
}
else {
try {
else {
task.run();
}
catch (Exception e) {
LOG.error(e);
}
}
catch (Exception e) {
LOG.error("Exception in task " + task, e);
}
}
};
@@ -684,6 +684,9 @@ public class HintManagerImpl extends HintManager implements Disposable {
}
public void showInformationHint(@NotNull Editor editor, @NotNull JComponent component, boolean showByBalloon) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
LightweightHint hint = new LightweightHint(component);
Point p = getHintPosition(hint, editor, ABOVE);
showEditorHint(hint, editor, p, HIDE_BY_ANY_KEY | HIDE_BY_TEXT_CHANGE | HIDE_BY_SCROLLING, 0, false);
@@ -5596,7 +5596,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
mySelectionModel.setSelection(caretOffset, caretOffset);
}
else {
if (!e.isPopupTrigger() && eventArea == EditorMouseEventArea.EDITING_AREA) {
if (!e.isPopupTrigger()
&& (eventArea == EditorMouseEventArea.EDITING_AREA || eventArea == EditorMouseEventArea.LINE_NUMBERS_AREA))
{
switch (e.getClickCount()) {
case 2:
selectWordAtCaret(mySettings.isMouseClickSelectionHonorsCamelWords() && mySettings.isCamelWords());
@@ -103,6 +103,7 @@
<extensionPoint name="multiHostInjector"
interface="com.intellij.lang.injection.MultiHostInjector"
area="IDEA_PROJECT"/>
<extensionPoint name="referenceInjector" interface="com.intellij.psi.injection.ReferenceInjector"/>
<extensionPoint name="annotator"
beanClass="com.intellij.lang.LanguageExtensionPoint">
@@ -144,11 +145,6 @@
<with attribute="implementationClass" implements="com.intellij.lang.Commenter"/>
</extensionPoint>
<extensionPoint name="lang.literalEscaper"
beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.lang.LiteralEscaper"/>
</extensionPoint>
<extensionPoint name="lang.braceMatcher"
beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.lang.PairedBraceMatcher"/>
@@ -305,5 +305,6 @@
groupKey="group.names.portability.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.intellij.codeStyle.InconsistentLineSeparatorsInspection"/>
<search.topHitProvider implementation="com.intellij.platform.DefaultPlatformTopHitProvider"/>
<search.topHitProvider implementation="com.intellij.ide.ui.UISimpleSettingsProvider"/>
</extensions>
</idea-plugin>
@@ -8,8 +8,8 @@
serviceImplementation="com.intellij.remoteServer.impl.configuration.RemoteServersManagerImpl"/>
<applicationService serviceInterface="com.intellij.remoteServer.configuration.deployment.DeploymentSourceUtil"
serviceImplementation="com.intellij.remoteServer.impl.configuration.deployment.DeploymentSourceUtilImpl"/>
<projectService serviceInterface="com.intellij.remoteServer.runtime.ServerConnectionManager"
serviceImplementation="com.intellij.remoteServer.impl.runtime.ServerConnectionManagerImpl"/>
<applicationService serviceInterface="com.intellij.remoteServer.runtime.ServerConnectionManager"
serviceImplementation="com.intellij.remoteServer.impl.runtime.ServerConnectionManagerImpl"/>
<applicationConfigurable instance="com.intellij.remoteServer.impl.configuration.RemoteServerListConfigurable"/>
<programRunner implementation="com.intellij.remoteServer.impl.runtime.DeployToServerRunner"/>
</extensions>
@@ -111,8 +111,6 @@
<renameHandler implementation="com.intellij.xml.refactoring.SchemaPrefixRenameHandler" order="before xmlTagRenameHandler"/>
<refactoring.inlineHandler language="XML" implementationClass="com.intellij.xml.refactoring.XmlInlineHandler"/>
<lang.literalEscaper language="XML" implementationClass="com.intellij.lang.xml.XmlLiteralEscaper"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.XmlCompletionContributor" id="xml"
order="first"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.XmlNonFirstCompletionContributor" id="xmlNonFirst" order="after xml"/>
@@ -6,10 +6,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.remoteServer.configuration.ServerConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurator;
import com.intellij.remoteServer.runtime.ServerConnector;
import com.intellij.remoteServer.runtime.ServerTaskExecutor;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.concurrent.Executor;
/**
* @author nik
@@ -42,5 +42,5 @@ public abstract class ServerType<C extends ServerConfiguration> {
public abstract DeploymentConfigurator<?> createDeployer(Project project);
@NotNull
public abstract ServerConnector<?> createConnector(@NotNull C configuration, @NotNull Project project, @NotNull Executor asyncTasksExecutor);
public abstract ServerConnector<?> createConnector(@NotNull C configuration, @NotNull ServerTaskExecutor asyncTasksExecutor);
}
@@ -0,0 +1,10 @@
package com.intellij.remoteServer.runtime;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public interface RemoteOperationCallback {
void errorOccurred(@NotNull String errorMessage);
}
@@ -4,6 +4,7 @@ import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import com.intellij.remoteServer.runtime.deployment.DeploymentStatus;
import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
import org.jetbrains.annotations.NotNull;
/**
@@ -20,9 +21,12 @@ public interface ServerConnection<D extends DeploymentConfiguration> {
String getStatusText();
void deploy(@NotNull DeploymentSource source, @NotNull D configuration);
void connect(@NotNull Runnable onFinished);
void undeploy(@NotNull DeploymentSource source, @NotNull D configuration);
void deploy(@NotNull DeploymentTask<D> task);
void undeploy(@NotNull DeploymentTask<D> task);
@NotNull
DeploymentStatus getDeploymentStatus(@NotNull DeploymentSource source);
@@ -1,7 +1,6 @@
package com.intellij.remoteServer.runtime;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.ServerConfiguration;
import org.jetbrains.annotations.NotNull;
@@ -13,8 +12,8 @@ import java.util.Collection;
*/
public abstract class ServerConnectionManager {
@NotNull
public static ServerConnectionManager getInstance(@NotNull Project project) {
return ServiceManager.getService(project, ServerConnectionManager.class);
public static ServerConnectionManager getInstance() {
return ServiceManager.getService(ServerConnectionManager.class);
}
@NotNull
@@ -12,8 +12,7 @@ public abstract class ServerConnector<D extends DeploymentConfiguration> {
public abstract void disconnect();
public interface ConnectionCallback<D extends DeploymentConfiguration> {
public interface ConnectionCallback<D extends DeploymentConfiguration> extends RemoteOperationCallback {
void connected(@NotNull ServerRuntimeInstance<D> serverRuntimeInstance);
void connectionFailed(@NotNull String errorMessage);
}
}
@@ -1,7 +0,0 @@
package com.intellij.remoteServer.runtime;
/**
* @author nik
*/
public interface ServerRuntimeData {
}
@@ -0,0 +1,14 @@
package com.intellij.remoteServer.runtime;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Executor;
/**
* @author nik
*/
public interface ServerTaskExecutor extends Executor {
void submit(@NotNull Runnable command);
void submit(@NotNull ThrowableRunnable<?> command, @NotNull RemoteOperationCallback callback);
}
@@ -0,0 +1,20 @@
package com.intellij.remoteServer.runtime.deployment;
import com.intellij.openapi.project.Project;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public interface DeploymentTask<D extends DeploymentConfiguration> {
@NotNull
DeploymentSource getSource();
@NotNull
D getConfiguration();
@NotNull
Project getProject();
}
@@ -1,7 +1,7 @@
package com.intellij.remoteServer.runtime.deployment;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import com.intellij.remoteServer.runtime.RemoteOperationCallback;
import org.jetbrains.annotations.NotNull;
/**
@@ -9,15 +9,11 @@ import org.jetbrains.annotations.NotNull;
*/
public abstract class ServerRuntimeInstance<D extends DeploymentConfiguration> {
public abstract void deploy(@NotNull DeploymentSource source, @NotNull D configuration,
@NotNull DeploymentOperationCallback callback);
public abstract void deploy(@NotNull DeploymentTask<D> task, @NotNull DeploymentOperationCallback callback);
public abstract void undeploy(@NotNull DeploymentSource source, @NotNull D configuration,
@NotNull DeploymentOperationCallback callback);
public abstract void undeploy(@NotNull DeploymentTask<D> task, @NotNull DeploymentOperationCallback callback);
public interface DeploymentOperationCallback {
public interface DeploymentOperationCallback extends RemoteOperationCallback {
void succeeded();
void failed(@NotNull String errorMessage);
}
}
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.remoteServer.impl.configuration.RemoteServerConfigurable">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="ab159" binding="mySettingsPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<vspacer id="7a5f8">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="9d650" class="javax.swing.JButton" binding="myTestConnectionButton" default-binding="true">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Test connection"/>
</properties>
</component>
<hspacer id="79e5">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children>
</grid>
</form>
@@ -1,15 +1,27 @@
package com.intellij.remoteServer.impl.configuration;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.ServerConfiguration;
import com.intellij.remoteServer.runtime.ConnectionStatus;
import com.intellij.remoteServer.runtime.ServerConnection;
import com.intellij.remoteServer.runtime.ServerConnectionManager;
import com.intellij.util.concurrency.Semaphore;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author nik
@@ -19,6 +31,9 @@ public class RemoteServerConfigurable extends NamedConfigurable<RemoteServer<?>>
private final RemoteServer<?> myServer;
private String myServerName;
private boolean myNew;
private JPanel myMainPanel;
private JPanel mySettingsPanel;
private JButton myTestConnectionButton;
public <C extends ServerConfiguration> RemoteServerConfigurable(RemoteServer<C> server, Runnable treeUpdater, boolean isNew) {
super(true, treeUpdater);
@@ -41,10 +56,58 @@ public class RemoteServerConfigurable extends NamedConfigurable<RemoteServer<?>>
@Override
public JComponent createOptionsPanel() {
JComponent component = myConfigurable.createComponent();
JPanel panel = new JPanel(new BorderLayout());
panel.add(component, BorderLayout.NORTH);
return panel;
mySettingsPanel.add(BorderLayout.CENTER, myConfigurable.createComponent());
myTestConnectionButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
apply();
}
catch (ConfigurationException exc) {
Messages.showErrorDialog(myMainPanel, "Cannot test connection: " + exc.getMessage(), exc.getTitle());
return;
}
testConnection();
}
});
return myMainPanel;
}
private void testConnection() {
final ServerConnection connection = ServerConnectionManager.getInstance().getOrCreateConnection(myServer);
final AtomicReference<Runnable> showResultRef = new AtomicReference<Runnable>(null);
new Task.Modal(null, "Connecting...", true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
indicator.setIndeterminate(true);
final Semaphore semaphore = new Semaphore();
semaphore.down();
connection.connect(new Runnable() {
@Override
public void run() {
showResultRef.set(new Runnable() {
@Override
public void run() {
if (connection.getStatus() == ConnectionStatus.CONNECTED) {
Messages.showInfoMessage(myMainPanel, "Connection successful", "Test Connection");
}
else if (connection.getStatus() == ConnectionStatus.DISCONNECTED) {
Messages.showErrorDialog(myMainPanel, "Cannot connect: " + connection.getStatusText(), "Test Connection");
}
}
});
semaphore.up();
}
});
while (!indicator.isCanceled()) {
semaphore.waitFor(500);
}
Runnable showResult = showResultRef.get();
if (showResult != null) {
ApplicationManager.getApplication().invokeLater(showResult);
}
}
}.queue();
}
@Nls
@@ -25,6 +25,7 @@ import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.ServerConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import com.intellij.remoteServer.impl.runtime.deployment.DeploymentTaskImpl;
import com.intellij.remoteServer.runtime.ServerConnection;
import com.intellij.remoteServer.runtime.ServerConnectionManager;
import org.jetbrains.annotations.NotNull;
@@ -51,8 +52,8 @@ public class DeployToServerState<S extends ServerConfiguration, D extends Deploy
@Nullable
@Override
public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
ServerConnection connection = ServerConnectionManager.getInstance(myEnvironment.getProject()).getOrCreateConnection(myServer);
connection.deploy(mySource, myConfiguration);
ServerConnection connection = ServerConnectionManager.getInstance().getOrCreateConnection(myServer);
connection.deploy(new DeploymentTaskImpl(mySource, myConfiguration, myEnvironment.getProject()));
return null;
}
}
@@ -3,12 +3,13 @@ package com.intellij.remoteServer.impl.runtime;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import com.intellij.remoteServer.impl.runtime.deployment.DeploymentInformation;
import com.intellij.remoteServer.runtime.ConnectionStatus;
import com.intellij.remoteServer.runtime.ServerConnection;
import com.intellij.remoteServer.runtime.ServerConnector;
import com.intellij.remoteServer.runtime.deployment.DeploymentStatus;
import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
import com.intellij.util.ParameterizedRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ConcurrentHashMap;
@@ -48,23 +49,49 @@ public class ServerConnectionImpl<D extends DeploymentConfiguration> implements
}
@Override
public void deploy(@NotNull final DeploymentSource source, @NotNull final D configuration) {
runOnInstance(new ParameterizedRunnable<ServerRuntimeInstance<D>>() {
public void connect(@NotNull final Runnable onFinished) {
disconnect();
connectIfNeeded(new ServerConnector.ConnectionCallback<D>() {
@Override
public void run(ServerRuntimeInstance<D> instance) {
myDeploymentInfos.put(source, new DeploymentInformation(DeploymentStatus.DEPLOYING));
instance.deploy(source, configuration, new UpdateDeploymentStatusCallback(source, DeploymentStatus.DEPLOYED,
DeploymentStatus.NOT_DEPLOYED));
public void connected(@NotNull ServerRuntimeInstance<D> serverRuntimeInstance) {
onFinished.run();
}
@Override
public void errorOccurred(@NotNull String errorMessage) {
onFinished.run();
}
});
}
private void disconnect() {
if (myStatus == ConnectionStatus.CONNECTED) {
myRuntimeInstance = null;
myConnector.disconnect();
myStatus = ConnectionStatus.DISCONNECTED;
}
}
@Override
public void deploy(@NotNull final DeploymentTask<D> task) {
connectIfNeeded(new ConnectionCallbackBase<D>() {
@Override
public void connected(@NotNull ServerRuntimeInstance<D> instance) {
myDeploymentInfos.put(task.getSource(), new DeploymentInformation(DeploymentStatus.DEPLOYING));
instance.deploy(task, new UpdateDeploymentStatusCallback(task.getSource(), DeploymentStatus.DEPLOYED,
DeploymentStatus.NOT_DEPLOYED));
}
});
}
@Override
public void undeploy(@NotNull final DeploymentSource source, @NotNull final D configuration) {
runOnInstance(new ParameterizedRunnable<ServerRuntimeInstance<D>>() {
public void undeploy(@NotNull final DeploymentTask<D> task) {
connectIfNeeded(new ConnectionCallbackBase<D>() {
@Override
public void run(ServerRuntimeInstance<D> instance) {
instance.undeploy(source, configuration, new UpdateDeploymentStatusCallback(source, DeploymentStatus.NOT_DEPLOYED, DeploymentStatus.DEPLOYED));
public void connected(@NotNull ServerRuntimeInstance<D> instance) {
myDeploymentInfos.put(task.getSource(), new DeploymentInformation(DeploymentStatus.UNDEPLOYING));
instance.undeploy(task, new UpdateDeploymentStatusCallback(task.getSource(), DeploymentStatus.NOT_DEPLOYED,
DeploymentStatus.DEPLOYED));
}
});
}
@@ -76,10 +103,10 @@ public class ServerConnectionImpl<D extends DeploymentConfiguration> implements
return information != null ? information.getStatus() : DeploymentStatus.NOT_DEPLOYED;
}
private void runOnInstance(final ParameterizedRunnable<ServerRuntimeInstance<D>> action) {
private void connectIfNeeded(final ServerConnector.ConnectionCallback<D> callback) {
final ServerRuntimeInstance<D> instance = myRuntimeInstance;
if (instance != null) {
action.run(instance);
callback.connected(instance);
return;
}
@@ -89,18 +116,25 @@ public class ServerConnectionImpl<D extends DeploymentConfiguration> implements
public void connected(@NotNull ServerRuntimeInstance<D> instance) {
myStatus = ConnectionStatus.CONNECTED;
myRuntimeInstance = instance;
action.run(instance);
callback.connected(instance);
}
@Override
public void connectionFailed(@NotNull String errorMessage) {
public void errorOccurred(@NotNull String errorMessage) {
myStatus = ConnectionStatus.DISCONNECTED;
myRuntimeInstance = null;
myStatusText = errorMessage;
callback.errorOccurred(errorMessage);
}
});
}
private static abstract class ConnectionCallbackBase<D extends DeploymentConfiguration> implements ServerConnector.ConnectionCallback<D> {
@Override
public void errorOccurred(@NotNull String errorMessage) {
}
}
private class UpdateDeploymentStatusCallback implements ServerRuntimeInstance.DeploymentOperationCallback {
private final DeploymentSource mySource;
private DeploymentStatus mySuccessStatus;
@@ -118,7 +152,7 @@ public class ServerConnectionImpl<D extends DeploymentConfiguration> implements
}
@Override
public void failed(@NotNull String errorMessage) {
public void errorOccurred(@NotNull String errorMessage) {
myDeploymentInfos.put(mySource, new DeploymentInformation(myFailedStatus, errorMessage));
}
}
@@ -1,13 +1,11 @@
package com.intellij.remoteServer.impl.runtime;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.ServerConfiguration;
import com.intellij.remoteServer.runtime.ServerConnection;
import com.intellij.remoteServer.runtime.ServerConnectionManager;
import com.intellij.util.concurrency.SequentialTaskExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.ide.PooledThreadExecutor;
import java.util.Collection;
import java.util.Collections;
@@ -19,20 +17,15 @@ import java.util.Map;
*/
public class ServerConnectionManagerImpl extends ServerConnectionManager {
private Map<RemoteServer<?>, ServerConnection> myConnections = new HashMap<RemoteServer<?>, ServerConnection>();
private final PooledThreadExecutor myPooledThreadExecutor = new PooledThreadExecutor();
private final Project myProject;
public ServerConnectionManagerImpl(Project project) {
myProject = project;
}
@NotNull
@Override
public <C extends ServerConfiguration> ServerConnection getOrCreateConnection(@NotNull RemoteServer<C> server) {
ApplicationManager.getApplication().assertIsDispatchThread();
ServerConnection connection = myConnections.get(server);
if (connection == null) {
SequentialTaskExecutor executor = new SequentialTaskExecutor(myPooledThreadExecutor);
connection = new ServerConnectionImpl(server, server.getType().createConnector(server.getConfiguration(), myProject, executor));
ServerTaskExecutorImpl executor = new ServerTaskExecutorImpl();
connection = new ServerConnectionImpl(server, server.getType().createConnector(server.getConfiguration(), executor));
myConnections.put(server, connection);
}
return connection;
@@ -41,6 +34,7 @@ public class ServerConnectionManagerImpl extends ServerConnectionManager {
@NotNull
@Override
public Collection<ServerConnection> getConnections() {
ApplicationManager.getApplication().assertIsDispatchThread();
return Collections.unmodifiableCollection(myConnections.values());
}
}
@@ -0,0 +1,48 @@
package com.intellij.remoteServer.impl.runtime;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.remoteServer.runtime.RemoteOperationCallback;
import com.intellij.remoteServer.runtime.ServerTaskExecutor;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.concurrency.SequentialTaskExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.ide.PooledThreadExecutor;
/**
* @author nik
*/
public class ServerTaskExecutorImpl implements ServerTaskExecutor {
private static final Logger LOG = Logger.getInstance(ServerTaskExecutorImpl.class);
private static final PooledThreadExecutor POOLED_THREAD_EXECUTOR = new PooledThreadExecutor();
private final SequentialTaskExecutor myTaskExecutor;
public ServerTaskExecutorImpl() {
myTaskExecutor = new SequentialTaskExecutor(POOLED_THREAD_EXECUTOR);
}
@Override
public void execute(@NotNull Runnable command) {
myTaskExecutor.execute(command);
}
@Override
public void submit(@NotNull Runnable command) {
execute(command);
}
@Override
public void submit(@NotNull final ThrowableRunnable<?> command, @NotNull final RemoteOperationCallback callback) {
execute(new Runnable() {
@Override
public void run() {
try {
command.run();
}
catch (Throwable e) {
LOG.info(e);
callback.errorOccurred(e.getMessage());
}
}
});
}
}
@@ -1,4 +1,4 @@
package com.intellij.remoteServer.impl.runtime;
package com.intellij.remoteServer.impl.runtime.deployment;
import com.intellij.remoteServer.runtime.deployment.DeploymentStatus;
import org.jetbrains.annotations.NotNull;
@@ -0,0 +1,37 @@
package com.intellij.remoteServer.impl.runtime.deployment;
import com.intellij.openapi.project.Project;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public class DeploymentTaskImpl<D extends DeploymentConfiguration> implements DeploymentTask<D> {
private final DeploymentSource mySource;
private final D myConfiguration;
private final Project myProject;
public DeploymentTaskImpl(DeploymentSource source, D configuration, Project project) {
mySource = source;
myConfiguration = configuration;
myProject = project;
}
@NotNull
public DeploymentSource getSource() {
return mySource;
}
@NotNull
public D getConfiguration() {
return myConfiguration;
}
@NotNull
public Project getProject() {
return myProject;
}
}
@@ -667,7 +667,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
myFile.getName() +
" at caret position, offset " +
myEditor.getCaretModel().getOffset() + "\"" +
" psi structure: " + DebugUtil.psiToString(myFile, true);
" psi structure: " + DebugUtil.psiToString(myFile, true, true);
return element;
}
@@ -136,7 +136,6 @@ public class AllIcons {
public static final Icon ShowHiddens = IconLoader.getIcon("/actions/showHiddens.png"); // 16x16
public static final Icon ShowImportStatements = IconLoader.getIcon("/actions/showImportStatements.png"); // 16x16
public static final Icon ShowReadAccess = IconLoader.getIcon("/actions/showReadAccess.png"); // 16x16
public static final Icon ShowSource = IconLoader.getIcon("/actions/showSource.png"); // 16x16
public static final Icon ShowViewer = IconLoader.getIcon("/actions/showViewer.png"); // 16x16
public static final Icon ShowWriteAccess = IconLoader.getIcon("/actions/showWriteAccess.png"); // 16x16
public static final Icon SortAsc = IconLoader.getIcon("/actions/sortAsc.png"); // 9x8
@@ -19,6 +19,7 @@ import com.intellij.util.containers.ConcurrentFactoryMap;
/**
* @author peter
* @see ReflectionCache
*/
public class ReflectionAssignabilityCache {
private final ConcurrentFactoryMap<Class, ConcurrentFactoryMap<Class, Boolean>> myCache = new ConcurrentFactoryMap<Class, ConcurrentFactoryMap<Class, Boolean>>() {
@@ -18,6 +18,7 @@ package com.intellij.util.xmlb;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.xmlb.annotations.OptionTag;
import org.jdom.Attribute;
@@ -64,7 +65,9 @@ class OptionTagBinding implements Binding {
Element targetElement = new Element(myTagName);
Object value = accessor.read(o);
targetElement.setAttribute(myNameAttribute, myName);
if (!StringUtil.isEmpty(myNameAttribute)) {
targetElement.setAttribute(myNameAttribute, myName);
}
if (value == null) return targetElement;
@@ -123,6 +126,9 @@ class OptionTagBinding implements Binding {
Element e = (Element)node;
if (!e.getName().equals(myTagName)) return false;
String name = e.getAttributeValue(myNameAttribute);
if (StringUtil.isEmpty(myNameAttribute)) {
return name == null || name.equals(myName);
}
return name != null && name.equals(myName);
}
@@ -23,7 +23,8 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Store value in tag like &lt;option name="optionName" value="optionValue"/&gt;
* <p>Store value in tag like {@code <option name="optionName" value="optionValue"/>}</p>
* <p>nameAttribute can be empty, in which case it is skipped: {@code <option value="optionValue" />}</p>
*
* @author nik
*/
@@ -1,26 +0,0 @@
/*
* Copyright 2000-2009 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.openapi.vcs;
public enum ThreeStateBoolean {
yes,
no,
z;
public static ThreeStateBoolean getInstance(final boolean value) {
return value ? yes : no;
}
}
@@ -21,14 +21,13 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.IgnoreSpaceEnum;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PlatformUtils;
import org.jdom.Element;
import com.intellij.util.xmlb.XmlSerializerUtil;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.OptionTag;
import com.intellij.util.xmlb.annotations.Property;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -38,28 +37,18 @@ import java.util.List;
/**
* author: lesya
*/
@State(
name = "VcsManagerConfiguration",
storages = {
@Storage(
file = StoragePathMacros.WORKSPACE_FILE
)
}
)
public final class VcsConfiguration implements PersistentStateComponent<Element> {
storages = { @Storage(file = StoragePathMacros.WORKSPACE_FILE) })
public final class VcsConfiguration implements PersistentStateComponent<VcsConfiguration> {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.VcsConfiguration");
public final static long ourMaximumFileForBaseRevisionSize = 500 * 1000;
@NonNls static final String VALUE_ATTR = "value";
@NonNls private static final String CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT = "confirmMoveToFailedCommit";
@NonNls private static final String CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT = "confirmRemoveEmptyChangelist";
@NonNls public static final String PATCH = "patch";
@NonNls public static final String DIFF = "diff";
private Project myProject;
public boolean OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT = true;
public boolean CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT = !PlatformUtils.isPyCharm() && !PlatformUtils.isRubyMine();
public boolean CHECK_NEW_TODO = true;
@@ -71,7 +60,9 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
public boolean PERFORM_ADD_REMOVE_IN_BACKGROUND = true;
public boolean PERFORM_ROLLBACK_IN_BACKGROUND = false;
public volatile boolean CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND = false;
@OptionTag(tag = "confirmMoveToFailedCommit", nameAttribute = "")
public VcsShowConfirmationOption.Value MOVE_TO_FAILED_COMMIT_CHANGELIST = VcsShowConfirmationOption.Value.SHOW_CONFIRMATION;
@OptionTag(tag = "confirmRemoveEmptyChangelist", nameAttribute = "")
public VcsShowConfirmationOption.Value REMOVE_EMPTY_INACTIVE_CHANGELISTS = VcsShowConfirmationOption.Value.SHOW_CONFIRMATION;
public int CHANGED_ON_SERVER_INTERVAL = 60;
public boolean SHOW_ONLY_CHANGED_IN_SELECTION_DIFF = true;
@@ -132,7 +123,9 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
public boolean FORCE_NON_EMPTY_COMMENT = false;
public boolean CLEAR_INITIAL_COMMIT_MESSAGE = false;
private final ArrayList<String> myLastCommitMessages = new ArrayList<String>();
@Property(surroundWithTag = false)
@AbstractCollection(elementTag = "MESSAGE", elementValueAttribute = "value", surroundWithTag = false)
public List<String> myLastCommitMessages = new ArrayList<String>();
public String LAST_COMMIT_MESSAGE = null;
public boolean MAKE_NEW_CHANGELIST_ACTIVE = false;
@@ -145,7 +138,6 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
public float FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION = 0.8f;
public float FILE_HISTORY_DIALOG_SPLITTER_PROPORTION = 0.5f;
public String ACTIVE_VCS_NAME = null;
public boolean UPDATE_GROUP_BY_PACKAGES = false;
public boolean UPDATE_GROUP_BY_CHANGELIST = false;
public boolean UPDATE_FILTER_BY_SCOPE = false;
@@ -160,71 +152,15 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
private final PerformInBackgroundOption myCheckoutOption = new CheckoutInBackgroundOption();
private final PerformInBackgroundOption myAddRemoveOption = new AddRemoveInBackgroundOption();
public VcsConfiguration(final Project project) {
myProject = project;
public VcsConfiguration() {
}
public Element getState() {
try {
final Element e = new Element("state");
writeExternal(e);
return e;
}
catch (WriteExternalException e1) {
LOG.error(e1);
return null;
}
public VcsConfiguration getState() {
return this;
}
public void loadState(Element state) {
try {
readExternal(state);
}
catch (InvalidDataException e) {
LOG.error(e);
}
}
public void readExternal(Element element) throws InvalidDataException {
DefaultJDOMExternalizer.readExternal(this, element);
Element child = element.getChild(CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT);
if (child != null) {
MOVE_TO_FAILED_COMMIT_CHANGELIST = VcsShowConfirmationOption.Value.fromString(child.getAttributeValue(VALUE_ATTR));
}
child = element.getChild(CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT);
if (child != null) {
REMOVE_EMPTY_INACTIVE_CHANGELISTS = VcsShowConfirmationOption.Value.fromString(child.getAttributeValue(VALUE_ATTR));
}
final List messages = element.getChildren(MESSAGE_ELEMENT_NAME);
for (final Object message : messages) {
saveCommitMessage(((Element)message).getAttributeValue(VALUE_ATTR));
}
if (ACTIVE_VCS_NAME != null && ACTIVE_VCS_NAME.length() > 0) {
StartupManager.getInstance(myProject).registerStartupActivity(new Runnable() {
public void run() {
ProjectLevelVcsManager.getInstance(myProject).setDirectoryMapping("", ACTIVE_VCS_NAME);
}
});
}
}
public void writeExternal(Element element) throws WriteExternalException {
DefaultJDOMExternalizer.writeExternal(this, element);
if (MOVE_TO_FAILED_COMMIT_CHANGELIST != VcsShowConfirmationOption.Value.SHOW_CONFIRMATION) {
Element confirmChild = new Element(CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT);
confirmChild.setAttribute(VALUE_ATTR, MOVE_TO_FAILED_COMMIT_CHANGELIST.toString());
element.addContent(confirmChild);
}
if (REMOVE_EMPTY_INACTIVE_CHANGELISTS != VcsShowConfirmationOption.Value.SHOW_CONFIRMATION) {
Element confirmChild = new Element(CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT);
confirmChild.setAttribute(VALUE_ATTR, REMOVE_EMPTY_INACTIVE_CHANGELISTS.toString());
element.addContent(confirmChild);
}
for (String message : myLastCommitMessages) {
final Element messageElement = new Element(MESSAGE_ELEMENT_NAME);
messageElement.setAttribute(VALUE_ATTR, message);
element.addContent(messageElement);
}
public void loadState(VcsConfiguration state) {
XmlSerializerUtil.copyBean(state, this);
}
public static VcsConfiguration getInstance(Project project) {
@@ -232,17 +168,12 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
}
public void saveCommitMessage(final String comment) {
LAST_COMMIT_MESSAGE = comment;
if (comment == null || comment.length() == 0) return;
myLastCommitMessages.remove(comment);
while (myLastCommitMessages.size() >= MAX_STORED_MESSAGES) {
myLastCommitMessages.remove(0);
}
myLastCommitMessages.add(comment);
}
@@ -16,34 +16,27 @@
package com.intellij.openapi.vcs;
public interface VcsShowConfirmationOption {
enum Value {
SHOW_CONFIRMATION(0),
DO_NOTHING_SILENTLY(1),
DO_ACTION_SILENTLY(2);
// NB: don't reorder enum values, otherwise you may break user settings based on the obsolete implementation
SHOW_CONFIRMATION,
DO_NOTHING_SILENTLY,
DO_ACTION_SILENTLY;
private final int myId;
Value(final int id) {
myId = id;
}
public int getId() {
return myId;
}
public String toString() {
return String.valueOf(myId);
// compatibility with the old implementation
return String.valueOf(ordinal());
}
@Deprecated
public static Value fromString(String s){
if (s == null) return SHOW_CONFIRMATION;
if (s.equals("1")) return DO_NOTHING_SILENTLY;
if (s.equals("2")) return DO_ACTION_SILENTLY;
return SHOW_CONFIRMATION;
}
}
public static final VcsShowConfirmationOption STATIC_SHOW_CONFIRMATION = new VcsShowConfirmationOption() {
VcsShowConfirmationOption STATIC_SHOW_CONFIRMATION = new VcsShowConfirmationOption() {
@Override
public Value getValue() {
return Value.SHOW_CONFIRMATION;
@@ -216,8 +216,10 @@ public class VcsGeneralConfigurationPanel implements SearchableConfigurable {
myForceNonEmptyComment.setSelected(settings.FORCE_NON_EMPTY_COMMENT);
myClearInitialCommitMessage.setSelected(settings.CLEAR_INITIAL_COMMIT_MESSAGE);
myCbOfferToMoveChanges.setSelected(settings.OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT);
int id = settings.REMOVE_EMPTY_INACTIVE_CHANGELISTS.getId();
UIUtil.setSelectedButton(myEmptyChangelistRemovingGroup, id == 0 ? 0 : id == 1 ? 2 : 1);
VcsShowConfirmationOption.Value value = settings.REMOVE_EMPTY_INACTIVE_CHANGELISTS;
UIUtil.setSelectedButton(myEmptyChangelistRemovingGroup, value == VcsShowConfirmationOption.Value.SHOW_CONFIRMATION
? 0
: value == VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY ? 2 : 1);
myShowReadOnlyStatusDialog.setSelected(getReadOnlyStatusHandler().getState().SHOW_DIALOG);
if (settings.MOVE_TO_FAILED_COMMIT_CHANGELIST == VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY) {
myFailedCommitChangelistCombo.setSelectedIndex(0);
@@ -1,11 +1,17 @@
package org.intellij.plugins.intelliLang;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiReference;
import com.intellij.psi.impl.PsiModificationTrackerImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import org.intellij.plugins.intelliLang.inject.InjectLanguageAction;
import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction;
import org.intellij.plugins.intelliLang.references.FileReferenceInjector;
import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor;
import org.intellij.plugins.intelliLang.references.InjectedReferencesInspection;
import org.jdom.Element;
/**
@@ -27,6 +33,11 @@ public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestC
assertFalse(new InjectLanguageAction().isAvailable(getProject(), myFixture.getEditor(), myFixture.getFile()));
assertTrue(new UnInjectLanguageAction().isAvailable(getProject(), myFixture.getEditor(), myFixture.getFile()));
myFixture.configureByText("bar.xml",
"<foo xmlns=\"<error descr=\"URI is not registered (Settings | Project Settings | Schemas and DTDs)\">http://foo.bar</error>\" \n" +
" xxx=\"<error descr=\"Cannot resolve file 'bar'\">b<caret>ar</error>\"/>");
myFixture.testHighlighting();
UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile());
assertNull(myFixture.getReferenceAtCaretPosition());
}
@@ -60,4 +71,44 @@ public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestC
UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile());
assertNull(myFixture.getReferenceAtCaretPosition());
}
public void testInjectIntoJava() throws Exception {
myFixture.configureByText("Foo.java", "class Foo {\n" +
" String bar() {\n" +
" return \"ba<caret>r.xml\";\n" +
" } \n" +
"}");
assertNull(getInjectedReferences());
InjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile(), new FileReferenceInjector());
assertNotNull(getInjectedReferences());
UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile());
assertNull(getInjectedReferences());
}
private PsiReference[] getInjectedReferences() {
PsiElement element = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
element = PsiTreeUtil.getParentOfType(element, PsiLanguageInjectionHost.class);
assertNotNull(element);
element.getReferences();
return InjectedReferencesContributor.getInjectedReferences(element);
}
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(new InjectedReferencesInspection());
}
@Override
protected void tearDown() throws Exception {
myFixture.disableInspections(new InjectedReferencesInspection());
super.tearDown();
}
@Override
protected boolean isWriteActionRequired() {
return false;
}
}
@@ -26,7 +26,7 @@ import com.intellij.psi.*;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.util.IncorrectOperationException;
import gnu.trove.THashMap;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -42,7 +42,7 @@ public class MethodParameterInjection extends BaseInjection {
private final Map<String, MethodInfo> myParameterMap = new THashMap<String, MethodInfo>();
public MethodParameterInjection() {
super(LanguageInjectionSupport.JAVA_SUPPORT_ID);
super(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID);
}
@NotNull
@@ -69,7 +69,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector {
myConfiguration = configuration;
myProject = project;
myTemporaryPlacesRegistry = temporaryPlacesRegistry;
mySupport = InjectorUtils.findNotNullInjectionSupport(LanguageInjectionSupport.JAVA_SUPPORT_ID);
mySupport = InjectorUtils.findNotNullInjectionSupport(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID);
myXmlIndex = CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider<Collection<String>>() {
public Result<Collection<String>> compute() {
final Map<ElementPattern<?>, BaseInjection> map = new THashMap<ElementPattern<?>, BaseInjection>();
@@ -139,7 +139,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector {
if (!hasLiteral) return;
final Language tempLanguage = tempInjectedLanguage == null ? null : tempInjectedLanguage.getLanguage();
final PsiFile finalContainingFile = containingFile;
InjectionProcessor injectionProcessor = new InjectionProcessor(myConfiguration, operands) {
InjectionProcessor injectionProcessor = new InjectionProcessor(myConfiguration, mySupport, operands) {
@Override
protected void processInjection(Language language,
List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list,
@@ -162,7 +162,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector {
}
};
if (tempLanguage != null) {
BaseInjection baseInjection = new BaseInjection(LanguageInjectionSupport.JAVA_SUPPORT_ID);
BaseInjection baseInjection = new BaseInjection(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID);
baseInjection.setInjectedLanguageId(tempInjectedLanguage.getID());
injectionProcessor.processInjectionInner(baseInjection, false);
InjectorUtils.putInjectedFileUserData(registrar, LanguageInjectionSupport.TEMPORARY_INJECTED_LANGUAGE, tempInjectedLanguage);
@@ -175,12 +175,14 @@ public class ConcatenationInjector implements ConcatenationAwareInjector {
public static class InjectionProcessor {
private final Configuration myConfiguration;
private final LanguageInjectionSupport mySupport;
private final PsiElement[] myOperands;
private boolean myShouldStop;
private boolean myUnparsable;
public InjectionProcessor(Configuration configuration, PsiElement... operands) {
public InjectionProcessor(Configuration configuration, LanguageInjectionSupport support, PsiElement... operands) {
myConfiguration = configuration;
mySupport = support;
myOperands = operands;
}
@@ -301,11 +303,11 @@ public class ConcatenationInjector implements ConcatenationAwareInjector {
}
private boolean processCommentInjections(PsiVariable owner) {
Ref<PsiComment> causeRef = Ref.create();
Ref<PsiElement> causeRef = Ref.create();
PsiElement anchor = owner.getFirstChild() instanceof PsiComment?
(owner.getModifierList() != null? owner.getModifierList() : owner.getTypeElement()) : owner;
if (anchor == null) return true;
BaseInjection injection = InjectorUtils.findCommentInjection(anchor, LanguageInjectionSupport.JAVA_SUPPORT_ID, causeRef);
BaseInjection injection = mySupport.findCommentInjection(anchor, causeRef);
return injection == null || processCommentInjectionInner(owner, causeRef.get(), injection);
}
@@ -351,7 +353,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector {
final String id = AnnotationUtilEx.calcAnnotationValue(annotations, "value");
final String prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix");
final String suffix = AnnotationUtilEx.calcAnnotationValue(annotations, "suffix");
final BaseInjection injection = new BaseInjection(LanguageInjectionSupport.JAVA_SUPPORT_ID);
final BaseInjection injection = new BaseInjection(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID);
if (prefix != null) injection.setPrefix(prefix);
if (suffix != null) injection.setSuffix(suffix);
if (id != null) injection.setInjectedLanguageId(id);
@@ -61,6 +61,7 @@ import org.intellij.plugins.intelliLang.inject.config.ui.configurables.MethodPar
import org.intellij.plugins.intelliLang.util.ContextComputationProcessor;
import org.intellij.plugins.intelliLang.util.PsiUtilEx;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -75,6 +76,8 @@ import static org.intellij.plugins.intelliLang.inject.config.MethodParameterInje
*/
public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSupport {
@NonNls public static final String JAVA_SUPPORT_ID = "java";
private static boolean isMine(final PsiLanguageInjectionHost psiElement) {
return PsiUtilEx.isStringOrCharacterLiteral(psiElement);
}
@@ -93,6 +96,11 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
return new Configurable[]{new AdvancedSettingsUI(project, configuration)};
}
@Override
public boolean isApplicableTo(PsiLanguageInjectionHost host) {
return host instanceof PsiLiteralExpression;
}
public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) {
if (!isMine(psiElement)) return false;
return doInjectInJava(psiElement.getProject(), psiElement, language.getID());
@@ -105,7 +113,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
final PsiLiteralExpression host = (PsiLiteralExpression)psiElement;
final Project project = host.getProject();
final Configuration configuration = Configuration.getProjectInstance(project);
collectInjections(host, configuration, injectionsMap, annotations);
collectInjections(host, configuration, this, injectionsMap, annotations);
if (injectionsMap.isEmpty() && annotations.isEmpty()) return false;
final ArrayList<BaseInjection> originalInjections = new ArrayList<BaseInjection>(injectionsMap.keySet());
@@ -129,7 +137,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
final PsiLiteralExpression host = (PsiLiteralExpression)psiElement;
final Project project = host.getProject();
final Configuration configuration = Configuration.getProjectInstance(project);
collectInjections(host, configuration, injectionsMap, annotations);
collectInjections(host, configuration, this, injectionsMap, annotations);
if (injectionsMap.isEmpty() || !annotations.isEmpty()) return false;
final BaseInjection originalInjection = injectionsMap.keySet().iterator().next();
@@ -146,7 +154,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
}
private BaseInjection showInjectionUI(final Project project, final MethodParameterInjection methodParameterInjection) {
private static BaseInjection showInjectionUI(final Project project, final MethodParameterInjection methodParameterInjection) {
final AbstractInjectionPanel panel = new MethodParameterPanel(methodParameterInjection, project);
panel.reset();
final DialogBuilder builder = new DialogBuilder(project);
@@ -343,10 +351,12 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
}
}
private static void collectInjections(final PsiLiteralExpression host, final Configuration configuration,
private static void collectInjections(PsiLiteralExpression host,
Configuration configuration,
JavaLanguageInjectionSupport support,
final HashMap<BaseInjection, Pair<PsiMethod, Integer>> injectionsMap,
final ArrayList<PsiElement> annotations) {
new ConcatenationInjector.InjectionProcessor(configuration, host) {
new ConcatenationInjector.InjectionProcessor(configuration, support, host) {
@Override
protected boolean processCommentInjectionInner(PsiVariable owner, PsiElement comment, BaseInjection injection) {
+3 -5
View File
@@ -16,7 +16,6 @@
<extensionPoints>
<extensionPoint name="languageSupport" interface="org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport"/>
<extensionPoint name="injectionConfig" beanClass="org.intellij.plugins.intelliLang.inject.LanguageInjectionConfigBean"/>
<extensionPoint name="referenceInjector" interface="org.intellij.plugins.intelliLang.references.ReferenceInjector"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
@@ -51,11 +50,10 @@
<compileServer.plugin classpath="intellilang-jps-plugin.jar"/>
<psi.referenceContributor implementation="org.intellij.plugins.intelliLang.references.InjectedReferencesContributor"/>
</extensions>
<extensions defaultExtensionNs="org.intellij.intelliLang">
<referenceInjector implementation="org.intellij.plugins.intelliLang.references.FileReferenceInjector"/>
<localInspection implementationClass="org.intellij.plugins.intelliLang.references.InjectedReferencesInspection"
enabledByDefault="true" level="ERROR"
displayName="Injected References" groupBundle="messages.InspectionsBundle" groupKey="inspection.general.tools.group.name"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,5 @@
<html>
<body>
Checks references injected by IntelliLang plugin.
</body>
</html>
@@ -186,14 +186,10 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
@NonNls public static final String COMPONENT_NAME = "LanguageInjectionConfiguration";
// element names
@NonNls private static final String TAG_INJECTION_NAME = "TAGS";
@NonNls private static final String ATTRIBUTE_INJECTION_NAME = "ATTRIBUTES";
@NonNls private static final String PARAMETER_INJECTION_NAME = "PARAMETERS";
@NonNls private static final String INSTRUMENTATION_TYPE_NAME = "INSTRUMENTATION";
@NonNls private static final String LANGUAGE_ANNOTATION_NAME = "LANGUAGE_ANNOTATION";
@NonNls private static final String PATTERN_ANNOTATION_NAME = "PATTERN_ANNOTATION";
@NonNls private static final String SUBST_ANNOTATION_NAME = "SUBST_ANNOTATION";
@NonNls private static final String ENTRY_NAME = "entry";
@NonNls private static final String RESOLVE_REFERENCES = "RESOLVE_REFERENCES";
@NonNls private static final String LOOK_FOR_VAR_ASSIGNMENTS = "LOOK_FOR_VAR_ASSIGNMENTS";
@NonNls private static final String USE_DFA_IF_AVAILABLE = "USE_DFA_IF_AVAILABLE";
@@ -242,7 +238,6 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) {
supports.put(support.getId(), support);
}
loadStateOld(element, supports.get(LanguageInjectionSupport.XML_SUPPORT_ID), supports.get(LanguageInjectionSupport.JAVA_SUPPORT_ID));
for (Element child : element.getChildren("injection")){
final String key = child.getAttributeValue("injector-id");
final LanguageInjectionSupport support = supports.get(key);
@@ -268,31 +263,6 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
return places.length != 0 && result.length == 0? null : result;
}
private void loadStateOld(Element element, final LanguageInjectionSupport xmlSupport, final LanguageInjectionSupport javaSupport) {
if (xmlSupport != null) {
final Element xmlTagMarker = new Element("XmlTagInjection");
myInjections.get(LanguageInjectionSupport.XML_SUPPORT_ID).addAll(readExternal(element.getChild(TAG_INJECTION_NAME), new Factory<BaseInjection>() {
public BaseInjection create() {
return xmlSupport.createInjection(xmlTagMarker);
}
}));
final Element xmlAttributeMarker = new Element("XmlAttributeInjection");
myInjections.get(LanguageInjectionSupport.XML_SUPPORT_ID).addAll(readExternal(element.getChild(ATTRIBUTE_INJECTION_NAME), new Factory<BaseInjection>() {
public BaseInjection create() {
return xmlSupport.createInjection(xmlAttributeMarker);
}
}));
}
if (javaSupport != null) {
final Element javaMethodMarker = new Element("MethodParameterInjection");
myInjections.get(LanguageInjectionSupport.JAVA_SUPPORT_ID).addAll(readExternal(element.getChild(PARAMETER_INJECTION_NAME), new Factory<BaseInjection>() {
public BaseInjection create() {
return javaSupport.createInjection(javaMethodMarker);
}
}));
}
}
private static boolean readBoolean(Element element, String key, boolean defValue) {
final String value = JDOMExternalizerUtil.readField(element, key);
if (value == null) return defValue;
@@ -361,20 +331,6 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
return element;
}
@SuppressWarnings({"unchecked"})
private static <T extends BaseInjection> List<T> readExternal(Element element, Factory<T> factory) {
final List<T> injections = new ArrayList<T>();
if (element != null) {
final List<Element> list = element.getChildren(ENTRY_NAME);
for (Element entry : list) {
final T o = factory.create();
o.loadState(entry);
injections.add(o);
}
}
return injections;
}
public static Configuration getInstance() {
return ServiceManager.getService(Configuration.class);
}
@@ -55,7 +55,7 @@ import org.intellij.plugins.intelliLang.inject.InjectorUtils;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.inject.config.InjectionPlace;
import org.intellij.plugins.intelliLang.references.ReferenceInjector;
import com.intellij.psi.injection.ReferenceInjector;
import org.jdom.Document;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -16,6 +16,7 @@
package org.intellij.plugins.intelliLang.inject;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -25,6 +26,7 @@ import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
@@ -35,6 +37,7 @@ import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.inject.config.ui.BaseInjectionPanel;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -44,7 +47,22 @@ import javax.swing.*;
*/
public abstract class AbstractLanguageInjectionSupport extends LanguageInjectionSupport {
public boolean useDefaultInjector(final PsiElement host) {
@Override
public boolean isApplicableTo(PsiLanguageInjectionHost host) {
return useDefaultInjector(host); // todo temporary plugin compatibility fix. TBR
}
public boolean useDefaultInjector(final PsiLanguageInjectionHost host) {
return false;
}
@Nullable
@Override
public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref<PsiElement> commentRef) {
return InjectorUtils.findCommentInjection(host, "comment", commentRef);
}
public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) {
return false;
}
@@ -1,15 +1,15 @@
package org.intellij.plugins.intelliLang.inject;
import com.intellij.lang.Language;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.psi.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.util.ArrayUtil;
import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -18,29 +18,53 @@ import java.util.List;
*/
public class CommentLanguageInjector implements MultiHostInjector {
private final LanguageInjectionSupport[] mySupports;
private final LanguageInjectionSupport myInjectorSupport = new AbstractLanguageInjectionSupport() {
@NotNull
@Override
public String getId() {
return "comment";
}
@Override
public boolean isApplicableTo(PsiLanguageInjectionHost host) {
return true;
}
@NotNull
@Override
public Class[] getPatternClasses() {
return ArrayUtil.EMPTY_CLASS_ARRAY;
}
};
/** @noinspection UnusedParameters*/
public CommentLanguageInjector(Configuration configuration) {
List<LanguageInjectionSupport> supports = new ArrayList<LanguageInjectionSupport>(InjectorUtils.getActiveInjectionSupports());
supports.add(myInjectorSupport);
mySupports = ArrayUtil.toObjectArray(supports, LanguageInjectionSupport.class);
}
@NotNull
public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
return Collections.singletonList(PsiLanguageInjectionHost.class);
}
public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement context) {
if (!(context instanceof PsiLanguageInjectionHost) || !((PsiLanguageInjectionHost)context).isValidHost()) return;
PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context;
if (!host.isValidHost()) return;
if (context.getClass().getSimpleName().startsWith("XmlAttribute")) return; // no injection in XML attributes, they cannot be commented
ElementManipulator<PsiLanguageInjectionHost> manipulator = ElementManipulators.getManipulator(host);
if (manipulator == null) return;
TextRange rangeInElement = manipulator.getRangeInElement(host);
if (rangeInElement.isEmpty()) return;
PsiElement anchor = rangeInElement.getStartOffset() == 0 ? context.getParent() : context; // handle XmlText
BaseInjection injection = InjectorUtils.findCommentInjection(anchor, "comment", Ref.<PsiComment>create());
//BaseInjection injection = InjectorUtils.findCommentInjection(context, "comment", Ref.<PsiComment>create());
if (injection == null) return;
InjectedLanguage injectedLanguage = InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
Language language = injectedLanguage != null ? injectedLanguage.getLanguage() : null;
if (language != null) {
Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange> info =
Trinity.create(host, injectedLanguage, rangeInElement);
InjectorUtils.registerInjection(language, Collections.singletonList(info), context.getContainingFile(), registrar);
boolean applicableFound = false;
for (LanguageInjectionSupport support : mySupports) {
if (!support.isApplicableTo(host)) continue;
if (support == myInjectorSupport && applicableFound) continue;
applicableFound = true;
BaseInjection injection = support.findCommentInjection(host, null);
if (injection == null) continue;
if (!InjectorUtils.registerInjectionSimple(host, injection, support, registrar)) continue;
return;
}
}
}
@@ -16,11 +16,8 @@
package org.intellij.plugins.intelliLang.inject;
import com.intellij.lang.Language;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.util.ArrayUtil;
@@ -28,7 +25,6 @@ import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -47,30 +43,18 @@ public final class DefaultLanguageInjector implements MultiHostInjector {
return Collections.singletonList(PsiLanguageInjectionHost.class);
}
public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement host) {
public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement context) {
if (!(context instanceof PsiLanguageInjectionHost) || !((PsiLanguageInjectionHost)context).isValidHost()) return;
PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context;
for (LanguageInjectionSupport support : mySupports) {
if (!support.isApplicableTo(host)) continue;
if (!support.useDefaultInjector(host)) continue;
for (BaseInjection injection : myInjectionConfiguration.getInjections(support.getId())) {
if (injection.acceptsPsiElement(host)) {
final Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
if (language == null) continue;
final InjectedLanguage injectedLanguage =
InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
List<TextRange> ranges = injection.getInjectedArea(host);
final List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list =
new ArrayList<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>(ranges.size());
for (TextRange range : ranges) {
list.add(Trinity.create((PsiLanguageInjectionHost)host, injectedLanguage, range));
}
//if (host.getChildren().length > 0) {
// host.putUserData(LanguageInjectionSupport.HAS_UNPARSABLE_FRAGMENTS, Boolean.TRUE);
//}
InjectorUtils.registerInjection(language, list, host.getContainingFile(), registrar);
InjectorUtils.registerSupport(support, true, registrar);
break;
}
if (!injection.acceptsPsiElement(host)) continue;
if (!InjectorUtils.registerInjectionSimple(host, injection, support, registrar)) continue;
return;
}
}
}
@@ -15,39 +15,66 @@
*/
package org.intellij.plugins.intelliLang.inject;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.Language;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiModificationTrackerImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.ColoredListCellRendererWrapper;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.components.JBList;
import com.intellij.util.FileContentUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.references.Injectable;
import com.intellij.psi.injection.Injectable;
import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor;
import com.intellij.psi.injection.ReferenceInjector;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class InjectLanguageAction implements IntentionAction {
@NonNls private static final String INJECT_LANGUAGE_FAMILY = "Inject Language/Reference";
public static final String LAST_INJECTED_LANGUAGE = "LAST_INJECTED_LANGUAGE";
public static List<Injectable> getAllInjectables() {
Language[] languages = InjectedLanguage.getAvailableLanguages();
List<Injectable> list = new ArrayList<Injectable>();
for (Language language : languages) {
list.add(Injectable.fromLanguage(language));
}
list.addAll(Arrays.asList(ReferenceInjector.EXTENSION_POINT_NAME.getExtensions()));
Collections.sort(list);
return list;
}
@NotNull
public String getText() {
@@ -99,18 +126,24 @@ public class InjectLanguageAction implements IntentionAction {
if (defaultFunctionalityWorked(host, injectable.getId())) return;
try {
Language language = injectable.toLanguage();
for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) {
if (support.addInjectionInPlace(injectable, host)) {
((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter();
if (support.isApplicableTo(host) && support.addInjectionInPlace(language, host)) {
return;
}
}
TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(injectable, host);
if (TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(language, host)) {
HintManager.getInstance().showInformationHint(editor, StringUtil.escapeXml(language.getDisplayName()) + " was temporarily injected");
}
}
finally {
if (injectable.getLanguage() != null) { // no need for reference injection
FileContentUtil.reparseFiles(project, Collections.<VirtualFile>emptyList(), true);
}
else {
((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter();
DaemonCodeAnalyzer.getInstance(project).restart();
}
}
}
@@ -119,27 +152,43 @@ public class InjectLanguageAction implements IntentionAction {
}
private static boolean doChooseLanguageToInject(Editor editor, final Processor<Injectable> onChosen) {
final List<Injectable> injectables = Injectable.getAllInjectables();
final List<Injectable> injectables = getAllInjectables();
final JList list = new JBList(injectables);
list.setCellRenderer(new ListCellRendererWrapper<Injectable>() {
list.setCellRenderer(new ColoredListCellRendererWrapper<Injectable>() {
@Override
public void customize(JList list, Injectable language, int index, boolean selected, boolean hasFocus) {
protected void doCustomize(JList list, Injectable language, int index, boolean selected, boolean hasFocus) {
setIcon(language.getIcon());
setText(language.getDisplayName());
append(language.getDisplayName());
String description = language.getAdditionalDescription();
if (description != null) {
append(description, SimpleTextAttributes.GRAYED_ATTRIBUTES);
}
}
});
new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() {
JBPopup popup = new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() {
public void run() {
onChosen.process((Injectable)list.getSelectedValue());
Injectable value = (Injectable)list.getSelectedValue();
onChosen.process(value);
PropertiesComponent.getInstance().setValue(LAST_INJECTED_LANGUAGE, value.getId());
}
}).setFilteringEnabled(new Function<Object, String>() {
@Override
public String fun(Object language) {
return ((Injectable)language).getDisplayName();
}
})
.createPopup().showInBestPositionFor(editor);
}).createPopup();
final String lastInjected = PropertiesComponent.getInstance().getValue(LAST_INJECTED_LANGUAGE);
if (lastInjected != null) {
Injectable injectable = ContainerUtil.find(injectables, new Condition<Injectable>() {
@Override
public boolean value(Injectable injectable) {
return lastInjected.equals(injectable.getId());
}
});
list.setSelectedValue(injectable, true);
}
popup.showInBestPositionFor(editor);
return true;
}
@@ -16,10 +16,8 @@
package org.intellij.plugins.intelliLang.inject;
import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil;
import com.intellij.lang.Language;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
@@ -59,6 +57,32 @@ public class InjectorUtils {
}
public static boolean registerInjectionSimple(@NotNull PsiLanguageInjectionHost host,
@NotNull BaseInjection injection,
@Nullable LanguageInjectionSupport support,
@NotNull MultiHostRegistrar registrar) {
Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
if (language == null) return false;
InjectedLanguage injectedLanguage =
InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
List<TextRange> ranges = injection.getInjectedArea(host);
List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list = ContainerUtil.newArrayListWithExpectedSize(ranges.size());
for (TextRange range : ranges) {
list.add(Trinity.create(host, injectedLanguage, range));
}
//if (host.getChildren().length > 0) {
// host.putUserData(LanguageInjectionSupport.HAS_UNPARSABLE_FRAGMENTS, Boolean.TRUE);
//}
registerInjection(language, list, host.getContainingFile(), registrar);
if (support != null) {
registerSupport(support, true, registrar);
}
return !ranges.isEmpty();
}
public static void registerInjection(Language language, List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list, PsiFile containingFile, MultiHostRegistrar registrar) {
// if language isn't injected when length == 0, subsequent edits will not cause the language to be injected as well.
// Maybe IDEA core is caching a bit too aggressively here?
@@ -196,12 +220,12 @@ public class InjectorUtils {
return true;
}
public static BaseInjection findCommentInjection(PsiElement context, final String supportId, final Ref<PsiComment> causeRef) {
public static BaseInjection findCommentInjection(PsiElement context, final String supportId, final Ref<PsiElement> causeRef) {
return findNearestComment(context, new NullableFunction<PsiComment, BaseInjection>() {
@Nullable
@Override
public BaseInjection fun(PsiComment comment) {
causeRef.set(comment);
if (causeRef != null) causeRef.set(comment);
String text = ElementManipulators.getValueText(comment).trim();
return detectInjectionFromText(supportId, text);
}
@@ -22,16 +22,17 @@ import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.ui.SimpleColoredText;
import com.intellij.util.Consumer;
import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.references.Injectable;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Gregory.Shrago
@@ -45,9 +46,6 @@ public abstract class LanguageInjectionSupport {
public static Key<LanguageInjectionSupport> INJECTOR_SUPPORT = Key.create("INJECTOR_SUPPORT");
public static Key<LanguageInjectionSupport> SETTINGS_EDITOR = Key.create("SETTINGS_EDITOR");
@NonNls public static final String XML_SUPPORT_ID = "xml";
@NonNls public static final String JAVA_SUPPORT_ID = "java";
@NonNls
@NotNull
public abstract String getId();
@@ -55,24 +53,14 @@ public abstract class LanguageInjectionSupport {
@NotNull
public abstract Class[] getPatternClasses();
public abstract boolean useDefaultInjector(final PsiElement host);
public abstract boolean isApplicableTo(PsiLanguageInjectionHost host);
public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) {
return addInjectionInPlace(language.getID(), psiElement);
}
public abstract boolean useDefaultInjector(PsiLanguageInjectionHost host);
public boolean addInjectionInPlace(final String id, final PsiLanguageInjectionHost psiElement) {
return false;
}
@Nullable
public abstract BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref<PsiElement> commentRef);
public final boolean addInjectionInPlace(final Injectable injectable, final PsiLanguageInjectionHost psiElement) {
if (injectable.getLanguage() == null) {
return addInjectionInPlace(injectable.getId(), psiElement);
}
else {
return addInjectionInPlace(injectable.getLanguage(), psiElement);
}
}
public abstract boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement);
public abstract boolean removeInjectionInPlace(final PsiLanguageInjectionHost psiElement);
@@ -47,18 +47,20 @@ public class TemporaryPlacesInjector implements MultiHostInjector {
}
public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement context) {
if (!(context instanceof PsiLanguageInjectionHost) || !((PsiLanguageInjectionHost)context).isValidHost()) return;
PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context;
PsiFile containingFile = context.getContainingFile();
InjectedLanguage injectedLanguage = myRegistry.getLanguageFor(host, containingFile);
Language language = injectedLanguage != null ? injectedLanguage.getLanguage() : null;
if (language != null) {
final ElementManipulator<PsiLanguageInjectionHost> manipulator = ElementManipulators.getManipulator(host);
if (manipulator == null) return;
List<Trinity<PsiLanguageInjectionHost, InjectedLanguage,TextRange>> trinities =
Collections.singletonList(Trinity.create(host, injectedLanguage, manipulator.getRangeInElement(host)));
InjectorUtils.registerInjection(language, trinities, containingFile, registrar);
InjectorUtils.registerSupport(myRegistry.getLanguageInjectionSupport(), false, registrar);
}
if (language == null) return;
final ElementManipulator<PsiLanguageInjectionHost> manipulator = ElementManipulators.getManipulator(host);
if (manipulator == null) return;
List<Trinity<PsiLanguageInjectionHost, InjectedLanguage,TextRange>> trinities =
Collections.singletonList(Trinity.create(host, injectedLanguage, manipulator.getRangeInElement(host)));
InjectorUtils.registerInjection(language, trinities, containingFile, registrar);
InjectorUtils.registerSupport(myRegistry.getLanguageInjectionSupport(), false, registrar);
}
}
@@ -50,6 +50,11 @@ public class TemporaryPlacesRegistry {
return "temp";
}
@Override
public boolean isApplicableTo(PsiLanguageInjectionHost host) {
return true;
}
@NotNull
@Override
public Class[] getPatternClasses() {
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.injection.ReferenceInjector;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
@@ -44,6 +45,11 @@ public class FileReferenceInjector extends ReferenceInjector {
@Override
public PsiReference[] getReferences(@NotNull PsiElement element, @NotNull ProcessingContext context, @NotNull TextRange range) {
String text = range.substring(element.getText());
return new FileReferenceSet(text, element, range.getStartOffset(), null, true).getAllReferences();
return new FileReferenceSet(text, element, range.getStartOffset(), null, true) {
@Override
protected boolean isSoft() {
return true;
}
}.getAllReferences();
}
}
@@ -19,11 +19,14 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.*;
import com.intellij.psi.injection.ReferenceInjector;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
import org.intellij.plugins.intelliLang.inject.InjectorUtils;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
import org.intellij.plugins.intelliLang.inject.TemporaryPlacesRegistry;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,10 +40,15 @@ import java.util.List;
*/
public class InjectedReferencesContributor extends PsiReferenceContributor {
private static final Key<ReferenceInjector> INJECTED_REFERENCE = Key.create("injected reference");
private static final Key<PsiReference[]> INJECTED_REFERENCES = Key.create("injected references");
public static boolean isInjected(@Nullable PsiReference reference) {
return reference != null && reference.getElement().getUserData(INJECTED_REFERENCE) != null;
return reference != null && reference.getElement().getUserData(INJECTED_REFERENCES) != null;
}
@Nullable
public static PsiReference[] getInjectedReferences(PsiElement element) {
return element.getUserData(INJECTED_REFERENCES);
}
@Override
@@ -49,24 +57,38 @@ public class InjectedReferencesContributor extends PsiReferenceContributor {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
element.putUserData(INJECTED_REFERENCE, null);
ReferenceInjector[] extensions = ReferenceInjector.EXTENSION_POINT_NAME.getExtensions();
PsiReference[] references = new PsiReference[0];
Configuration configuration = Configuration.getProjectInstance(element.getProject());
for (ReferenceInjector extension : extensions) {
Collection<BaseInjection> injections = configuration.getInjectionsByLanguageId(extension.getId());
boolean injected = false;
for (ReferenceInjector injector : extensions) {
Collection<BaseInjection> injections = configuration.getInjectionsByLanguageId(injector.getId());
for (BaseInjection injection : injections) {
if (injection.acceptForReference(element)) {
element.putUserData(INJECTED_REFERENCE, extension);
injected = true;
LanguageInjectionSupport support = InjectorUtils.findInjectionSupport(injection.getSupportId());
element.putUserData(LanguageInjectionSupport.INJECTOR_SUPPORT, support);
List<TextRange> area = injection.getInjectedArea(element);
for (TextRange range : area) {
references = ArrayUtil.mergeArrays(references, extension.getReferences(element, context, range));
references = ArrayUtil.mergeArrays(references, injector.getReferences(element, context, range));
}
}
}
}
if (element instanceof PsiLanguageInjectionHost) {
TemporaryPlacesRegistry registry = TemporaryPlacesRegistry.getInstance(element.getProject());
InjectedLanguage language = registry.getLanguageFor((PsiLanguageInjectionHost)element, element.getContainingFile());
if (language != null) {
ReferenceInjector injector = ReferenceInjector.findById(language.getID());
if (injector != null) {
injected = true;
element.putUserData(LanguageInjectionSupport.INJECTOR_SUPPORT, registry.getLanguageInjectionSupport());
TextRange range = ElementManipulators.getValueTextRange(element);
references = ArrayUtil.mergeArrays(references, injector.getReferences(element, context, range));
}
}
}
element.putUserData(INJECTED_REFERENCES, injected ? references : null);
return references;
}
});
@@ -0,0 +1,51 @@
/*
* Copyright 2000-2013 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 org.intellij.plugins.intelliLang.references;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Avdeev
* Date: 05.08.13
*/
public class InjectedReferencesInspection extends LocalInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new PsiElementVisitor() {
@Override
public void visitElement(PsiElement element) {
PsiReference[] injected = InjectedReferencesContributor.getInjectedReferences(element);
if (injected != null) {
for (PsiReference reference : injected) {
if (reference.resolve() == null) {
holder.registerProblem(reference);
}
}
}
super.visitElement(element);
}
};
}
}
@@ -23,7 +23,7 @@ import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
import org.intellij.plugins.intelliLang.inject.xml.XmlLanguageInjectionSupport;
import org.intellij.plugins.intelliLang.util.StringMatcher;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
@@ -60,7 +60,7 @@ public class AbstractTagInjection extends BaseInjection {
private boolean myApplyToSubTagTexts;
public AbstractTagInjection() {
super(LanguageInjectionSupport.XML_SUPPORT_ID);
super(XmlLanguageInjectionSupport.XML_SUPPORT_ID);
}
@NotNull
@@ -16,6 +16,7 @@
package org.intellij.plugins.intelliLang.inject.xml;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.options.Configurable;
@@ -23,15 +24,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlText;
import com.intellij.psi.xml.*;
import com.intellij.util.Consumer;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.ContainerUtil;
@@ -47,6 +46,7 @@ import org.intellij.plugins.intelliLang.inject.config.ui.XmlTagPanel;
import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlAttributeInjectionConfigurable;
import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlTagInjectionConfigurable;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,6 +59,8 @@ import java.util.Collections;
*/
public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSupport {
@NonNls public static final String XML_SUPPORT_ID = "xml";
private static boolean isMine(final PsiLanguageInjectionHost host) {
if (host instanceof XmlAttributeValue) {
final PsiElement p = host.getParent();
@@ -84,12 +86,22 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
return new Class[] {XmlPatterns.class};
}
public boolean useDefaultInjector(final PsiElement host) {
return false;
@Override
public boolean isApplicableTo(PsiLanguageInjectionHost host) {
return host instanceof XmlElement;
}
public boolean addInjectionInPlace(final String id, final PsiLanguageInjectionHost psiElement) {
@Nullable
@Override
public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref<PsiElement> commentRef) {
if (host instanceof XmlAttributeValue) return null;
return InjectorUtils.findCommentInjection(host instanceof XmlText ? host.getParent() : host, getId(), commentRef);
}
@Override
public boolean addInjectionInPlace(Language language, final PsiLanguageInjectionHost psiElement) {
if (!isMine(psiElement)) return false;
String id = language.getID();
if (psiElement instanceof XmlAttributeValue) {
return doInjectInAttributeValue((XmlAttributeValue)psiElement, id);
}

Some files were not shown because too many files have changed in this diff Show More