diff --git a/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralRenameHandler.java b/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralRenameHandler.java index 0a801b10494b..b7fdf465f7ea 100644 --- a/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralRenameHandler.java +++ b/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralRenameHandler.java @@ -34,7 +34,7 @@ import org.jetbrains.annotations.Nullable; */ public class PyMagicLiteralRenameHandler implements RenameHandler { @Override - public boolean isAvailableOnDataContext(DataContext dataContext) { + public boolean isAvailableOnDataContext(final DataContext dataContext) { final Editor editor = CommonDataKeys.EDITOR.getData(dataContext); if (editor == null) { return false; @@ -47,11 +47,7 @@ public class PyMagicLiteralRenameHandler implements RenameHandler { final PsiElement element = getElement(file, editor); - if (element == null || !PyMagicLiteralTools.isMagicLiteral(element)) { - return false; - } - - return true; + return !((element == null) || !PyMagicLiteralTools.isMagicLiteral(element)); } @Nullable diff --git a/python/src/com/jetbrains/python/psi/impl/PyBlockEvaluator.java b/python/src/com/jetbrains/python/psi/impl/PyBlockEvaluator.java deleted file mode 100644 index 36e67a166765..000000000000 --- a/python/src/com/jetbrains/python/psi/impl/PyBlockEvaluator.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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.psi.impl; - -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.util.QualifiedName; -import com.jetbrains.python.PyNames; -import com.jetbrains.python.psi.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -/** - * - * @author yole - */ -public class PyBlockEvaluator { - private final Map myNamespace = new HashMap(); - private final Map> myDeclarations = new HashMap>(); - private final Set myVisitedFiles; - private final Set myDeclarationsToTrack = new HashSet(); - private String myCurrentFilePath; - private Object myReturnValue; - private boolean myEvaluateCollectionItems = true; - - public PyBlockEvaluator() { - myVisitedFiles = new HashSet(); - } - - public PyBlockEvaluator(Set visitedFiles) { - myVisitedFiles = visitedFiles; - } - - public void trackDeclarations(String attrName) { - myDeclarationsToTrack.add(attrName); - } - - public void evaluate(PyElement element) { - VirtualFile vFile = element.getContainingFile().getVirtualFile(); - myCurrentFilePath = vFile != null ? vFile.getPath() : null; - if (myVisitedFiles.contains(element)) { - return; - } - myVisitedFiles.add((PyFile)element.getContainingFile()); - PyElement statementContainer = element instanceof PyFunction ? ((PyFunction) element).getStatementList() : element; - if (statementContainer == null) { - return; - } - statementContainer.acceptChildren(new PyElementVisitor() { - @Override - public void visitPyAssignmentStatement(PyAssignmentStatement node) { - PyExpression expression = node.getLeftHandSideExpression(); - if (expression instanceof PyTargetExpression) { - String name = expression.getName(); - PyExpression value = ((PyTargetExpression)expression).findAssignedValue(); - myNamespace.put(name, prepareEvaluator().evaluate(value)); - if (myDeclarationsToTrack.contains(name)) { - List declarations = new ArrayList(); - PyPsiUtils.sequenceToList(declarations, value); - myDeclarations.put(name, declarations); - } - } - else if (expression instanceof PySubscriptionExpression) { - PyExpression operand = ((PySubscriptionExpression)expression).getOperand(); - PyExpression indexExpression = ((PySubscriptionExpression)expression).getIndexExpression(); - if (operand instanceof PyReferenceExpression && ((PyReferenceExpression)operand).getQualifier() == null) { - Object currentValue = myNamespace.get(((PyReferenceExpression)operand).getReferencedName()); - if (currentValue instanceof Map) { - Object mapKey = prepareEvaluator().evaluate(indexExpression); - if (mapKey != null) { - Object value = myEvaluateCollectionItems ? prepareEvaluator().evaluate(node.getAssignedValue()) : node.getAssignedValue(); - ((Map)currentValue).put(mapKey, value); - } - } - } - } - } - - @Override - public void visitPyAugAssignmentStatement(PyAugAssignmentStatement node) { - PyExpression target = node.getTarget(); - String name = target.getName(); - if (target instanceof PyReferenceExpression && !((PyReferenceExpression)target).isQualified() && name != null) { - Object currentValue = myNamespace.get(name); - if (currentValue != null) { - Object rhs = prepareEvaluator().evaluate(node.getValue()); - myNamespace.put(name, prepareEvaluator().concatenate(currentValue, rhs)); - } - if (myDeclarationsToTrack.contains(name)) { - List declarations = myDeclarations.get(name); - if (declarations != null) { - PyPsiUtils.sequenceToList(declarations, node.getValue()); - } - } - } - } - - @Override - public void visitPyExpressionStatement(PyExpressionStatement node) { - node.getExpression().accept(this); - } - - @Override - public void visitPyCallExpression(PyCallExpression node) { - PyExpression callee = node.getCallee(); - if (callee instanceof PyReferenceExpression) { - PyReferenceExpression calleeRef = (PyReferenceExpression)callee; - PyExpression qualifier = calleeRef.getQualifier(); - if (qualifier instanceof PyReferenceExpression) { - PyReferenceExpression qualifierRef = (PyReferenceExpression)qualifier; - if (!qualifierRef.isQualified()) { - if (PyNames.EXTEND.equals(calleeRef.getReferencedName()) && node.getArguments().length == 1) { - processExtendCall(node, qualifierRef.getReferencedName()); - } - else if (PyNames.UPDATE.equals(calleeRef.getReferencedName()) && node.getArguments().length == 1) { - processUpdateCall(node, qualifierRef.getReferencedName()); - } - } - } - } - } - - @Override - public void visitPyFromImportStatement(PyFromImportStatement node) { - if (node.isFromFuture()) return; - PsiElement source = PyUtil.turnDirIntoInit(node.resolveImportSource()); - if (source instanceof PyFile) { - PyBlockEvaluator importEvaluator = new PyBlockEvaluator(myVisitedFiles); - importEvaluator.myDeclarationsToTrack.addAll(myDeclarationsToTrack); - importEvaluator.evaluate((PyFile)source); - if (node.isStarImport()) { - // TODO honor __all__ here - myNamespace.putAll(importEvaluator.myNamespace); - myDeclarations.putAll(importEvaluator.myDeclarations); - } - else { - for (final PyImportElement element : node.getImportElements()) { - final String nameOfVarInOurModule = element.getVisibleName(); - final QualifiedName nameOfVarInExternalModule = element.getImportedQName(); - if ((nameOfVarInOurModule == null) || (nameOfVarInExternalModule == null)) { - continue; - } - - final Object value = importEvaluator.myNamespace.get(nameOfVarInExternalModule.toString()); - myNamespace.put(nameOfVarInOurModule, value); - final List declarations = importEvaluator.getDeclarations(nameOfVarInOurModule); - if (myDeclarations.containsKey(nameOfVarInOurModule)) { - myDeclarations.get(nameOfVarInOurModule).addAll(declarations); - } - else { - myDeclarations.put(nameOfVarInOurModule, declarations); - } - } - } - } - } - - @Override - public void visitPyIfStatement(PyIfStatement node) { - PyStatementList list = node.getIfPart().getStatementList(); - if (list != null) { - list.acceptChildren(this); - } - } - - @Override - public void visitPyReturnStatement(PyReturnStatement node) { - myReturnValue = prepareEvaluator().evaluate(node.getExpression()); - } - }); - } - - private void processExtendCall(PyCallExpression node, String nameBeingExtended) { - PyExpression arg = node.getArguments()[0]; - - Object value = myNamespace.get(nameBeingExtended); - if (value instanceof List) { - Object argValue = prepareEvaluator().evaluate(arg); - myNamespace.put(nameBeingExtended, prepareEvaluator().concatenate(value, argValue)); - } - - if (myDeclarationsToTrack.contains(nameBeingExtended)) { - List declarations = myDeclarations.get(nameBeingExtended); - if (declarations != null) { - PyPsiUtils.sequenceToList(declarations, arg); - } - } - } - - private void processUpdateCall(PyCallExpression node, String name) { - Object value = myNamespace.get(name); - if (value instanceof Map) { - Object argValue = prepareEvaluator().evaluate(node.getArguments()[0]); - if (argValue instanceof Map) { - ((Map)value).putAll((Map)argValue); - } - } - } - - private PyEvaluator prepareEvaluator() { - PyEvaluator evaluator = createEvaluator(); - evaluator.setNamespace(myNamespace); - evaluator.setEvaluateCollectionItems(myEvaluateCollectionItems); - return evaluator; - } - - protected PyEvaluator createEvaluator() { - return new PyPathEvaluator(myCurrentFilePath); - } - - public Object getValue(String name) { - return myNamespace.get(name); - } - - @Nullable - public String getValueAsString(String name) { - Object value = myNamespace.get(name); - return value instanceof String ? (String) value : null; - } - - @Nullable - public List getValueAsList(String name) { - Object value = myNamespace.get(name); - return value instanceof List ? (List) value : null; - } - - @NotNull - public List getValueAsStringList(String name) { - Object value = myNamespace.get(name); - if (value instanceof List) { - List valueList = (List) value; - for (Object o : valueList) { - if (o != null && !(o instanceof String)) { - return Collections.emptyList(); - } - } - return (List) value; - } - if (value instanceof String) { - return Collections.singletonList((String) value); - } - return Collections.emptyList(); - } - - public Set getVisitedFiles() { - return myVisitedFiles; - } - - @NotNull - public List getDeclarations(String name) { - List expressions = myDeclarations.get(name); - return expressions != null ? expressions : Collections.emptyList(); - } - - public Object getReturnValue() { - return myReturnValue; - } - - public void setEvaluateCollectionItems(boolean evaluateCollectionItems) { - myEvaluateCollectionItems = evaluateCollectionItems; - } -} diff --git a/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyBlockEvaluator.java b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyBlockEvaluator.java new file mode 100644 index 000000000000..b1fca2893970 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyBlockEvaluator.java @@ -0,0 +1,314 @@ +/* + * 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.psi.impl.blockEvaluator; + +import com.google.common.collect.Sets; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.QualifiedName; +import com.jetbrains.python.PyNames; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyEvaluator; +import com.jetbrains.python.psi.impl.PyPathEvaluator; +import com.jetbrains.python.psi.impl.PyPsiUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * @author yole + */ +public class PyBlockEvaluator { + @NotNull + private final PyEvaluationResult myEvaluationResult = new PyEvaluationResult(); + @NotNull + private final PyEvaluationContext myContext; + private final Set myVisitedFiles; + private final Set myDeclarationsToTrack = new HashSet(); + private String myCurrentFilePath; + private Object myReturnValue; + private boolean myEvaluateCollectionItems = true; + + /** + * @param evaluationContext context, obtained via {@link #getContext()}. Pass it here to enable cache. See {@link com.jetbrains.python.psi.impl.blockEvaluator.PyEvaluationContext} + * for more info + * @see com.jetbrains.python.psi.impl.blockEvaluator.PyEvaluationContext + */ + public PyBlockEvaluator(@NotNull final PyEvaluationContext evaluationContext) { + this(Sets.newHashSet(), evaluationContext); + } + + /** + * Create evaluator with out of cache context + */ + public PyBlockEvaluator() { + this(new PyEvaluationContext()); + } + + private PyBlockEvaluator(@NotNull final Set visitedFiles, @NotNull final PyEvaluationContext evaluationContext) { + myVisitedFiles = visitedFiles; + myContext = evaluationContext; + } + + public void trackDeclarations(String attrName) { + myDeclarationsToTrack.add(attrName); + } + + public void evaluate(PyElement element) { + VirtualFile vFile = element.getContainingFile().getVirtualFile(); + myCurrentFilePath = vFile != null ? vFile.getPath() : null; + if (myVisitedFiles.contains(element)) { + return; + } + myVisitedFiles.add((PyFile)element.getContainingFile()); + PyElement statementContainer = element instanceof PyFunction ? ((PyFunction)element).getStatementList() : element; + if (statementContainer == null) { + return; + } + statementContainer.acceptChildren(new MyPyElementVisitor()); + } + + private void processExtendCall(PyCallExpression node, String nameBeingExtended) { + PyExpression arg = node.getArguments()[0]; + + Object value = myEvaluationResult.myNamespace.get(nameBeingExtended); + if (value instanceof List) { + Object argValue = prepareEvaluator().evaluate(arg); + myEvaluationResult.myNamespace.put(nameBeingExtended, prepareEvaluator().concatenate(value, argValue)); + } + + if (myDeclarationsToTrack.contains(nameBeingExtended)) { + List declarations = myEvaluationResult.myDeclarations.get(nameBeingExtended); + if (declarations != null) { + PyPsiUtils.sequenceToList(declarations, arg); + } + } + } + + private void processUpdateCall(PyCallExpression node, String name) { + Object value = myEvaluationResult.myNamespace.get(name); + if (value instanceof Map) { + Object argValue = prepareEvaluator().evaluate(node.getArguments()[0]); + if (argValue instanceof Map) { + ((Map)value).putAll((Map)argValue); + } + } + } + + private PyEvaluator prepareEvaluator() { + PyEvaluator evaluator = createEvaluator(); + evaluator.setNamespace(myEvaluationResult.myNamespace); + evaluator.setEvaluateCollectionItems(myEvaluateCollectionItems); + return evaluator; + } + + protected PyEvaluator createEvaluator() { + return new PyPathEvaluator(myCurrentFilePath); + } + + public Object getValue(String name) { + return myEvaluationResult.myNamespace.get(name); + } + + @Nullable + public String getValueAsString(String name) { + Object value = myEvaluationResult.myNamespace.get(name); + return value instanceof String ? (String)value : null; + } + + @Nullable + public List getValueAsList(String name) { + Object value = myEvaluationResult.myNamespace.get(name); + return value instanceof List ? (List)value : null; + } + + @NotNull + public List getValueAsStringList(String name) { + Object value = myEvaluationResult.myNamespace.get(name); + if (value instanceof List) { + List valueList = (List)value; + for (Object o : valueList) { + if (o != null && !(o instanceof String)) { + return Collections.emptyList(); + } + } + return (List)value; + } + if (value instanceof String) { + return Collections.singletonList((String)value); + } + return Collections.emptyList(); + } + + public Set getVisitedFiles() { + return myVisitedFiles; + } + + + public Object getReturnValue() { + return myReturnValue; + } + + public void setEvaluateCollectionItems(boolean evaluateCollectionItems) { + myEvaluateCollectionItems = evaluateCollectionItems; + } + + @NotNull + public List getDeclarations(@NotNull final String name) { + return myEvaluationResult.getDeclarations(name); + } + + /** + * @return so-called context. You may pass it to any instance of {@link com.jetbrains.python.psi.impl.blockEvaluator.PyBlockEvaluator} + * to make instances share their cache + */ + @NotNull + public PyEvaluationContext getContext() { + return myContext; + } + + private class MyPyElementVisitor extends PyElementVisitor { + @Override + public void visitPyAssignmentStatement(PyAssignmentStatement node) { + PyExpression expression = node.getLeftHandSideExpression(); + if (expression instanceof PyTargetExpression) { + String name = expression.getName(); + PyExpression value = ((PyTargetExpression)expression).findAssignedValue(); + myEvaluationResult.myNamespace.put(name, prepareEvaluator().evaluate(value)); + if (myDeclarationsToTrack.contains(name)) { + List declarations = new ArrayList(); + PyPsiUtils.sequenceToList(declarations, value); + myEvaluationResult.myDeclarations.put(name, declarations); + } + } + else if (expression instanceof PySubscriptionExpression) { + PyExpression operand = ((PySubscriptionExpression)expression).getOperand(); + PyExpression indexExpression = ((PySubscriptionExpression)expression).getIndexExpression(); + if (operand instanceof PyReferenceExpression && ((PyReferenceExpression)operand).getQualifier() == null) { + Object currentValue = myEvaluationResult.myNamespace.get(((PyReferenceExpression)operand).getReferencedName()); + if (currentValue instanceof Map) { + Object mapKey = prepareEvaluator().evaluate(indexExpression); + if (mapKey != null) { + Object value = myEvaluateCollectionItems ? prepareEvaluator().evaluate(node.getAssignedValue()) : node.getAssignedValue(); + ((Map)currentValue).put(mapKey, value); + } + } + } + } + } + + @Override + public void visitPyAugAssignmentStatement(PyAugAssignmentStatement node) { + PyExpression target = node.getTarget(); + String name = target.getName(); + if (target instanceof PyReferenceExpression && !((PyReferenceExpression)target).isQualified() && name != null) { + Object currentValue = myEvaluationResult.myNamespace.get(name); + if (currentValue != null) { + Object rhs = prepareEvaluator().evaluate(node.getValue()); + myEvaluationResult.myNamespace.put(name, prepareEvaluator().concatenate(currentValue, rhs)); + } + if (myDeclarationsToTrack.contains(name)) { + List declarations = myEvaluationResult.myDeclarations.get(name); + if (declarations != null) { + PyPsiUtils.sequenceToList(declarations, node.getValue()); + } + } + } + } + + @Override + public void visitPyExpressionStatement(PyExpressionStatement node) { + node.getExpression().accept(this); + } + + @Override + public void visitPyCallExpression(PyCallExpression node) { + PyExpression callee = node.getCallee(); + if (callee instanceof PyReferenceExpression) { + PyReferenceExpression calleeRef = (PyReferenceExpression)callee; + PyExpression qualifier = calleeRef.getQualifier(); + if (qualifier instanceof PyReferenceExpression) { + PyReferenceExpression qualifierRef = (PyReferenceExpression)qualifier; + if (!qualifierRef.isQualified()) { + if (PyNames.EXTEND.equals(calleeRef.getReferencedName()) && node.getArguments().length == 1) { + processExtendCall(node, qualifierRef.getReferencedName()); + } + else if (PyNames.UPDATE.equals(calleeRef.getReferencedName()) && node.getArguments().length == 1) { + processUpdateCall(node, qualifierRef.getReferencedName()); + } + } + } + } + } + + @Override + public void visitPyFromImportStatement(final PyFromImportStatement node) { + if (node.isFromFuture()) return; + final PsiElement source = PyUtil.turnDirIntoInit(node.resolveImportSource()); + if (source instanceof PyFile) { + final PyFile pyFile = (PyFile)source; + PyEvaluationResult newlyEvaluatedResult = myContext.getCachedResult(pyFile); + + if (newlyEvaluatedResult == null) { + final PyBlockEvaluator importEvaluator = new PyBlockEvaluator(myVisitedFiles, myContext); + importEvaluator.myDeclarationsToTrack.addAll(myDeclarationsToTrack); + importEvaluator.evaluate(pyFile); + newlyEvaluatedResult = importEvaluator.myEvaluationResult; + myContext.cache(pyFile, newlyEvaluatedResult); + } + + if (node.isStarImport()) { + // TODO honor __all__ here + myEvaluationResult.myNamespace.putAll(newlyEvaluatedResult.myNamespace); + myEvaluationResult.myDeclarations.putAll(newlyEvaluatedResult.myDeclarations); + } + else { + for (final PyImportElement element : node.getImportElements()) { + final String nameOfVarInOurModule = element.getVisibleName(); + final QualifiedName nameOfVarInExternalModule = element.getImportedQName(); + if ((nameOfVarInOurModule == null) || (nameOfVarInExternalModule == null)) { + continue; + } + + final Object value = newlyEvaluatedResult.myNamespace.get(nameOfVarInExternalModule.toString()); + myEvaluationResult.myNamespace.put(nameOfVarInOurModule, value); + final List declarations = newlyEvaluatedResult.getDeclarations(nameOfVarInOurModule); + if (myEvaluationResult.myDeclarations.containsKey(nameOfVarInOurModule)) { + myEvaluationResult.myDeclarations.get(nameOfVarInOurModule).addAll(declarations); + } + else { + myEvaluationResult.myDeclarations.put(nameOfVarInOurModule, declarations); + } + } + } + } + } + + @Override + public void visitPyIfStatement(PyIfStatement node) { + PyStatementList list = node.getIfPart().getStatementList(); + if (list != null) { + list.acceptChildren(this); + } + } + + @Override + public void visitPyReturnStatement(PyReturnStatement node) { + myReturnValue = prepareEvaluator().evaluate(node.getExpression()); + } + } +} diff --git a/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyEvaluationContext.java b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyEvaluationContext.java new file mode 100644 index 000000000000..ababfd56751d --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyEvaluationContext.java @@ -0,0 +1,42 @@ +package com.jetbrains.python.psi.impl.blockEvaluator; + +import com.jetbrains.python.psi.PyFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** + * Cache for {@link com.jetbrains.python.psi.impl.blockEvaluator.PyBlockEvaluator}. + * You may obtain one via {@link PyBlockEvaluator#getContext()} and pass to ctor: + * {@link com.jetbrains.python.psi.impl.blockEvaluator.PyBlockEvaluator#PyBlockEvaluator(PyEvaluationContext)} to enable cache + * + * @author Ilya.Kazakevich + */ +public class PyEvaluationContext { + @NotNull + private final Map myResultMap = new HashMap(); + + PyEvaluationContext() { + } + + /** + * Get evaluation result by file + * @param file file + * @return eval result + */ + @Nullable + PyEvaluationResult getCachedResult(@NotNull final PyFile file) { + return myResultMap.get(file); + } + + /** + * Store evaluation result by file + * @param file file + * @param result evaluation result + */ + void cache(@NotNull final PyFile file, @NotNull final PyEvaluationResult result) { + myResultMap.put(file, result); + } +} diff --git a/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyEvaluationResult.java b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyEvaluationResult.java new file mode 100644 index 000000000000..c28baf569f8b --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/PyEvaluationResult.java @@ -0,0 +1,26 @@ +package com.jetbrains.python.psi.impl.blockEvaluator; + +import com.jetbrains.python.psi.PyExpression; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Ilya.Kazakevich + */ +@SuppressWarnings("PackageVisibleField") // Package-only class +class PyEvaluationResult { + @NotNull + final Map myNamespace = new HashMap(); + @NotNull + final Map> myDeclarations = new HashMap>(); + + @NotNull + List getDeclarations(@NotNull final String name) { + final List expressions = myDeclarations.get(name); + return (expressions != null) ? expressions : Collections.emptyList(); + } +} diff --git a/python/src/com/jetbrains/python/psi/impl/blockEvaluator/package-info.java b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/package-info.java new file mode 100644 index 000000000000..c44fd5dfa346 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/blockEvaluator/package-info.java @@ -0,0 +1,7 @@ +/** + * Engine to evaluate block of python text. + * Use {@link com.jetbrains.python.psi.impl.blockEvaluator.PyBlockEvaluator} as entry point. + * + * @author Ilya.Kazakevich + */ +package com.jetbrains.python.psi.impl.blockEvaluator; \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyBlockEvaluatorTest.java b/python/testSrc/com/jetbrains/python/PyBlockEvaluatorTest.java index 368c05556ef0..75665ac3dbe3 100644 --- a/python/testSrc/com/jetbrains/python/PyBlockEvaluatorTest.java +++ b/python/testSrc/com/jetbrains/python/PyBlockEvaluatorTest.java @@ -21,7 +21,7 @@ import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyStringLiteralExpression; import com.jetbrains.python.psi.PyUtil; -import com.jetbrains.python.psi.impl.PyBlockEvaluator; +import com.jetbrains.python.psi.impl.blockEvaluator.PyBlockEvaluator; import org.junit.Assert; import java.util.ArrayList;