use of org.apache.flex.compiler.mxml.IMXMLTagData in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method completion.
/**
* Returns a list of all items to display in the completion list at a
* specific position in a document. Called automatically by VSCode as the
* user types, and may not necessarily be triggered only on "." or ":".
*/
@Override
public CompletableFuture<CompletionList> completion(TextDocumentPositionParams position) {
String textDocumentUri = position.getTextDocument().getUri();
if (!textDocumentUri.endsWith(AS_EXTENSION) && !textDocumentUri.endsWith(MXML_EXTENSION)) {
CompletionList result = new CompletionList();
result.setIsIncomplete(false);
result.setItems(new ArrayList<>());
return CompletableFuture.completedFuture(result);
}
IMXMLTagData offsetTag = getOffsetMXMLTag(position);
if (offsetTag != null) {
IASNode embeddedNode = getEmbeddedActionScriptNodeInMXMLTag(offsetTag, currentOffset, position);
if (embeddedNode != null) {
return actionScriptCompletionWithNode(position, embeddedNode);
}
//so that's why we call isMXMLTagValidForCompletion()
if (isMXMLTagValidForCompletion(offsetTag)) {
return mxmlCompletion(position, offsetTag);
}
}
if (offsetTag == null && position.getTextDocument().getUri().endsWith(MXML_EXTENSION)) {
//it's possible for the offset tag to be null in an MXML file, but
//we don't want to trigger ActionScript completion.
//for some reason, the offset tag will be null if completion is
//triggered at the asterisk:
//<fx:Declarations>*
CompletionList result = new CompletionList();
result.setIsIncomplete(false);
result.setItems(new ArrayList<>());
return CompletableFuture.completedFuture(result);
}
return actionScriptCompletion(position);
}
use of org.apache.flex.compiler.mxml.IMXMLTagData in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method mxmlCompletion.
private CompletableFuture<CompletionList> mxmlCompletion(TextDocumentPositionParams position, IMXMLTagData offsetTag) {
CompletionList result = new CompletionList();
result.setIsIncomplete(false);
result.setItems(new ArrayList<>());
if (isInXMLComment(position)) {
//if we're inside a comment, no completion!
return CompletableFuture.completedFuture(result);
}
IMXMLTagData parentTag = offsetTag.getParentTag();
//for some reason, the attributes list includes the >, but that's not
//what we want here, so check if currentOffset isn't the end of the tag!
boolean isAttribute = offsetTag.isOffsetInAttributeList(currentOffset) && currentOffset < offsetTag.getAbsoluteEnd();
if (isAttribute && offsetTag.isCloseTag()) {
return CompletableFuture.completedFuture(result);
}
//inside <fx:Declarations>
if (isDeclarationsTag(offsetTag)) {
if (!isAttribute) {
autoCompleteTypesForMXML(result);
}
return CompletableFuture.completedFuture(result);
}
IDefinition offsetDefinition = getDefinitionForMXMLTag(offsetTag);
if (offsetDefinition == null) {
IDefinition parentDefinition = null;
if (parentTag != null) {
parentDefinition = getDefinitionForMXMLTag(parentTag);
}
if (parentDefinition != null) {
if (parentDefinition instanceof IClassDefinition) {
IClassDefinition classDefinition = (IClassDefinition) parentDefinition;
String offsetPrefix = offsetTag.getPrefix();
if (offsetPrefix.length() == 0 || parentTag.getPrefix().equals(offsetPrefix)) {
//only add members if the prefix is the same as the
//parent tag. members can't have different prefixes.
//also allow members when we don't have a prefix.
addMembersForMXMLTypeToAutoComplete(classDefinition, parentTag, offsetPrefix.length() == 0, result);
}
if (!isAttribute) {
//tags can't appear in attributes, so skip types
String defaultPropertyName = classDefinition.getDefaultPropertyName(currentProject);
if (defaultPropertyName != null) {
//only add types if the class defines [DefaultProperty]
//metadata
autoCompleteTypesForMXMLFromExistingTag(result, offsetTag);
}
}
} else {
//the parent is something like a property, so matching the
//prefix is not required
autoCompleteTypesForMXMLFromExistingTag(result, offsetTag);
}
return CompletableFuture.completedFuture(result);
} else if (isDeclarationsTag(parentTag)) {
autoCompleteTypesForMXMLFromExistingTag(result, offsetTag);
return CompletableFuture.completedFuture(result);
}
return CompletableFuture.completedFuture(result);
}
if (offsetDefinition instanceof IClassDefinition) {
IMXMLTagAttributeData attribute = getMXMLTagAttributeWithValueAtOffset(offsetTag, currentOffset);
if (attribute != null) {
return mxmlAttributeCompletion(offsetTag, result);
}
IClassDefinition classDefinition = (IClassDefinition) offsetDefinition;
addMembersForMXMLTypeToAutoComplete(classDefinition, offsetTag, !isAttribute, result);
String defaultPropertyName = classDefinition.getDefaultPropertyName(currentProject);
if (defaultPropertyName != null && !isAttribute) {
//if [DefaultProperty] is set, then we can instantiate
//types as child elements
//but we don't want to do that when in an attribute
autoCompleteTypesForMXML(result);
}
return CompletableFuture.completedFuture(result);
}
if (offsetDefinition instanceof IVariableDefinition || offsetDefinition instanceof IEventDefinition || offsetDefinition instanceof IStyleDefinition) {
if (!isAttribute) {
autoCompleteTypesForMXML(result);
}
return CompletableFuture.completedFuture(result);
}
System.err.println("Unknown definition for MXML completion: " + offsetDefinition.getClass());
return CompletableFuture.completedFuture(result);
}
use of org.apache.flex.compiler.mxml.IMXMLTagData in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method getOffsetMXMLTag.
private IMXMLTagData getOffsetMXMLTag(TextDocumentIdentifier textDocument, Position position) {
namespaceStartIndex = -1;
namespaceEndIndex = -1;
String uri = textDocument.getUri();
if (!uri.endsWith(MXML_EXTENSION)) {
// don't try to parse ActionScript files as MXML
return null;
}
currentOffset = -1;
importStartIndex = -1;
importEndIndex = -1;
Path path = LanguageServerUtils.getPathFromLanguageServerURI(uri);
if (path == null) {
return null;
}
if (!isInWorkspaceOrSourcePath(path)) {
//the path must be in the workspace or source-path
return null;
}
String code;
if (sourceByPath.containsKey(path)) {
code = sourceByPath.get(path);
} else {
System.err.println("Could not find source " + path.toAbsolutePath().toString());
System.err.println(sourceByPath.keySet().size());
return null;
}
//need to ensure that the compilation unit exists, even though we don't
//use it directly
ICompilationUnit unit = getCompilationUnit(path);
if (unit == null) {
//should have been logged already
return null;
}
IMXMLDataManager mxmlDataManager = currentWorkspace.getMXMLDataManager();
MXMLData mxmlData = (MXMLData) mxmlDataManager.get(fileSpecGetter.getFileSpecification(path.toAbsolutePath().toString()));
if (mxmlData == null) {
return null;
}
currentOffset = lineAndCharacterToOffset(new StringReader(code), position.getLine(), position.getCharacter());
if (currentOffset == -1) {
System.err.println("Could not find code at position " + position.getLine() + ":" + position.getCharacter() + " in file " + path.toAbsolutePath().toString());
return null;
}
//calculate the location for automatically generated xmlns tags
IMXMLTagData rootTag = mxmlData.getRootTag();
IMXMLTagAttributeData[] attributeDatas = rootTag.getAttributeDatas();
for (IMXMLTagAttributeData attributeData : attributeDatas) {
if (!attributeData.getName().startsWith("xmlns")) {
if (namespaceStartIndex == -1) {
namespaceStartIndex = attributeData.getStart();
namespaceEndIndex = namespaceStartIndex;
}
break;
}
int start = attributeData.getAbsoluteStart();
int end = attributeData.getValueEnd() + 1;
if (brokenMXMLValueEnd) {
end--;
}
if (namespaceStartIndex == -1 || namespaceStartIndex > start) {
namespaceStartIndex = start;
}
if (namespaceEndIndex == -1 || namespaceEndIndex < end) {
namespaceEndIndex = end;
}
}
IMXMLUnitData unitData = mxmlData.findContainmentReferenceUnit(currentOffset);
IMXMLUnitData currentUnitData = unitData;
while (currentUnitData != null) {
if (currentUnitData instanceof IMXMLTagData) {
IMXMLTagData tagData = (IMXMLTagData) currentUnitData;
if (tagData.getXMLName().equals(tagData.getMXMLDialect().resolveScript()) && unitData instanceof IMXMLTextData) {
IMXMLTextData textUnitData = (IMXMLTextData) unitData;
if (textUnitData.getTextType() == IMXMLTextData.TextType.CDATA) {
importStartIndex = textUnitData.getCompilableTextStart();
importEndIndex = textUnitData.getCompilableTextEnd();
}
}
return tagData;
}
currentUnitData = currentUnitData.getParentUnitData();
}
return null;
}
use of org.apache.flex.compiler.mxml.IMXMLTagData in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method hover.
/**
* Returns information to display in a tooltip when the mouse hovers over
* something in a text document.
*/
@Override
public CompletableFuture<Hover> hover(TextDocumentPositionParams position) {
String textDocumentUri = position.getTextDocument().getUri();
if (!textDocumentUri.endsWith(AS_EXTENSION) && !textDocumentUri.endsWith(MXML_EXTENSION)) {
return CompletableFuture.completedFuture(new Hover(Collections.emptyList(), null));
}
IMXMLTagData offsetTag = getOffsetMXMLTag(position);
if (offsetTag != null) {
IASNode embeddedNode = getEmbeddedActionScriptNodeInMXMLTag(offsetTag, currentOffset, position);
if (embeddedNode != null) {
return actionScriptHoverWithNode(position, embeddedNode);
}
//so that's why we call isMXMLTagValidForCompletion()
if (isMXMLTagValidForCompletion(offsetTag)) {
return mxmlHover(position, offsetTag);
}
}
return actionScriptHover(position);
}
use of org.apache.flex.compiler.mxml.IMXMLTagData in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method signatureHelp.
/**
* Displays a function's parameters, including which one is currently
* active. Called automatically by VSCode any time that the user types "(",
* so be sure to check that a function call is actually happening at the
* current position.
*/
@Override
public CompletableFuture<SignatureHelp> signatureHelp(TextDocumentPositionParams position) {
String textDocumentUri = position.getTextDocument().getUri();
if (!textDocumentUri.endsWith(AS_EXTENSION) && !textDocumentUri.endsWith(MXML_EXTENSION)) {
//we couldn't find a node at the specified location
return CompletableFuture.completedFuture(new SignatureHelp(Collections.emptyList(), -1, -1));
}
IASNode offsetNode = null;
IMXMLTagData offsetTag = getOffsetMXMLTag(position);
if (offsetTag != null) {
IMXMLTagAttributeData attributeData = getMXMLTagAttributeWithValueAtOffset(offsetTag, currentOffset);
if (attributeData != null) {
//some attributes can have ActionScript completion, such as
//events and properties with data binding
IClassDefinition tagDefinition = (IClassDefinition) currentProject.resolveXMLNameToDefinition(offsetTag.getXMLName(), offsetTag.getMXMLDialect());
IDefinition attributeDefinition = currentProject.resolveSpecifier(tagDefinition, attributeData.getShortName());
if (attributeDefinition instanceof IEventDefinition) {
IMXMLInstanceNode mxmlNode = (IMXMLInstanceNode) getOffsetNode(position);
IMXMLEventSpecifierNode eventNode = mxmlNode.getEventSpecifierNode(attributeData.getShortName());
for (IASNode asNode : eventNode.getASNodes()) {
IASNode containingNode = getContainingNodeIncludingStart(asNode, currentOffset);
if (containingNode != null) {
offsetNode = containingNode;
}
}
if (offsetNode == null) {
offsetNode = eventNode;
}
}
}
}
if (offsetNode == null) {
offsetNode = getOffsetNode(position);
}
if (offsetNode == null) {
//we couldn't find a node at the specified location
return CompletableFuture.completedFuture(new SignatureHelp(Collections.emptyList(), -1, -1));
}
IFunctionCallNode functionCallNode = getAncestorFunctionCallNode(offsetNode);
IFunctionDefinition functionDefinition = null;
if (functionCallNode != null) {
IExpressionNode nameNode = functionCallNode.getNameNode();
IDefinition definition = nameNode.resolve(currentUnit.getProject());
if (definition instanceof IFunctionDefinition) {
functionDefinition = (IFunctionDefinition) definition;
} else if (definition instanceof IClassDefinition) {
IClassDefinition classDefinition = (IClassDefinition) definition;
functionDefinition = classDefinition.getConstructor();
} else if (nameNode instanceof IIdentifierNode) {
//special case for super()
IIdentifierNode identifierNode = (IIdentifierNode) nameNode;
if (identifierNode.getName().equals(IASKeywordConstants.SUPER)) {
ITypeDefinition typeDefinition = nameNode.resolveType(currentProject);
if (typeDefinition instanceof IClassDefinition) {
IClassDefinition classDefinition = (IClassDefinition) typeDefinition;
functionDefinition = classDefinitionToConstructor(classDefinition);
}
}
}
}
if (functionDefinition != null) {
SignatureHelp result = new SignatureHelp();
List<SignatureInformation> signatures = new ArrayList<>();
SignatureInformation signatureInfo = new SignatureInformation();
signatureInfo.setLabel(getSignatureLabel(functionDefinition));
List<ParameterInformation> parameters = new ArrayList<>();
for (IParameterDefinition param : functionDefinition.getParameters()) {
ParameterInformation paramInfo = new ParameterInformation();
paramInfo.setLabel(param.getBaseName());
parameters.add(paramInfo);
}
signatureInfo.setParameters(parameters);
signatures.add(signatureInfo);
result.setSignatures(signatures);
result.setActiveSignature(0);
int index = getFunctionCallNodeArgumentIndex(functionCallNode, offsetNode);
IParameterDefinition[] params = functionDefinition.getParameters();
int paramCount = params.length;
if (paramCount > 0 && index >= paramCount) {
if (index >= paramCount) {
IParameterDefinition lastParam = params[paramCount - 1];
if (lastParam.isRest()) {
//functions with rest parameters may accept any
//number of arguments, so continue to make the rest
//parameter active
index = paramCount - 1;
} else {
//if there's no rest parameter, and we're beyond the
//final parameter, none should be active
index = -1;
}
}
}
if (index != -1) {
result.setActiveParameter(index);
}
return CompletableFuture.completedFuture(result);
}
return CompletableFuture.completedFuture(new SignatureHelp(Collections.emptyList(), -1, -1));
}
Aggregations