Commit 4a64d651 authored by alexey.afanasiev's avatar alexey.afanasiev
Browse files

IDEA-196685 IDEA 2018.2 freezes on specific editing of build.gradle file

parent b480d7e7
Showing with 142 additions and 102 deletions
+142 -102
/*
* 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.util;
import com.intellij.openapi.Disposable;
......@@ -361,8 +347,8 @@ public class RecursionManager {
}
@TestOnly
public static void assertOnRecursionPrevention(@NotNull Disposable parentDisposable) {
ourAssertOnPrevention = true;
public static void assertOnRecursionPrevention(@NotNull Disposable parentDisposable, boolean enableAssert) {
ourAssertOnPrevention = enableAssert;
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
......@@ -372,4 +358,8 @@ public class RecursionManager {
});
}
@TestOnly
public static void assertOnRecursionPrevention(@NotNull Disposable parentDisposable) {
assertOnRecursionPrevention(parentDisposable, true);
}
}
......@@ -33,6 +33,8 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.plugins.groovy.lang.resolve.processors.inference.InferenceKt.buildTopLevelArgumentTypes;
/**
* @author ilyas
*/
......@@ -196,11 +198,9 @@ public class GrNewExpressionImpl extends GrCallExpressionImpl implements GrNewEx
}
}
PsiType[] types = PsiUtil.getArgumentTypes(ref, true);
PsiType[] types = buildTopLevelArgumentTypes(ref);
if (types != null) {
types = GrInnerClassConstructorUtil.addEnclosingArgIfNeeded(types, this, (PsiClass)classCandidate.getElement());
}
types = GrInnerClassConstructorUtil.addEnclosingArgIfNeeded(types, this, (PsiClass)classCandidate.getElement());
return PsiUtil.getConstructorCandidates(ref, classCandidate, types);
}
......
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.groovy.lang.resolve.delegatesTo;
import com.intellij.openapi.util.text.StringUtil;
......@@ -23,6 +9,7 @@ import com.intellij.psi.util.TypeConversionUtil;
import groovy.lang.Closure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
......@@ -212,6 +199,9 @@ public class DefaultDelegatesToProvider implements GrDelegatesToProvider {
PsiElement context = FromStringHintProcessor.createContext((PsiMethod)element);
PsiType type = JavaPsiFacade.getElementFactory(context.getProject()).createTypeFromText(typeValue, context);
if (result instanceof GroovyMethodResult) {
return ((GroovyMethodResult)result).getSubstitutor(false).substitute(type);
}
return result.getSubstitutor().substitute(type);
}
......
......@@ -9,26 +9,20 @@ import com.intellij.psi.scope.ElementClassHint;
import com.intellij.psi.scope.JavaScopeProcessorEvent;
import com.intellij.psi.scope.NameHint;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyMethodResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrBindingVariable;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.GrResolverProcessor;
......@@ -38,13 +32,15 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.inference.GroovyInfe
import org.jetbrains.plugins.groovy.lang.resolve.processors.inference.GroovyInferenceSessionBuilder;
import org.jetbrains.plugins.groovy.lang.resolve.processors.inference.MethodCandidate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import static org.jetbrains.plugins.groovy.lang.psi.util.PropertyUtilKt.isPropertyName;
import static org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil.isAccessible;
import static org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil.isStaticsOK;
import static org.jetbrains.plugins.groovy.lang.resolve.processors.inference.InferenceKt.getTopLevelTypeCached;
import static org.jetbrains.plugins.groovy.lang.resolve.processors.inference.InferenceKt.*;
public abstract class GroovyResolverProcessor implements PsiScopeProcessor, ElementClassHint, NameHint, DynamicMembersHint {
......@@ -74,7 +70,7 @@ public abstract class GroovyResolverProcessor implements PsiScopeProcessor, Elem
myTypeArguments = ref.getTypeArguments();
if (kinds.contains(GroovyResolveKind.METHOD) || myIsLValue) {
myArgumentTypes = NullableLazyValue.createValue(() -> buildArgumentTypes());
myArgumentTypes = NullableLazyValue.createValue(() -> buildTopLevelArgumentTypes(myRef));
}
else {
myArgumentTypes = NullableLazyValue.createValue(() -> null);
......@@ -196,7 +192,7 @@ public abstract class GroovyResolverProcessor implements PsiScopeProcessor, Elem
final PsiSubstitutor siteSubstitutor = updateSubst(myRef.getTypeArguments(), method.getTypeParameters(), substitutor);
GrExpression qualifierExpression = myRef.getQualifierExpression();
Argument qualifierConstraint = buildQualifier(state, qualifierExpression);
List<Argument> argumentConstraints = buildArguments();
List<Argument> argumentConstraints = buildArguments(myRef);
if (method instanceof GrGdkMethod) {
ArrayList<Argument> arguments = new ArrayList<>();
......@@ -225,46 +221,8 @@ public abstract class GroovyResolverProcessor implements PsiScopeProcessor, Elem
return new Argument(resolvedThis != null ? resolvedThis : type, null);
}
@NotNull
private List<Argument> buildArguments() {
PsiElement parent = myRef.getParent();
if (parent instanceof GrCall) {
List<Argument> result = new ArrayList<>();
GrCall call = (GrCall)parent;
GrNamedArgument[] namedArgs = call.getNamedArguments();
GrExpression[] expressions = call.getExpressionArguments();
GrClosableBlock[] closures = call.getClosureArguments();
if (namedArgs.length > 0) {
GrNamedArgument context = namedArgs[0];
result.add(new Argument(GrMapType.createFromNamedArgs(context, namedArgs), null));
}
GrExpression[] argExp = ArrayUtil.mergeArrays(expressions, closures);
List<Argument> constraints = Arrays.stream(argExp).map((exp) -> new Argument(null, exp)).collect(Collectors.toList());
result.addAll(constraints);
return result;
}
PsiType[] argumentTypes = PsiUtil.getArgumentTypes(myRef, false, null);
if (argumentTypes == null) return Collections.emptyList();
return Arrays.stream(argumentTypes).map((t) -> new Argument(t, null)).collect(Collectors.toList());
}
@NotNull
private PsiType[] buildArgumentTypes() {
return buildArguments().stream().map(it -> {
if (it.getExpression() != null) {
return getTopLevelTypeCached(it.getExpression());
} else {
if (it.getType() instanceof GrMapType) {
return TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_UTIL_MAP, myRef);
}
return it.getType();
}
}).toArray(PsiType[]::new);
}
@NotNull
private static PsiSubstitutor updateSubst(@NotNull PsiType[] arguments,
......
......@@ -10,6 +10,7 @@ import com.intellij.psi.util.TypeConversionUtil
import com.intellij.util.ArrayUtil
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable
......@@ -21,7 +22,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil
class GroovyInferenceSessionBuilder(val ref: GrReferenceExpression, val candidate: MethodCandidate) {
......@@ -111,18 +111,19 @@ class GroovyInferenceSessionBuilder(val ref: GrReferenceExpression, val candidat
else if (parent is GrAssignmentExpression && call == parent.rValue) {
val lValue = PsiUtil.skipParentheses(parent.lValue, false)
return if (lValue is GrExpression && lValue !is GrIndexProperty) lValue.nominalType else null
} else if (parent is GrArgumentList && gparent is GrNewExpression) { // TODO: fix with moving constructor resolve to new API
val resolveResult = gparent.advancedResolve()
val parameters = GrClosureSignatureUtil.mapArgumentsToParameters(
resolveResult,
gparent,
false,
true,
gparent.namedArguments,
gparent.expressionArguments,
gparent.closureArguments)
return parameters?.get(call)?.second
} else if (parent is GrVariable) {
}
else if (parent is GrArgumentList && gparent is GrNewExpression) { // TODO: fix with moving constructor resolve to new API
with(gparent) {
val resolveResult = advancedResolve()
if (resolveResult is GroovyMethodResult) {
val methodCandidate = MethodCandidate(resolveResult.element, resolveResult.getSubstitutor(false), null,
buildArguments(referenceElement!!), call)
return methodCandidate.argumentMapping[Argument(null, call)]?.second
}
}
return null
}
else if (parent is GrVariable) {
return parent.declaredType
}
return null
......
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.groovy.lang.resolve.processors.inference
import com.intellij.psi.CommonClassNames
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiType
import com.intellij.util.ArrayUtil
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil
import java.util.*
fun getTopLevelType(expression: GrExpression): PsiType? {
if (expression is GrMethodCall) {
val resolved = expression.advancedResolve()
(resolved as? GroovyMethodResult)?.candidate?.let {
val session = GroovyInferenceSessionBuilder(expression.invokedExpression as GrReferenceExpression, it)
.resolveMode(false)
.build()
val session = GroovyInferenceSessionBuilder(expression.invokedExpression as GrReferenceExpression, it).build()
return session.inferSubst().substitute(PsiUtil.getSmartReturnType(it.method))
}
}
......@@ -33,4 +37,42 @@ fun getTopLevelType(expression: GrExpression): PsiType? {
fun getTopLevelTypeCached(expression: GrExpression): PsiType? {
return GroovyPsiManager.getInstance(expression.project).getTopLevelType(expression)
}
fun buildArguments(place: PsiElement): List<Argument> {
val parent = place as? GrEnumConstant ?: place.parent
if (parent is GrCall) {
val result = ArrayList<Argument>()
val namedArgs = parent.namedArguments
val expressions = parent.expressionArguments
val closures = parent.closureArguments
if (namedArgs.isNotEmpty()) {
val context = namedArgs[0]
result.add(Argument(GrMapType.createFromNamedArgs(context, namedArgs), null))
}
val argExp = ArrayUtil.mergeArrays(expressions, closures)
result.addAll(argExp.map { exp -> Argument(null, exp) })
return result
}
val argumentTypes = PsiUtil.getArgumentTypes(place, false, null) ?: return emptyList()
return argumentTypes.map { t -> Argument(t, null) }
}
fun buildTopLevelArgumentTypes(place: PsiElement): Array<PsiType?> {
return buildArguments(place).map { (type, expression) ->
if (expression != null) {
getTopLevelTypeCached(expression)
}
else {
if (type is GrMapType) {
TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_UTIL_MAP, place)
} else {
type
}
}
}.toTypedArray()
}
\ No newline at end of file
......@@ -238,6 +238,31 @@ class SomeClass {
measureHighlighting(text, 14_000)
}
void "test constructor call's"() {
def text = """
class Cl {
Cl(Map<String, Integer> a, Condition<Cl> con, String s) {
}
interface Condition<T> {}
static <T> Condition<T> alwaysFalse() {
return (Condition<T>)null
}
static m() {
${'''new Cl(alwaysFalse(), name: 1, m: 2, new Object().toString(), sad: 12)\n'''*100}
}
}
"""
IdeaTestUtil.startPerformanceTest(getTestName(false), 750, configureAndHighlight(text))
.attempts(20)
.usesAllCPUCores()
.assertTiming()
}
void "test infer only the variable types that are needed"() {
addGdsl '''contribute(currentType(String.name)) {
println 'sleeping'
......
......@@ -2,6 +2,7 @@
package org.jetbrains.plugins.groovy.lang.highlighting
import com.intellij.codeInspection.InspectionProfileEntry
import com.intellij.openapi.util.RecursionManager
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
......@@ -23,6 +24,12 @@ class GrLatestHighlightingTest extends GrHighlightingTestBase {
new MissingReturnInspection()]
}
@Override
void setUp() throws Exception {
super.setUp()
RecursionManager.assertOnRecursionPrevention(myFixture.testRootDisposable)
}
void 'test IDEA-184690'() {
testHighlighting '''\
import groovy.transform.CompileStatic
......@@ -383,6 +390,7 @@ class GoodCodeRed {
}
void 'test recursive generics'() {
RecursionManager.assertOnRecursionPrevention(myFixture.testRootDisposable, false)
testHighlighting '''
import groovy.transform.CompileStatic
......@@ -435,6 +443,32 @@ class Cl {
'''
}
void 'test constructor parameter'() {
testHighlighting '''
import groovy.transform.CompileStatic
@CompileStatic
class Cl {
Cl(Map<String, Integer> a, Condition<Cl> con, String s) {
}
interface Condition<T> {}
static <T> Condition<T> alwaysFalse() {
return (Condition<T>)null
}
static m() {
new Cl(alwaysFalse(), name: 1, m: 2, new Object().toString(), sad: 12)
}
}
'''
}
void 'test call without reference'() {
testHighlighting '''
class E {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment