/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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.google.dart.engine.services.internal.refactoring; import com.google.dart.engine.ast.AssignmentExpression; import com.google.dart.engine.ast.AstNode; import com.google.dart.engine.ast.ConstructorInitializer; import com.google.dart.engine.ast.Expression; import com.google.dart.engine.ast.ForStatement; import com.google.dart.engine.ast.PrefixedIdentifier; import com.google.dart.engine.ast.SimpleIdentifier; import com.google.dart.engine.ast.TypeName; import com.google.dart.engine.ast.VariableDeclaration; import com.google.dart.engine.element.Element; import com.google.dart.engine.element.FunctionElement; import com.google.dart.engine.element.MethodElement; import com.google.dart.engine.services.internal.correction.CorrectionUtils; import com.google.dart.engine.services.internal.correction.StatementAnalyzer; import com.google.dart.engine.services.status.RefactoringStatusContext; import com.google.dart.engine.services.util.SelectionAnalyzer; import com.google.dart.engine.utilities.source.SourceRange; /** * {@link SelectionAnalyzer} for "Extract Method" refactoring. */ public class ExtractMethodAnalyzer extends StatementAnalyzer { public ExtractMethodAnalyzer(CorrectionUtils utils, SourceRange selection) { super(utils, selection); } @Override public Void visitAssignmentExpression(AssignmentExpression node) { super.visitAssignmentExpression(node); Expression lhs = node.getLeftHandSide(); if (isFirstSelectedNode(lhs)) { invalidSelection( "Cannot extract the left-hand side of an assignment.", new RefactoringStatusContext(lhs)); } return null; } @Override public Void visitConstructorInitializer(ConstructorInitializer node) { super.visitConstructorInitializer(node); if (isFirstSelectedNode(node)) { invalidSelection( "Cannot extract a constructor initializer. Select expression part of initializer.", new RefactoringStatusContext(node)); } return null; } @Override public Void visitForStatement(ForStatement node) { super.visitForStatement(node); if (node.getVariables() == getFirstSelectedNode()) { invalidSelection("Cannot extract initialization part of a 'for' statement."); } else if (node.getUpdaters().contains(getLastSelectedNode())) { invalidSelection("Cannot extract increment part of a 'for' statement."); } return null; } @Override public Void visitSimpleIdentifier(SimpleIdentifier node) { super.visitSimpleIdentifier(node); if (isFirstSelectedNode(node)) { // name of declaration if (node.inDeclarationContext()) { invalidSelection("Cannot extract the name part of a declaration."); } // method name Element element = node.getBestElement(); if (element instanceof FunctionElement || element instanceof MethodElement) { invalidSelection("Cannot extract a single method name."); } // name in property access if (node.getParent() instanceof PrefixedIdentifier && ((PrefixedIdentifier) node.getParent()).getIdentifier() == node) { invalidSelection("Can not extract name part of a property access."); } } return null; } @Override public Void visitTypeName(TypeName node) { super.visitTypeName(node); if (isFirstSelectedNode(node)) { invalidSelection("Cannot extract a single type reference."); } return null; } @Override public Void visitVariableDeclaration(VariableDeclaration node) { super.visitVariableDeclaration(node); if (isFirstSelectedNode(node)) { invalidSelection( "Cannot extract a variable declaration fragment. Select whole declaration statement.", new RefactoringStatusContext(node)); } return null; } @Override protected void handleNextSelectedNode(AstNode node) { super.handleNextSelectedNode(node); checkParent(node); } @Override protected void handleSelectionEndsIn(AstNode node) { super.handleSelectionEndsIn(node); invalidSelection("The selection does not cover a set of statements or an expression. " + "Extend selection to a valid range."); } private void checkParent(AstNode node) { AstNode firstParent = getFirstSelectedNode().getParent(); do { node = node.getParent(); if (node == firstParent) { return; } } while (node != null); invalidSelection("Not all selected statements are enclosed by the same parent statement."); } private boolean isFirstSelectedNode(AstNode node) { return getFirstSelectedNode() == node; } }