blob: 4f05f804a5bf5d760780940312179b7acb7e315e [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.elements;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.netbeans.modules.parsing.spi.indexing.support.IndexResult;
import org.netbeans.modules.php.editor.api.ElementQuery;
import org.netbeans.modules.php.editor.api.NameKind;
import org.netbeans.modules.php.editor.api.PhpElementKind;
import org.netbeans.modules.php.editor.api.PhpModifiers;
import org.netbeans.modules.php.editor.api.QualifiedName;
import org.netbeans.modules.php.editor.api.elements.InterfaceElement;
import org.netbeans.modules.php.editor.api.elements.NamespaceElement;
import org.netbeans.modules.php.editor.index.PHPIndexer;
import org.netbeans.modules.php.editor.index.Signature;
import org.netbeans.modules.php.editor.model.impl.VariousUtils;
import org.netbeans.modules.php.editor.model.nodes.InterfaceDeclarationInfo;
import org.netbeans.modules.php.editor.parser.astnodes.InterfaceDeclaration;
import org.openide.util.Parameters;
/**
* @author Radek Matous
*/
public final class InterfaceElementImpl extends TypeElementImpl implements InterfaceElement {
public static final String IDX_FIELD = PHPIndexer.FIELD_IFACE;
private InterfaceElementImpl(
final QualifiedName qualifiedName,
final int offset,
final Set<QualifiedName> ifaceNames,
final Collection<QualifiedName> fqSuperInterfaces,
final String fileUrl,
final ElementQuery elementQuery,
final boolean isDeprecated) {
super(qualifiedName, offset, ifaceNames, fqSuperInterfaces,
PhpModifiers.noModifiers().toFlags(), fileUrl, elementQuery, isDeprecated);
}
public static Set<InterfaceElement> fromSignature(IndexQueryImpl indexScopeQuery, IndexResult indexResult) {
return fromSignature(NameKind.empty(), indexScopeQuery, indexResult);
}
public static Set<InterfaceElement> fromSignature(final NameKind query,
final IndexQueryImpl indexScopeQuery, final IndexResult indexResult) {
String[] values = indexResult.getValues(IDX_FIELD);
Set<InterfaceElement> retval = values.length > 0 ? new HashSet<InterfaceElement>() : Collections.<InterfaceElement>emptySet();
for (String val : values) {
final InterfaceElement iface = fromSignature(query, indexScopeQuery, Signature.get(val));
if (iface != null) {
retval.add(iface);
}
}
return retval;
}
private static InterfaceElement fromSignature(final NameKind query, final IndexQueryImpl indexScopeQuery,
final Signature signature) {
Parameters.notNull("query", query); //NOI18N
InterfaceSignatureParser signParser = new InterfaceSignatureParser(signature);
InterfaceElement retval = null;
if (matchesQuery(query, signParser)) {
retval = new InterfaceElementImpl(signParser.getQualifiedName(), signParser.getOffset(),
signParser.getSuperInterfaces(), signParser.getFQSuperInterfaces(),
signParser.getFileUrl(), indexScopeQuery, signParser.isDeprecated());
}
return retval;
}
public static InterfaceElement fromNode(final NamespaceElement namespace, final InterfaceDeclaration node, final ElementQuery.File fileQuery) {
Parameters.notNull("node", node);
Parameters.notNull("fileQuery", fileQuery);
InterfaceDeclarationInfo info = InterfaceDeclarationInfo.create(node);
final QualifiedName fullyQualifiedName = namespace != null
? namespace.getFullyQualifiedName()
: QualifiedName.createForDefaultNamespaceName();
return new InterfaceElementImpl(
fullyQualifiedName.append(info.getName()), info.getRange().getStart(),
info.getInterfaceNames(), Collections.<QualifiedName>emptySet(),
fileQuery.getURL().toExternalForm(), fileQuery, VariousUtils.isDeprecatedFromPHPDoc(fileQuery.getResult().getProgram(), node));
}
private static boolean matchesQuery(final NameKind query, InterfaceSignatureParser signParser) {
Parameters.notNull("query", query); //NOI18N
return (query instanceof NameKind.Empty) || query.matchesName(InterfaceElement.KIND, signParser.getQualifiedName());
}
@Override
public String getSignature() {
StringBuilder sb = new StringBuilder();
sb.append(getName().toLowerCase()).append(Separator.SEMICOLON); //NOI18N
sb.append(getName()).append(Separator.SEMICOLON); //NOI18N
sb.append(getOffset()).append(Separator.SEMICOLON); //NOI18N
StringBuilder ifaceSb = new StringBuilder();
for (QualifiedName ifaceName : getSuperInterfaces()) {
if (ifaceSb.length() > 0) {
ifaceSb.append(Separator.COMMA); //NOI18N
}
ifaceSb.append(ifaceName.toString()); //NOI18N
}
sb.append(ifaceSb);
sb.append(Separator.SEMICOLON); //NOI18N
QualifiedName namespaceName = getNamespaceName();
sb.append(namespaceName.toString()).append(Separator.SEMICOLON); //NOI18N
sb.append(isDeprecated() ? 1 : 0).append(Separator.SEMICOLON);
sb.append(getFilenameUrl()).append(Separator.SEMICOLON);
checkInterfaceSignature(sb);
return sb.toString();
}
@Override
public PhpElementKind getPhpElementKind() {
return InterfaceElement.KIND;
}
@Override
public String asString(PrintAs as) {
StringBuilder retval = new StringBuilder();
switch (as) {
case NameAndSuperTypes:
retval.append(getName());
printAsSuperTypes(retval);
break;
case SuperTypes:
printAsSuperTypes(retval);
break;
default:
assert false : as;
}
return retval.toString();
}
private void printAsSuperTypes(StringBuilder sb) {
Set<QualifiedName> superIfaces = getSuperInterfaces();
if (!superIfaces.isEmpty()) {
sb.append(" extends "); //NOI18N
}
StringBuilder ifacesBuffer = new StringBuilder();
for (QualifiedName qualifiedName : superIfaces) {
if (ifacesBuffer.length() > 0) {
ifacesBuffer.append(", "); //NOI18N
}
ifacesBuffer.append(qualifiedName.getName());
}
sb.append(ifacesBuffer);
}
private void checkInterfaceSignature(StringBuilder sb) {
boolean checkEnabled = false;
assert checkEnabled = true;
if (checkEnabled) {
String retval = sb.toString();
InterfaceSignatureParser parser = new InterfaceSignatureParser(Signature.get(retval));
assert getName().equals(parser.getQualifiedName().toName().toString());
assert getNamespaceName().equals(parser.getQualifiedName().toNamespaceName());
assert getOffset() == parser.getOffset();
assert getSuperInterfaces().size() == parser.getSuperInterfaces().size();
}
}
private static class InterfaceSignatureParser {
private final Signature signature;
InterfaceSignatureParser(Signature signature) {
this.signature = signature;
}
QualifiedName getQualifiedName() {
return composeQualifiedName(signature.string(4), signature.string(1));
}
public Set<QualifiedName> getSuperInterfaces() {
Set<QualifiedName> ifaces = Collections.emptySet();
String separatedIfaces = signature.string(3);
if (separatedIfaces != null && separatedIfaces.length() > 0) {
int index = separatedIfaces.indexOf('|');
if (index > 0) {
String field = separatedIfaces.substring(0, index);
ifaces = new HashSet<>(); //NOI18N
final String[] ifaceNames = field.split(Separator.COMMA.toString());
for (String ifName : ifaceNames) {
ifaces.add(QualifiedName.create(ifName));
}
}
}
return ifaces;
}
public Collection<QualifiedName> getFQSuperInterfaces() {
Collection<QualifiedName> retval = Collections.<QualifiedName>emptySet();
String separatedIfaces = signature.string(3);
if (separatedIfaces != null) { //NOI18N
int index = separatedIfaces.indexOf('|');
if (index > 0) {
String field = separatedIfaces.substring(index + 1);
retval = new ArrayList<>();
for (StringTokenizer st = new StringTokenizer(field, ","); st.hasMoreTokens();) { //NOI18N
String token = st.nextToken();
retval.add(QualifiedName.create(token));
}
}
}
return retval;
}
int getOffset() {
return signature.integer(2);
}
boolean isDeprecated() {
return signature.integer(5) == 1;
}
String getFileUrl() {
return signature.string(6);
}
}
}