mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 22:17:05 +07:00
565 lines
19 KiB
Java
565 lines
19 KiB
Java
/*
|
|
* 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.jetbrains.python;
|
|
|
|
import com.intellij.psi.PsiElement;
|
|
import com.intellij.psi.PsiPolyVariantReference;
|
|
import com.intellij.psi.PsiReference;
|
|
import com.intellij.psi.ResolveResult;
|
|
import com.intellij.psi.util.PsiTreeUtil;
|
|
import com.intellij.testFramework.UsefulTestCase;
|
|
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
|
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
|
import com.jetbrains.python.fixtures.PyResolveTestCase;
|
|
import com.jetbrains.python.psi.*;
|
|
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
|
import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
|
|
import com.jetbrains.python.psi.resolve.ImportedResolveResult;
|
|
import junit.framework.Assert;
|
|
|
|
public class PyResolveTest extends PyResolveTestCase {
|
|
@Override
|
|
protected PsiElement doResolve() {
|
|
final PsiReference ref = findReferenceByMarker();
|
|
return ref.resolve();
|
|
}
|
|
|
|
private PsiReference findReferenceByMarker() {
|
|
myFixture.configureByFile("resolve/" + getTestName(false) + ".py");
|
|
return PyResolveTestCase.findReferenceByMarker(myFixture.getFile());
|
|
}
|
|
|
|
protected PsiElement resolve() {
|
|
PsiReference ref = configureByFile("resolve/" + getTestName(false) + ".py");
|
|
// if need be: PythonLanguageLevelPusher.setForcedLanguageLevel(project, LanguageLevel.PYTHON26);
|
|
return ref.resolve();
|
|
}
|
|
|
|
private ResolveResult[] multiResolve() {
|
|
PsiReference ref = findReferenceByMarker();
|
|
Assert.assertTrue(ref instanceof PsiPolyVariantReference);
|
|
return ((PsiPolyVariantReference)ref).multiResolve(false);
|
|
}
|
|
|
|
public void testClass() {
|
|
assertResolvesTo(PyClass.class, "Test");
|
|
}
|
|
|
|
public void testFunc() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyFunction);
|
|
}
|
|
|
|
public void testToConstructor() {
|
|
PsiElement target = resolve();
|
|
Assert.assertTrue(target instanceof PyFunction);
|
|
Assert.assertEquals(PyNames.INIT, ((PyFunction)target).getName());
|
|
}
|
|
|
|
public void testToConstructorInherited() {
|
|
ResolveResult[] targets = multiResolve();
|
|
Assert.assertEquals(2, targets.length); // to class, to init
|
|
PsiElement elt;
|
|
// class
|
|
elt = targets[0].getElement();
|
|
Assert.assertTrue(elt instanceof PyClass);
|
|
Assert.assertEquals("Bar", ((PyClass)elt).getName());
|
|
// init
|
|
elt = targets[1].getElement();
|
|
Assert.assertTrue(elt instanceof PyFunction);
|
|
PyFunction fun = (PyFunction)elt;
|
|
Assert.assertEquals(PyNames.INIT, fun.getName());
|
|
PyClass cls = fun.getContainingClass();
|
|
Assert.assertNotNull(cls);
|
|
Assert.assertEquals("Foo", cls.getName());
|
|
}
|
|
|
|
// NOTE: maybe this test does not belong exactly here; still it's the best place currently.
|
|
public void testComplexCallee() {
|
|
PsiElement targetElement = resolve();
|
|
PyExpression assigned = ((PyAssignmentStatement)targetElement.getContext()).getAssignedValue();
|
|
Assert.assertTrue(assigned instanceof PyCallExpression);
|
|
PsiElement callee = ((PyCallExpression)assigned).getCallee();
|
|
Assert.assertTrue(callee instanceof PySubscriptionExpression);
|
|
}
|
|
|
|
public void testVar() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testDefaultInClass() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertNotNull(targetElement);
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertEquals("FOO", ((PyTargetExpression)targetElement).getName());
|
|
}
|
|
|
|
public void testQualifiedFunc() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyFunction);
|
|
}
|
|
|
|
public void testQualifiedVar() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testQualifiedTarget() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testQualifiedFalseTarget() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertNull(targetElement);
|
|
}
|
|
|
|
public void testInnerFuncVar() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testTupleInComprh() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testForStatement() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testExceptClause() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testLookAhead() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testLookAheadCapped() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testTryExceptElse() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testGlobal() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
|
|
}
|
|
|
|
public void testGlobalDefinedLocally() {
|
|
final PsiElement element = resolve();
|
|
UsefulTestCase.assertInstanceOf(element, PyTargetExpression.class);
|
|
final PsiElement parent = element.getParent();
|
|
UsefulTestCase.assertInstanceOf(parent, PyAssignmentStatement.class);
|
|
}
|
|
|
|
public void testLambda() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyNamedParameter);
|
|
}
|
|
|
|
public void testLambdaParameterOutside() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testSuperField() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testFieldInCondition() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testMultipleFields() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testClassPeerMembers() {
|
|
PsiElement target = resolve();
|
|
Assert.assertTrue(target instanceof PyFunction);
|
|
}
|
|
|
|
public void testTuple() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
|
|
}
|
|
|
|
public void testMultiTarget() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
|
|
}
|
|
|
|
public void testMultiTargetTuple() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertNotNull(PsiTreeUtil.getParentOfType(targetElement, PyAssignmentStatement.class)); // it's deep in a tuple
|
|
}
|
|
|
|
public void testWithStatement() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyWithItem);
|
|
}
|
|
|
|
public void testTupleInExcept() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(PsiTreeUtil.getParentOfType(targetElement, PyExceptPart.class) != null);
|
|
}
|
|
|
|
|
|
public void testDocStringClass() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyStringLiteralExpression);
|
|
Assert.assertEquals("Docstring of class Foo", ((PyStringLiteralExpression)targetElement).getStringValue());
|
|
}
|
|
|
|
public void testDocStringInstance() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyStringLiteralExpression);
|
|
Assert.assertEquals("Docstring of class Foo", ((PyStringLiteralExpression)targetElement).getStringValue());
|
|
}
|
|
|
|
public void testDocStringFunction() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyStringLiteralExpression);
|
|
Assert.assertEquals("Docstring of function bar", ((PyStringLiteralExpression)targetElement).getStringValue());
|
|
}
|
|
|
|
public void testDocStringInvalid() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertNull(targetElement);
|
|
}
|
|
|
|
public void testFieldNotInInit() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
}
|
|
|
|
public void testClassIsNotMemberOfItself() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertNull(targetElement);
|
|
}
|
|
|
|
public void testSuper() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyFunction);
|
|
Assert.assertEquals("A", ((PyFunction)targetElement).getContainingClass().getName());
|
|
}
|
|
|
|
public void testSuperPy3k() { // PY-1330
|
|
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON30);
|
|
try {
|
|
final PyFunction pyFunction = assertResolvesTo(PyFunction.class, "foo");
|
|
Assert.assertEquals("A", pyFunction.getContainingClass().getName());
|
|
}
|
|
finally {
|
|
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
|
|
}
|
|
}
|
|
|
|
public void testStackOverflow() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertNull(targetElement);
|
|
}
|
|
|
|
public void testProperty() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyFunction);
|
|
Assert.assertEquals("set_full_name", ((PyFunction)targetElement).getName());
|
|
}
|
|
|
|
public void testLambdaWithParens() { // PY-882
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyParameter);
|
|
}
|
|
|
|
public void testTextBasedResolve() {
|
|
ResolveResult[] resolveResults = multiResolve();
|
|
Assert.assertEquals(1, resolveResults.length);
|
|
Assert.assertTrue(resolveResults[0].getElement() instanceof PyFunction);
|
|
}
|
|
|
|
public void testClassPrivateInClass() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
|
|
}
|
|
|
|
public void testClassPrivateInMethod() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
|
|
}
|
|
|
|
public void testClassPrivateInMethodNested() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
|
|
}
|
|
|
|
public void testClassPrivateInherited() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertTrue(targetElement instanceof PyTargetExpression);
|
|
Assert.assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
|
|
}
|
|
|
|
public void testClassPrivateOutsideClass() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertNull(targetElement);
|
|
}
|
|
|
|
public void testClassPrivateOutsideInstance() {
|
|
PsiElement targetElement = resolve();
|
|
Assert.assertNull(targetElement);
|
|
}
|
|
|
|
public void testClassNameEqualsMethodName() {
|
|
PsiElement targetElement = resolve();
|
|
UsefulTestCase.assertInstanceOf(targetElement, PyFunction.class);
|
|
}
|
|
|
|
public void testUnresolvedImport() {
|
|
final ResolveResult[] results = multiResolve();
|
|
Assert.assertEquals(1, results.length);
|
|
UsefulTestCase.assertInstanceOf(results[0], ImportedResolveResult.class);
|
|
ImportedResolveResult result = (ImportedResolveResult) results [0];
|
|
Assert.assertNull(result.getElement());
|
|
}
|
|
|
|
public void testIsInstance() { // PY-1133
|
|
PsiElement targetElement = resolve();
|
|
UsefulTestCase.assertInstanceOf(targetElement, PyNamedParameter.class);
|
|
}
|
|
|
|
public void testListComprehension() { // PY-1143
|
|
PsiElement targetElement = resolve();
|
|
UsefulTestCase.assertInstanceOf(targetElement, PyTargetExpression.class);
|
|
}
|
|
|
|
public void testSuperMetaClass() {
|
|
assertResolvesTo(PyFunction.class, "foo");
|
|
}
|
|
|
|
public void testSuperDunderClass() { // PY-1190
|
|
assertResolvesTo(PyFunction.class, "foo");
|
|
}
|
|
|
|
public void testSuperTwoClasses() { // PY-2133
|
|
final PyFunction pyFunction = assertResolvesTo(PyFunction.class, "my_call");
|
|
Assert.assertEquals("Base2", pyFunction.getContainingClass().getName());
|
|
}
|
|
|
|
public void testLambdaDefaultParameter() {
|
|
final PsiElement element = doResolve();
|
|
UsefulTestCase.assertInstanceOf(element, PyTargetExpression.class);
|
|
Assert.assertTrue(element.getParent() instanceof PySetCompExpression);
|
|
}
|
|
|
|
public void testListAssignment() {
|
|
final PsiElement element = doResolve();
|
|
UsefulTestCase.assertInstanceOf(element, PyTargetExpression.class);
|
|
}
|
|
|
|
public void testStarUnpacking() { // PY-1459
|
|
assertResolvesTo(LanguageLevel.PYTHON30, PyTargetExpression.class, "heads");
|
|
}
|
|
|
|
public void testStarUnpackingInLoop() { // PY-1525
|
|
assertResolvesTo(LanguageLevel.PYTHON30, PyTargetExpression.class, "bbb");
|
|
}
|
|
|
|
public void testBuiltinVsClassMember() { // PY-1654
|
|
final PyFunction pyFunction = assertResolvesTo(PyFunction.class, "eval");
|
|
Assert.assertEquals("__builtin__.py", pyFunction.getContainingFile().getName());
|
|
}
|
|
|
|
public void testLambdaToClass() { // PY-2182
|
|
assertResolvesTo(PyClass.class, "TestTwo");
|
|
}
|
|
|
|
public void testImportInTryExcept() { // PY-2197
|
|
assertResolvesTo(PyFile.class, "sys.py");
|
|
}
|
|
|
|
public void testModuleToBuiltins() {
|
|
final PsiElement element = doResolve();
|
|
Assert.assertNull(element);
|
|
}
|
|
|
|
public void testWithParentheses() {
|
|
assertResolvesTo(LanguageLevel.PYTHON27, PyTargetExpression.class, "MockClass1");
|
|
}
|
|
|
|
public void testPrivateInsideModule() { // PY-2618
|
|
assertResolvesTo(PyClass.class, "__VeryPrivate");
|
|
}
|
|
|
|
public void testRedeclaredInstanceVar() { // PY-2740
|
|
assertResolvesTo(PyFunction.class, "jobsDoneCount");
|
|
}
|
|
|
|
public void testNoResolveIntoGenerator() { // PY-3030
|
|
PyTargetExpression expr = assertResolvesTo(PyTargetExpression.class, "foo");
|
|
Assert.assertEquals("foo = 1", expr.getParent().getText());
|
|
}
|
|
|
|
public void testResolveInGenerator() {
|
|
assertResolvesTo(PyTargetExpression.class, "foo");
|
|
}
|
|
|
|
public void testNestedListComp() { // PY-3068
|
|
assertResolvesTo(PyTargetExpression.class, "yy");
|
|
}
|
|
|
|
public void testSuperclassResolveScope() { // PY-3554
|
|
assertResolvesTo(PyClass.class, "date", "datetime.py");
|
|
}
|
|
|
|
public void testDontResolveTargetToBuiltins() { // PY-4256
|
|
assertResolvesTo(PyTargetExpression.class, "str");
|
|
}
|
|
|
|
public void testKeywordArgument() {
|
|
assertResolvesTo(PyNamedParameter.class, "bar");
|
|
}
|
|
|
|
public void testImplicitResolveInstanceAttribute() {
|
|
ResolveResult[] resolveResults = multiResolve();
|
|
Assert.assertEquals(1, resolveResults.length);
|
|
final PsiElement psiElement = resolveResults[0].getElement();
|
|
Assert.assertTrue(psiElement instanceof PyTargetExpression && "xyzzy".equals(((PyTargetExpression)psiElement).getName()));
|
|
}
|
|
|
|
public void testAttributeAssignedNearby() {
|
|
assertResolvesTo(PyTargetExpression.class, "xyzzy");
|
|
}
|
|
|
|
public void testPreviousTarget() {
|
|
PsiElement resolved = resolve();
|
|
UsefulTestCase.assertInstanceOf(resolved, PyTargetExpression.class);
|
|
PyTargetExpression target = (PyTargetExpression)resolved;
|
|
PyExpression value = target.findAssignedValue();
|
|
UsefulTestCase.assertInstanceOf(value, PyNumericLiteralExpression.class);
|
|
}
|
|
|
|
public void testMetaclass() {
|
|
final PyFunction function = assertResolvesTo(PyFunction.class, "getStore");
|
|
Assert.assertEquals("PluginMetaclass", function.getContainingClass().getName());
|
|
}
|
|
|
|
// PY-6083
|
|
public void testLambdaParameterInDecorator() {
|
|
assertResolvesTo(PyNamedParameter.class, "xx");
|
|
}
|
|
|
|
// PY-6435
|
|
public void testLambdaParameterInDefaultValue() {
|
|
assertResolvesTo(PyNamedParameter.class, "xx");
|
|
}
|
|
|
|
// PY-6540
|
|
public void testClassRedefinedField() {
|
|
assertResolvesTo(PyClass.class, "Foo");
|
|
}
|
|
|
|
public void testKWArg() {
|
|
assertResolvesTo(PyClass.class, "timedelta");
|
|
}
|
|
|
|
public void testShadowingTargetExpression() {
|
|
assertResolvesTo(PyTargetExpression.class, "lab");
|
|
}
|
|
|
|
public void testReferenceInDocstring() {
|
|
assertResolvesTo(PyClass.class, "datetime");
|
|
}
|
|
|
|
// PY-7541
|
|
public void testLoopToUpperReassignment() {
|
|
final PsiReference ref = findReferenceByMarker();
|
|
final PsiElement source = ref.getElement();
|
|
final PsiElement target = ref.resolve();
|
|
Assert.assertNotNull(target);
|
|
Assert.assertTrue(source != target);
|
|
Assert.assertTrue(PyPsiUtils.isBefore(target, source));
|
|
}
|
|
|
|
// PY-7541
|
|
public void testLoopToLowerReassignment() {
|
|
final PsiReference ref = findReferenceByMarker();
|
|
final PsiElement source = ref.getElement();
|
|
final PsiElement target = ref.resolve();
|
|
Assert.assertNotNull(target);
|
|
Assert.assertTrue(source == target);
|
|
}
|
|
|
|
// PY-7970
|
|
public void testAugmentedAssignment() {
|
|
assertResolvesTo(PyTargetExpression.class, "foo");
|
|
}
|
|
|
|
// PY-7970
|
|
public void testAugmentedAfterAugmented() {
|
|
final PsiReference ref = findReferenceByMarker();
|
|
final PsiElement source = ref.getElement();
|
|
final PsiElement resolved = ref.resolve();
|
|
UsefulTestCase.assertInstanceOf(resolved, PyReferenceExpression.class);
|
|
Assert.assertNotSame(resolved, source);
|
|
final PyReferenceExpression res = (PyReferenceExpression)resolved;
|
|
Assert.assertNotNull(res);
|
|
Assert.assertEquals("foo", res.getName());
|
|
UsefulTestCase.assertInstanceOf(res.getParent(), PyAugAssignmentStatement.class);
|
|
}
|
|
|
|
public void testGeneratorShadowing() { // PY-8725
|
|
assertResolvesTo(PyFunction.class, "_");
|
|
}
|
|
|
|
// PY-6805
|
|
public void testAttributeDefinedInNew() {
|
|
final PsiElement resolved = resolve();
|
|
UsefulTestCase.assertInstanceOf(resolved, PyTargetExpression.class);
|
|
final PyTargetExpression target = (PyTargetExpression)resolved;
|
|
Assert.assertEquals("foo", target.getName());
|
|
final ScopeOwner owner = ScopeUtil.getScopeOwner(target);
|
|
Assert.assertNotNull(owner);
|
|
UsefulTestCase.assertInstanceOf(owner, PyFunction.class);
|
|
Assert.assertEquals("__new__", owner.getName());
|
|
}
|
|
|
|
public void testPreferInitForAttributes() { // PY-9228
|
|
PyTargetExpression xyzzy = assertResolvesTo(PyTargetExpression.class, "xyzzy");
|
|
assertEquals("__init__", PsiTreeUtil.getParentOfType(xyzzy, PyFunction.class).getName());
|
|
}
|
|
}
|