blob: bbfdcd6a35102c2c3fcbacbda784631513a5266f [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.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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.elements.TypeConstantElement;
import org.netbeans.modules.php.editor.api.elements.TypeElement;
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.ClassConstantDeclarationInfo;
import org.netbeans.modules.php.editor.parser.astnodes.BodyDeclaration;
import org.netbeans.modules.php.editor.parser.astnodes.ConstantDeclaration;
import org.openide.util.Parameters;
/**
* @author Radek Matous
*/
public final class TypeConstantElementImpl extends PhpElementImpl implements TypeConstantElement {
public static final String IDX_FIELD = PHPIndexer.FIELD_CLASS_CONST;
private final TypeElement enclosingType;
private final String value;
private final boolean isMagic;
private final PhpModifiers modifiers;
private TypeConstantElementImpl(
final TypeElement enclosingType,
final String constantName,
final String value,
final int offset,
final int flags,
final String fileUrl,
final ElementQuery elementQuery,
final boolean isDeprecated) {
this(enclosingType, constantName, value, offset, flags, fileUrl, elementQuery, isDeprecated, false);
}
private TypeConstantElementImpl(
final TypeElement enclosingType,
final String constantName,
final String value,
final int offset,
final int flags,
final String fileUrl,
final ElementQuery elementQuery,
final boolean isDeprecated,
final boolean isMagic) {
super(constantName, enclosingType.getName(), fileUrl, offset, elementQuery, isDeprecated);
this.enclosingType = enclosingType;
this.value = value;
this.isMagic = isMagic;
this.modifiers = PhpModifiers.fromBitMask(flags);
}
public static Set<TypeConstantElement> getMagicConstants(TypeElement type) {
Set<TypeConstantElement> retval = new HashSet<>();
retval.add(createMagicConstant(type, "class")); //NOI18N
return retval;
}
private static TypeConstantElement createMagicConstant(TypeElement type, String constantName) {
TypeConstantElement retval = new TypeConstantElementImpl(
type,
constantName,
type.getFullyQualifiedName().toString(),
0,
BodyDeclaration.Modifier.PUBLIC,
type.getFilenameUrl(),
null,
type.isDeprecated(),
true);
return retval;
}
public static Set<TypeConstantElement> fromSignature(final TypeElement type,
final IndexQueryImpl indexScopeQuery, final IndexResult indexResult) {
return fromSignature(type, NameKind.empty(), indexScopeQuery, indexResult);
}
public static Set<TypeConstantElement> fromSignature(final TypeElement type, final NameKind query,
final IndexQueryImpl indexScopeQuery, final IndexResult indexResult) {
final String[] values = indexResult.getValues(IDX_FIELD);
final Set<TypeConstantElement> retval = values.length > 0
? new HashSet<>() : Collections.<TypeConstantElement>emptySet();
for (final String val : values) {
final TypeConstantElement constant = fromSignature(type, query, indexScopeQuery, Signature.get(val));
if (constant != null) {
retval.add(constant);
}
}
return retval;
}
private static TypeConstantElement fromSignature(final TypeElement type, final NameKind query,
final IndexQueryImpl indexScopeQuery, final Signature signature) {
final ConstantSignatureParser signParser = new ConstantSignatureParser(signature);
TypeConstantElement retval = null;
if (matchesQuery(query, signParser)) {
retval = new TypeConstantElementImpl(
type,
signParser.getConstantName(),
signParser.getValue(),
signParser.getOffset(),
signParser.getFlags(),
signParser.getFileUrl(),
indexScopeQuery,
signParser.isDeprecated());
}
return retval;
}
public static Set<TypeConstantElement> fromNode(final TypeElement type, ConstantDeclaration node, final ElementQuery.File fileQuery) {
Parameters.notNull("type", type);
Parameters.notNull("node", node);
Parameters.notNull("fileQuery", fileQuery);
final List<? extends ClassConstantDeclarationInfo> consts = ClassConstantDeclarationInfo.create(node);
final Set<TypeConstantElement> retval = new HashSet<>();
for (ClassConstantDeclarationInfo info : consts) {
retval.add(new TypeConstantElementImpl(
type, info.getName(), info.getValue(), info.getRange().getStart(),
info.getAccessModifiers().toFlags(), fileQuery.getURL().toExternalForm(), fileQuery,
VariousUtils.isDeprecatedFromPHPDoc(fileQuery.getResult().getProgram(), node)));
}
return retval;
}
private static boolean matchesQuery(final NameKind query, ConstantSignatureParser signParser) {
Parameters.notNull("query", query); //NOI18N
return (query instanceof NameKind.Empty)
|| query.matchesName(TypeConstantElement.KIND, signParser.getConstantName());
}
@Override
public String getSignature() {
StringBuilder sb = new StringBuilder();
sb.append(getName().toLowerCase()).append(Separator.SEMICOLON);
sb.append(getName()).append(Separator.SEMICOLON);
sb.append(getOffset()).append(Separator.SEMICOLON);
sb.append(getValue()).append(Separator.SEMICOLON);
sb.append(isDeprecated() ? 1 : 0).append(Separator.SEMICOLON);
sb.append(getFilenameUrl()).append(Separator.SEMICOLON);
sb.append(getPhpModifiers().toFlags()).append(Separator.SEMICOLON);
checkSignature(sb);
return sb.toString();
}
@Override
public PhpModifiers getPhpModifiers() {
return modifiers;
}
@Override
public PhpElementKind getPhpElementKind() {
return TypeConstantElement.KIND;
}
@Override
public TypeElement getType() {
return enclosingType;
}
private void checkSignature(StringBuilder sb) {
boolean checkEnabled = false;
assert checkEnabled = true;
if (checkEnabled) {
String retval = sb.toString();
ConstantSignatureParser parser = new ConstantSignatureParser(Signature.get(retval));
assert getName().equals(parser.getConstantName());
assert getOffset() == parser.getOffset();
assert getPhpModifiers().toFlags() == parser.getFlags();
}
}
@Override
public String getValue() {
return value;
}
@Override
public boolean isStatic() {
return getPhpModifiers().isStatic();
}
@Override
public boolean isPublic() {
return getPhpModifiers().isPublic();
}
@Override
public boolean isProtected() {
return getPhpModifiers().isProtected();
}
@Override
public boolean isPrivate() {
return getPhpModifiers().isPrivate();
}
@Override
public boolean isFinal() {
return getPhpModifiers().isFinal();
}
@Override
public boolean isAbstract() {
return getPhpModifiers().isAbstract();
}
@Override
public boolean isMagic() {
return isMagic;
}
private static class ConstantSignatureParser {
private final Signature signature;
ConstantSignatureParser(Signature signature) {
this.signature = signature;
}
String getConstantName() {
return signature.string(1);
}
int getOffset() {
return signature.integer(2);
}
String getValue() {
return signature.string(3);
}
boolean isDeprecated() {
return signature.integer(4) == 1;
}
String getFileUrl() {
return signature.string(5);
}
int getFlags() {
return signature.integer(6);
}
}
}