# HG changeset patch # User Alexander Simon # Date 1475834790 -10800 # Fri Oct 07 13:06:30 2016 +0300 # Branch release82 # Node ID 2ca5f234caab95516366d29a7278d62b9851d505 # Parent cfeb0bf531e8aea41699f2c248aab091dbab47e0 fixing Bug #268402 Find Usages: mark differently read, write and read/write access to variable - introduce RW access in FU diff --git a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/api/WhereUsedQueryConstants.java b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/api/WhereUsedQueryConstants.java --- a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/api/WhereUsedQueryConstants.java +++ b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/api/WhereUsedQueryConstants.java @@ -50,5 +50,6 @@ FIND_OVERRIDING_METHODS, FIND_SUBCLASSES, FIND_DIRECT_SUBCLASSES, - SEARCH_FROM_BASECLASS; + SEARCH_FROM_BASECLASS, + READ_WRITE; } diff --git a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/elements/CsmRefactoringElementImpl.java b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/elements/CsmRefactoringElementImpl.java --- a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/elements/CsmRefactoringElementImpl.java +++ b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/elements/CsmRefactoringElementImpl.java @@ -30,13 +30,22 @@ */ package org.netbeans.modules.cnd.refactoring.elements; +import java.util.Collection; import java.util.EnumSet; +import java.util.concurrent.atomic.AtomicReference; import javax.swing.Icon; import javax.swing.text.BadLocationException; import javax.swing.text.StyledDocument; import org.netbeans.api.editor.document.LineDocumentUtils; +import org.netbeans.api.lexer.Token; +import org.netbeans.api.lexer.TokenId; +import org.netbeans.api.lexer.TokenSequence; +import org.netbeans.cnd.api.lexer.CndLexerUtilities; +import org.netbeans.cnd.api.lexer.CppTokenId; import org.netbeans.editor.BaseDocument; import org.netbeans.modules.cnd.api.model.CsmFile; +import org.netbeans.modules.cnd.api.model.CsmObject; +import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities; import org.netbeans.modules.cnd.api.model.xref.CsmReference; import org.netbeans.modules.cnd.api.model.xref.CsmReferenceKind; import org.netbeans.modules.cnd.api.model.xref.CsmReferenceResolver; @@ -60,6 +69,12 @@ */ public class CsmRefactoringElementImpl extends SimpleRefactoringElementImplementation implements FiltersManager.Filterable { + + public enum RW { + Read, + Write, + ReadWrite + } private static final boolean LAZY = false; private final CsmReference elem; private final PositionBounds bounds; @@ -72,9 +87,10 @@ private final boolean isInMacros; private final boolean isInDeadCode; private final boolean isInComments; + private final RW rw; public CsmRefactoringElementImpl(PositionBounds bounds, - CsmReference elem, FileObject fo, String displayText) { + CsmReference elem, FileObject fo, String displayText, CsmObject referencedObject) { this.elem = elem; this.bounds = bounds; this.fo = fo; @@ -90,6 +106,11 @@ this.isInMacros = CsmReferenceResolver.getDefault().isKindOf(elem, EnumSet.of(CsmReferenceKind.IN_PREPROCESSOR_DIRECTIVE)); this.isInDeadCode = CsmReferenceResolver.getDefault().isKindOf(elem, EnumSet.of(CsmReferenceKind.IN_DEAD_BLOCK)); this.isInComments = CsmReferenceResolver.getDefault().isKindOf(elem, EnumSet.of(CsmReferenceKind.COMMENT)); + if (referencedObject != null && CsmKindUtilities.isVariable(referencedObject)) { + this.rw = getRW(elem); + } else { + this.rw = RW.Read; + } } private boolean isScope(CsmReference ref) { @@ -111,7 +132,189 @@ } return false; } - + + private RW getRW(final CsmReference ref) { + final AtomicReference out = new AtomicReference<>(RW.Write); + CsmFile csmFile = ref.getContainingFile(); + CloneableEditorSupport ces = CsmUtilities.findCloneableEditorSupport(csmFile); + StyledDocument stDoc = CsmUtilities.openDocument(ces); + if (stDoc instanceof BaseDocument) { + final BaseDocument doc = (BaseDocument) stDoc; + doc.render(new Runnable() { + @Override + public void run() { + int offset = ref.getStartOffset(); + TokenSequence cppTokenSequence = CndLexerUtilities.getCppTokenSequence(doc, offset, true, false); + if (cppTokenSequence == null) { + return; + } + CppTokenId nextImportantToken = null; + cppTokenSequence.move(offset); + if (cppTokenSequence.moveNext()) { + next: + while (cppTokenSequence.moveNext()) { + Token token = cppTokenSequence.token(); + TokenId id = token.id(); + if (id instanceof CppTokenId) { + switch ((CppTokenId) id) { + // skip unimportant + case WHITESPACE: + case ESCAPED_LINE: + case ESCAPED_WHITESPACE: + case NEW_LINE: + case LINE_COMMENT: + case BLOCK_COMMENT: + case DOXYGEN_COMMENT: + case DOXYGEN_LINE_COMMENT: + break; + // asignments + case EQ: + case PLUSEQ: + case MINUSEQ: + case STAREQ: + case SLASHEQ: + case AMPEQ: + case BAREQ: + case CARETEQ: + case PERCENTEQ: + case LTLTEQ: + case GTGTEQ: + // increments + case PLUSPLUS: + case MINUSMINUS: + out.set(RW.Write); + return; + // supose that binary operators have a read access + case PLUS: + case MINUS: + case GT: + case LT: + case QUESTION: + case EQEQ: + case LTEQ: + case GTEQ: + case NOTEQ: + case AMPAMP: + case BARBAR: + case STAR: + case SLASH: + case BAR: + case CARET: + case PERCENT: + case LTLT: + case GTGT: + out.set(RW.Read); + return; + case COMMA: + case COLON: + case SEMICOLON: + case RBRACKET: + case RPAREN: + case DOT: + case DOTMBR: + case ARROW: + case ARROWMBR: + case SCOPE: + nextImportantToken = (CppTokenId) id; + break next; + default: + break next; + } + } + } + } + + cppTokenSequence.move(offset); + prev: + while (cppTokenSequence.movePrevious()) { + Token token = cppTokenSequence.token(); + TokenId id = token.id(); + if (id instanceof CppTokenId) { + switch ((CppTokenId) id) { + // skip unimportant + case WHITESPACE: + case ESCAPED_LINE: + case ESCAPED_WHITESPACE: + case NEW_LINE: + case LINE_COMMENT: + case BLOCK_COMMENT: + case DOXYGEN_COMMENT: + case DOXYGEN_LINE_COMMENT: + break; + // increments + case PLUSPLUS: + case MINUSMINUS: + out.set(RW.Write); + return; + case EQ: + case PLUSEQ: + case MINUSEQ: + case STAREQ: + case SLASHEQ: + case AMPEQ: + case BAREQ: + case CARETEQ: + case PERCENTEQ: + case LTLTEQ: + case GTGTEQ: + out.set(RW.Read); + return; + // supose that unary operators have a read access + case NOT: + case TILDE: + out.set(RW.Read); + return; + // supose that unary/binary operators have a read access + case PLUS: + case MINUS: + out.set(RW.Read); + return; + // supose that binary operators have a read access + case GT: + case LT: + case QUESTION: + case EQEQ: + case LTEQ: + case GTEQ: + case NOTEQ: + case AMPAMP: + case BARBAR: + case STAR: + case SLASH: + case BAR: + case CARET: + case PERCENT: + case LTLT: + case GTGT: + out.set(RW.Read); + return; + //needs further investigation + case COMMA: + case LPAREN: + case DOT: + case DOTMBR: + case ARROW: + case ARROWMBR: + case SCOPE: + out.set(RW.Read); + return; + //needs further investigation + case AMP: + out.set(RW.Read); + return; + //needs further investigation + default: + out.set(RW.Read); + return; + } + } + } + } + }); + } + return out.get(); + } + @Override public String getText() { return elem.getText().toString(); @@ -153,16 +356,25 @@ return "{" + "bounds=" + bounds + ", displayText=" + displayText + ", enclosing=" + enclosing + ", fo=" + fo + '}'; // NOI18N } - public static RefactoringElementImplementation create(CsmReference ref,boolean nameInBold) { + public static RefactoringElementImplementation create(CsmReference ref, boolean nameInBold, CsmObject referencedObject) { CsmFile csmFile = ref.getContainingFile(); FileObject fo = CsmUtilities.getFileObject(csmFile); PositionBounds bounds = CsmUtilities.createPositionBounds(ref); String displayText = LAZY ? null : CsmReferenceSupport.getContextLineHtml(ref, nameInBold).toString(); - return new CsmRefactoringElementImpl(bounds, ref, fo, displayText); + return new CsmRefactoringElementImpl(bounds, ref, fo, displayText, referencedObject); } @Override public boolean filter(FiltersManager manager) { + if (rw == RW.Read && !manager.isSelected(CsmWhereUsedFilters.READ.getKey())) { + return false; + } + if (rw == RW.Write && !manager.isSelected(CsmWhereUsedFilters.WRITE.getKey())) { + return false; + } + if (rw == RW.ReadWrite && !manager.isSelected(CsmWhereUsedFilters.READ_WRITE.getKey())) { + return false; + } if (isDecl && !manager.isSelected(CsmWhereUsedFilters.DECLARATIONS.getKey())) { return false; } diff --git a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/Bundle.properties b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/Bundle.properties --- a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/Bundle.properties +++ b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/Bundle.properties @@ -266,6 +266,9 @@ #Find Usages Filters TXT_Filter_Comments=Comments filter TXT_Filter_DeadCode=Dead code filter +TXT_Filter_Read=Read filter +TXT_Filter_Write=Write filter +TXT_Filter_ReadWrite=Read/Write filter TXT_Filter_Declarations=Declarations and definitions filter TXT_Filter_Macros=Macros filter TXT_Filter_Scope=Class name in qualified name filter diff --git a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedFilters.java b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedFilters.java --- a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedFilters.java +++ b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedFilters.java @@ -50,6 +50,9 @@ COMMENTS("filter-comments"), // NOI18N DEAD_CODE("filter-deadcode"), // NOI18N MACROS("filter-macros"), // NOI18N + READ("filter-read"), // NOI18N + WRITE("filter-write"), // NOI18N + READ_WRITE("filter-readwrite"), // NOI18N DECLARATIONS("filter-declarations"), // NOI18N SCOPE("filter-scope"); // NOI18N diff --git a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedQueryPlugin.java b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedQueryPlugin.java --- a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedQueryPlugin.java +++ b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/plugins/CsmWhereUsedQueryPlugin.java @@ -306,6 +306,10 @@ return refactoring.getBooleanValue(WhereUsedQueryConstants.SEARCH_FROM_BASECLASS); } + private boolean isReadWriteAccess() { + return refactoring.getBooleanValue(WhereUsedQueryConstants.READ_WRITE); + } + private boolean isSearchInComments() { return refactoring.getBooleanValue(WhereUsedQuery.SEARCH_IN_COMMENTS); } @@ -344,7 +348,7 @@ accept = !CsmReferenceResolver.getDefault().isKindOf(csmReference, EnumSet.of(CsmReferenceKind.DECLARATION, CsmReferenceKind.DEFINITION)); } if (accept) { - elements.add(CsmRefactoringElementImpl.create(csmReference, true)); + elements.add(CsmRefactoringElementImpl.create(csmReference, true, curObj)); } } } finally { @@ -464,6 +468,17 @@ filtersDescription.addFilter(CsmWhereUsedFilters.DEAD_CODE.getKey(), NbBundle.getMessage(this.getClass(), "TXT_Filter_DeadCode"), true, ImageUtilities.loadImageIcon("org/netbeans/modules/cnd/refactoring/resources/found_item_dead.png", false)); //NOI18N + + filtersDescription.addFilter(CsmWhereUsedFilters.READ.getKey(), + NbBundle.getMessage(this.getClass(), "TXT_Filter_Read"), true, + ImageUtilities.loadImageIcon("org/netbeans/modules/cnd/refactoring/resources/found_item_read.png", false)); //NOI18N + filtersDescription.addFilter(CsmWhereUsedFilters.WRITE.getKey(), + NbBundle.getMessage(this.getClass(), "TXT_Filter_Write"), true, + ImageUtilities.loadImageIcon("org/netbeans/modules/cnd/refactoring/resources/found_item_write.png", false)); //NOI18N + filtersDescription.addFilter(CsmWhereUsedFilters.READ_WRITE.getKey(), + NbBundle.getMessage(this.getClass(), "TXT_Filter_ReadWrite"), true, + ImageUtilities.loadImageIcon("org/netbeans/modules/cnd/refactoring/resources/found_item_readwrite.png", false)); //NOI18N + filtersDescription.addFilter(CsmWhereUsedFilters.DECLARATIONS.getKey(), NbBundle.getMessage(this.getClass(), "TXT_Filter_Declarations"), false, ImageUtilities.loadImageIcon(CsmImageName.DECLARATION_FILTER, false)); @@ -481,6 +496,11 @@ filtersDescription.enable(CsmWhereUsedFilters.COMMENTS.getKey()); } filtersDescription.enable(CsmWhereUsedFilters.DEAD_CODE.getKey()); + if (isReadWriteAccess()) { + filtersDescription.enable(CsmWhereUsedFilters.READ.getKey()); + filtersDescription.enable(CsmWhereUsedFilters.WRITE.getKey()); + filtersDescription.enable(CsmWhereUsedFilters.READ_WRITE.getKey()); + } if (!isFindDirectSubclassesOnly() && !isFindSubclasses()) { filtersDescription.enable(CsmWhereUsedFilters.DECLARATIONS.getKey()); filtersDescription.enable(CsmWhereUsedFilters.SCOPE.getKey()); @@ -531,7 +551,7 @@ accept = !CsmReferenceResolver.getDefault().isKindOf(csmReference, EnumSet.of(CsmReferenceKind.DECLARATION, CsmReferenceKind.DEFINITION)); } if (accept) { - fileElems.add(CsmRefactoringElementImpl.create(csmReference, true)); + fileElems.add(CsmRefactoringElementImpl.create(csmReference, true, objs.length > 0 ? objs[0] : null)); } } } finally { @@ -569,13 +589,13 @@ overrides.add(csmMethod); for (CsmMethod method : overrides) { CsmReference declRef = CsmReferenceSupport.createObjectReference(method); - elements.add(CsmRefactoringElementImpl.create(declRef, false)); + elements.add(CsmRefactoringElementImpl.create(declRef, false, method)); // find defintion of method if needed if (!CsmKindUtilities.isFunctionDefinition(method)) { CsmFunctionDefinition def = method.getDefinition(); if (def != null) { CsmReference defRef = CsmReferenceSupport.createObjectReference(def); - elements.add(CsmRefactoringElementImpl.create(defRef, false)); + elements.add(CsmRefactoringElementImpl.create(defRef, false, method)); } } } @@ -606,14 +626,14 @@ for (CsmReference csmReference : refs) { for (CsmProject prj : prjs) { if (csmReference.getContainingFile().getProject().equals(prj)) { - elements.add(CsmRefactoringElementImpl.create(csmReference, false)); + elements.add(CsmRefactoringElementImpl.create(csmReference, false, csmFile)); break; } } } } else { for (CsmReference csmReference : refs) { - elements.add(CsmRefactoringElementImpl.create(csmReference, false)); + elements.add(CsmRefactoringElementImpl.create(csmReference, false, csmFile)); } } } @@ -630,7 +650,7 @@ CsmClass referencedClass = (CsmClass) obj; Collection refs = CsmTypeHierarchyResolver.getDefault().getSubTypes(referencedClass, directSubtypesOnly); for (CsmReference csmReference : refs) { - elements.add(CsmRefactoringElementImpl.create(csmReference, false)); + elements.add(CsmRefactoringElementImpl.create(csmReference, false, startClass)); } } } diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/resources/found_item_read.png b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/resources/found_item_read.png copy from refactoring.java/src/org/netbeans/modules/refactoring/java/resources/found_item_read.png copy to cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/resources/found_item_read.png diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/resources/found_item_readwrite.png b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/resources/found_item_readwrite.png copy from refactoring.java/src/org/netbeans/modules/refactoring/java/resources/found_item_readwrite.png copy to cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/resources/found_item_readwrite.png diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/resources/found_item_write.png b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/resources/found_item_write.png copy from refactoring.java/src/org/netbeans/modules/refactoring/java/resources/found_item_write.png copy to cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/resources/found_item_write.png diff --git a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/ui/WhereUsedQueryUI.java b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/ui/WhereUsedQueryUI.java --- a/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/ui/WhereUsedQueryUI.java +++ b/cnd.refactoring/src/org/netbeans/modules/cnd/refactoring/ui/WhereUsedQueryUI.java @@ -104,14 +104,19 @@ assert panel != null; query.putValue(WhereUsedQuery.SEARCH_IN_COMMENTS,panel.isSearchInComments()); + Collection prjs = CsmRefactoringUtils.getRelatedCsmProjects(this.origObject, panel.getScopeProject()); CsmProject[] ar = prjs.toArray(new CsmProject[prjs.size()]); query.getContext().add(ar); + query.putValue(WhereUsedQueryConstants.READ_WRITE, false); CsmObject refObj = panel.getReferencedObject(); if (refObj == null) { query.setRefactoringSource(Lookup.EMPTY); } else { + if (CsmKindUtilities.isVariable(refObj)) { + query.putValue(WhereUsedQueryConstants.READ_WRITE, true); + } query.setRefactoringSource(Lookups.singleton(CsmRefactoringUtils.getHandler(refObj))); } if (panel.isVirtualMethod()) {