StreamChain (@NotNull List<PsiMethodCallExpression> streamExpressions, @NotNull PsiElement context) { final PsiMethodCallExpression firstCall = streamExpressions.get(0); final PsiExpression qualifierExpression = firstCall.getMethodExpression().getQualifierExpression(); final PsiType qualifierType = qualifierExpression == null ? null : qualifierExpression.getType(); final GenericType typeAfterQualifier = qualifierType == null ? getGenericTypeOfThis(qualifierExpression) : JavaTypes.INSTANCE.fromStreamPsiType(qualifierType); final QualifierExpressionImpl qualifier = qualifierExpression == null ? new QualifierExpressionImpl("", TextRange.EMPTY_RANGE, typeAfterQualifier) : new QualifierExpressionImpl(qualifierExpression.getText(), qualifierExpression.getTextRange(), typeAfterQualifier); final List<IntermediateStreamCall> intermediateCalls = createIntermediateCalls(typeAfterQualifier, streamExpressions.subList(0, streamExpressions.size() - 1)); final GenericType typeBefore = intermediateCalls.isEmpty() ? qualifier.getTypeAfter() : intermediateCalls.get(intermediateCalls.size() - 1).getTypeAfter(); final TerminatorStreamCall terminationCall = createTerminationCall(typeBefore, streamExpressions.get(streamExpressions.size() - 1)); return new StreamChainImpl(qualifier, intermediateCalls, terminationCall, context); }