blob: 8a86f2c03bfa6b16940dc2f13de31e88a478df78 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.netbeans.modules.php.editor.verification;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.csl.api.EditList;
import org.netbeans.modules.csl.api.Hint;
import org.netbeans.modules.csl.api.HintFix;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.spi.support.CancelSupport;
import org.netbeans.modules.php.editor.parser.PHPParseResult;
import org.netbeans.modules.php.editor.parser.astnodes.DeclareStatement;
import org.netbeans.modules.php.editor.parser.astnodes.EmptyStatement;
import org.netbeans.modules.php.editor.parser.astnodes.Statement;
import org.netbeans.modules.php.editor.parser.astnodes.visitors.DefaultVisitor;
import org.openide.filesystems.FileObject;
import org.openide.util.NbBundle;
/**
*
* @author Ondrej Brejla <obrejla@netbeans.org>
*/
public class EmptyStatementHint extends HintRule {
private static final String HINT_ID = "Empty.Statement.Hint"; //NOI18N
@Override
public void invoke(PHPRuleContext context, List<Hint> hints) {
PHPParseResult phpParseResult = (PHPParseResult) context.parserResult;
if (phpParseResult.getProgram() != null) {
FileObject fileObject = phpParseResult.getSnapshot().getSource().getFileObject();
if (fileObject != null) {
if (CancelSupport.getDefault().isCancelled()) {
return;
}
CheckVisitor checkVisitor = new CheckVisitor(fileObject, context.doc);
phpParseResult.getProgram().accept(checkVisitor);
if (CancelSupport.getDefault().isCancelled()) {
return;
}
hints.addAll(checkVisitor.getHints());
}
}
}
private final class CheckVisitor extends DefaultVisitor {
private final FileObject fileObject;
private final BaseDocument baseDocument;
private final List<Hint> hints;
public CheckVisitor(FileObject fileObject, BaseDocument baseDocument) {
this.fileObject = fileObject;
this.baseDocument = baseDocument;
this.hints = new ArrayList<>();
}
public List<Hint> getHints() {
return hints;
}
@Override
@NbBundle.Messages("EmptyStatementHintText=Empty Statement")
public void visit(EmptyStatement node) {
if (CancelSupport.getDefault().isCancelled()) {
return;
}
super.visit(node);
if (isSemicolon(node)) {
createHint(node);
}
}
@Override
public void visit(DeclareStatement node) {
if (CancelSupport.getDefault().isCancelled()) {
return;
}
Statement body = node.getBody();
// #259026 ignore declare();
if (!(body instanceof EmptyStatement)) {
super.visit(node);
}
}
private void createHint(EmptyStatement node) {
OffsetRange offsetRange = new OffsetRange(node.getStartOffset(), node.getEndOffset());
if (showHint(offsetRange, baseDocument)) {
hints.add(new Hint(
EmptyStatementHint.this,
Bundle.EmptyStatementHintText(),
fileObject,
offsetRange,
Collections.<HintFix>singletonList(new Fix(node, baseDocument)),
500));
}
}
private boolean isSemicolon(EmptyStatement node) {
return (node.getEndOffset() - node.getStartOffset()) == 1;
}
}
@Override
public String getId() {
return HINT_ID;
}
@Override
@NbBundle.Messages("EmptyStatementHintDesc=Empty statements should be removed.")
public String getDescription() {
return Bundle.EmptyStatementHintDesc();
}
@Override
@NbBundle.Messages("EmptyStatementHintDisp=Empty Statement")
public String getDisplayName() {
return Bundle.EmptyStatementHintDisp();
}
private static final class Fix implements HintFix {
private final EmptyStatement node;
private final BaseDocument baseDocument;
private Fix(EmptyStatement node, BaseDocument baseDocument) {
this.node = node;
this.baseDocument = baseDocument;
}
@Override
@NbBundle.Messages("EmptyStatementHintFix=Remove Empty Statement")
public String getDescription() {
return Bundle.EmptyStatementHintFix();
}
@Override
public void implement() throws Exception {
EditList editList = new EditList(baseDocument);
int removeLength = node.getEndOffset() - node.getStartOffset();
editList.replace(node.getStartOffset(), removeLength, "", true, 0); //NOI18N
editList.apply();
}
@Override
public boolean isSafe() {
return true;
}
@Override
public boolean isInteractive() {
return false;
}
}
}