use of org.apache.flex.compiler.tree.as.IASNode 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));
}
use of org.apache.flex.compiler.tree.as.IASNode in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method renameDefinition.
private WorkspaceEdit renameDefinition(IDefinition definition, String newName) {
if (definition == null) {
if (languageClient != null) {
MessageParams message = new MessageParams();
message.setType(MessageType.Info);
message.setMessage("You cannot rename this element.");
languageClient.showMessage(message);
}
return new WorkspaceEdit(new HashMap<>());
}
WorkspaceEdit result = new WorkspaceEdit();
Map<String, List<TextEdit>> changes = new HashMap<>();
result.setChanges(changes);
if (definition.getContainingFilePath().endsWith(SWC_EXTENSION)) {
if (languageClient != null) {
MessageParams message = new MessageParams();
message.setType(MessageType.Info);
message.setMessage("You cannot rename an element defined in a SWC file.");
languageClient.showMessage(message);
}
return result;
}
if (definition instanceof IPackageDefinition) {
if (languageClient != null) {
MessageParams message = new MessageParams();
message.setType(MessageType.Info);
message.setMessage("You cannot rename a package.");
languageClient.showMessage(message);
}
return result;
}
IDefinition parentDefinition = definition.getParent();
if (parentDefinition != null && parentDefinition instanceof IPackageDefinition) {
if (languageClient != null) {
MessageParams message = new MessageParams();
message.setType(MessageType.Info);
message.setMessage("You cannot rename this element.");
languageClient.showMessage(message);
}
return result;
}
for (ICompilationUnit compilationUnit : compilationUnits) {
if (compilationUnit == null || compilationUnit instanceof SWCCompilationUnit) {
continue;
}
ArrayList<TextEdit> textEdits = new ArrayList<>();
if (compilationUnit.getAbsoluteFilename().endsWith(MXML_EXTENSION)) {
IMXMLDataManager mxmlDataManager = currentWorkspace.getMXMLDataManager();
MXMLData mxmlData = (MXMLData) mxmlDataManager.get(fileSpecGetter.getFileSpecification(compilationUnit.getAbsoluteFilename()));
IMXMLTagData rootTag = mxmlData.getRootTag();
if (rootTag != null) {
ArrayList<ISourceLocation> units = new ArrayList<>();
findMXMLUnits(mxmlData.getRootTag(), definition, units);
for (ISourceLocation otherUnit : units) {
TextEdit textEdit = new TextEdit();
textEdit.setNewText(newName);
Range range = LanguageServerUtils.getRangeFromSourceLocation(otherUnit);
if (range == null) {
continue;
}
textEdit.setRange(range);
textEdits.add(textEdit);
}
}
}
IASNode ast = null;
try {
ast = compilationUnit.getSyntaxTreeRequest().get().getAST();
} catch (Exception e) {
//safe to ignore
}
if (ast != null) {
ArrayList<IIdentifierNode> identifiers = new ArrayList<>();
findIdentifiers(ast, definition, identifiers);
for (IIdentifierNode identifierNode : identifiers) {
TextEdit textEdit = new TextEdit();
textEdit.setNewText(newName);
Range range = LanguageServerUtils.getRangeFromSourceLocation(identifierNode);
if (range == null) {
continue;
}
textEdit.setRange(range);
textEdits.add(textEdit);
}
}
if (textEdits.size() == 0) {
continue;
}
URI uri = Paths.get(compilationUnit.getAbsoluteFilename()).toUri();
changes.put(uri.toString(), textEdits);
}
return result;
}
use of org.apache.flex.compiler.tree.as.IASNode in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method definition.
/**
* Finds where the definition referenced at the current position in a text
* document is defined.
*/
@Override
public CompletableFuture<List<? extends Location>> definition(TextDocumentPositionParams position) {
String textDocumentUri = position.getTextDocument().getUri();
if (!textDocumentUri.endsWith(AS_EXTENSION) && !textDocumentUri.endsWith(MXML_EXTENSION)) {
return CompletableFuture.completedFuture(Collections.emptyList());
}
IMXMLTagData offsetTag = getOffsetMXMLTag(position);
if (offsetTag != null) {
IASNode embeddedNode = getEmbeddedActionScriptNodeInMXMLTag(offsetTag, currentOffset, position);
if (embeddedNode != null) {
return actionScriptDefinitionWithNode(position, embeddedNode);
}
//so that's why we call isMXMLTagValidForCompletion()
if (isMXMLTagValidForCompletion(offsetTag)) {
return mxmlDefinition(position, offsetTag);
}
}
return actionScriptDefinition(position);
}
use of org.apache.flex.compiler.tree.as.IASNode in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method referencesForDefinition.
private void referencesForDefinition(IDefinition definition, List<Location> result) {
for (ICompilationUnit compilationUnit : compilationUnits) {
if (compilationUnit == null || compilationUnit instanceof SWCCompilationUnit) {
continue;
}
if (compilationUnit.getAbsoluteFilename().endsWith(MXML_EXTENSION)) {
IMXMLDataManager mxmlDataManager = currentWorkspace.getMXMLDataManager();
MXMLData mxmlData = (MXMLData) mxmlDataManager.get(fileSpecGetter.getFileSpecification(compilationUnit.getAbsoluteFilename()));
IMXMLTagData rootTag = mxmlData.getRootTag();
if (rootTag != null) {
ArrayList<ISourceLocation> units = new ArrayList<>();
findMXMLUnits(mxmlData.getRootTag(), definition, units);
for (ISourceLocation otherUnit : units) {
Location location = LanguageServerUtils.getLocationFromSourceLocation(otherUnit);
if (location == null) {
continue;
}
result.add(location);
}
}
}
IASNode ast;
try {
ast = compilationUnit.getSyntaxTreeRequest().get().getAST();
} catch (Exception e) {
continue;
}
ArrayList<IIdentifierNode> identifiers = new ArrayList<>();
findIdentifiers(ast, definition, identifiers);
for (IIdentifierNode otherNode : identifiers) {
Location location = LanguageServerUtils.getLocationFromSourceLocation(otherNode);
if (location == null) {
continue;
}
result.add(location);
}
}
}
use of org.apache.flex.compiler.tree.as.IASNode in project vscode-nextgenas by BowlerHatLLC.
the class ActionScriptTextDocumentService method actionScriptCompletionWithNode.
private CompletableFuture<CompletionList> actionScriptCompletionWithNode(TextDocumentPositionParams position, IASNode offsetNode) {
CompletionList result = new CompletionList();
result.setIsIncomplete(false);
result.setItems(new ArrayList<>());
if (offsetNode == null) {
//we couldn't find a node at the specified location
autoCompletePackageBlock(result);
return CompletableFuture.completedFuture(result);
}
IASNode parentNode = offsetNode.getParent();
IASNode nodeAtPreviousOffset = null;
if (parentNode != null) {
nodeAtPreviousOffset = parentNode.getContainingNode(currentOffset - 1);
}
if (!isActionScriptCompletionAllowedInNode(position, offsetNode)) {
//if we're inside a node that shouldn't have completion!
return CompletableFuture.completedFuture(new CompletionList());
}
//variable types
if (offsetNode instanceof IVariableNode) {
IVariableNode variableNode = (IVariableNode) offsetNode;
IExpressionNode nameExpression = variableNode.getNameExpressionNode();
IExpressionNode typeNode = variableNode.getVariableTypeNode();
int line = position.getPosition().getLine();
int column = position.getPosition().getCharacter();
if (line >= nameExpression.getEndLine() && line <= typeNode.getLine()) {
if ((line != nameExpression.getEndLine() && line != typeNode.getLine()) || (line == nameExpression.getEndLine() && column > nameExpression.getEndColumn()) || (line == typeNode.getLine() && column <= typeNode.getColumn())) {
autoCompleteTypes(offsetNode, result);
}
return CompletableFuture.completedFuture(result);
}
}
if (parentNode != null && parentNode instanceof IVariableNode) {
IVariableNode variableNode = (IVariableNode) parentNode;
if (offsetNode == variableNode.getVariableTypeNode()) {
autoCompleteTypes(parentNode, result);
return CompletableFuture.completedFuture(result);
}
}
//function return types
if (offsetNode instanceof IFunctionNode) {
IFunctionNode functionNode = (IFunctionNode) offsetNode;
IContainerNode parameters = functionNode.getParametersContainerNode();
IExpressionNode typeNode = functionNode.getReturnTypeNode();
if (typeNode != null) {
int line = position.getPosition().getLine();
int column = position.getPosition().getCharacter();
if (line >= parameters.getEndLine() && column > parameters.getEndColumn() && line <= typeNode.getLine() && column <= typeNode.getColumn()) {
autoCompleteTypes(offsetNode, result);
return CompletableFuture.completedFuture(result);
}
}
}
if (parentNode != null && parentNode instanceof IFunctionNode) {
IFunctionNode functionNode = (IFunctionNode) parentNode;
if (offsetNode == functionNode.getReturnTypeNode()) {
autoCompleteTypes(parentNode, result);
return CompletableFuture.completedFuture(result);
}
}
//new keyword types
if (parentNode != null && parentNode instanceof IFunctionCallNode) {
IFunctionCallNode functionCallNode = (IFunctionCallNode) parentNode;
if (functionCallNode.getNameNode() == offsetNode && functionCallNode.isNewExpression()) {
autoCompleteTypes(parentNode, result);
return CompletableFuture.completedFuture(result);
}
}
if (nodeAtPreviousOffset != null && nodeAtPreviousOffset instanceof IKeywordNode && nodeAtPreviousOffset.getNodeID() == ASTNodeID.KeywordNewID) {
autoCompleteTypes(nodeAtPreviousOffset, result);
return CompletableFuture.completedFuture(result);
}
//as and is keyword types
if (parentNode != null && parentNode instanceof IBinaryOperatorNode && (parentNode.getNodeID() == ASTNodeID.Op_AsID || parentNode.getNodeID() == ASTNodeID.Op_IsID)) {
IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) parentNode;
if (binaryOperatorNode.getRightOperandNode() == offsetNode) {
autoCompleteTypes(parentNode, result);
return CompletableFuture.completedFuture(result);
}
}
if (nodeAtPreviousOffset != null && nodeAtPreviousOffset instanceof IBinaryOperatorNode && (nodeAtPreviousOffset.getNodeID() == ASTNodeID.Op_AsID || nodeAtPreviousOffset.getNodeID() == ASTNodeID.Op_IsID)) {
autoCompleteTypes(nodeAtPreviousOffset, result);
return CompletableFuture.completedFuture(result);
}
//class extends keyword
if (offsetNode instanceof IClassNode && nodeAtPreviousOffset != null && nodeAtPreviousOffset instanceof IKeywordNode && nodeAtPreviousOffset.getNodeID() == ASTNodeID.KeywordExtendsID) {
autoCompleteTypes(offsetNode, result);
return CompletableFuture.completedFuture(result);
}
//class implements keyword
if (offsetNode instanceof IClassNode && nodeAtPreviousOffset != null && nodeAtPreviousOffset instanceof IKeywordNode && nodeAtPreviousOffset.getNodeID() == ASTNodeID.KeywordImplementsID) {
autoCompleteTypes(offsetNode, result);
return CompletableFuture.completedFuture(result);
}
//interface extends keyword
if (offsetNode instanceof IInterfaceNode && nodeAtPreviousOffset != null && nodeAtPreviousOffset instanceof IKeywordNode && nodeAtPreviousOffset.getNodeID() == ASTNodeID.KeywordExtendsID) {
autoCompleteTypes(offsetNode, result);
return CompletableFuture.completedFuture(result);
}
//package (must be before member access)
if (offsetNode instanceof IPackageNode) {
IPackageNode packageNode = (IPackageNode) offsetNode;
autoCompletePackageName(packageNode.getPackageName(), result);
return CompletableFuture.completedFuture(result);
}
if (parentNode != null && parentNode instanceof FullNameNode) {
IASNode gpNode = parentNode.getParent();
if (gpNode != null && gpNode instanceof IPackageNode) {
IPackageNode packageNode = (IPackageNode) gpNode;
autoCompletePackageName(packageNode.getPackageName(), result);
}
}
if (parentNode != null && parentNode instanceof IPackageNode) {
//we'll get here if the last character in the package name is .
IPackageNode packageNode = (IPackageNode) parentNode;
IExpressionNode nameNode = packageNode.getNameExpressionNode();
if (offsetNode == nameNode) {
autoCompletePackageName(packageNode.getPackageName(), result);
return CompletableFuture.completedFuture(result);
}
}
//import (must be before member access)
if (parentNode != null && parentNode instanceof IImportNode) {
IImportNode importNode = (IImportNode) parentNode;
IExpressionNode nameNode = importNode.getImportNameNode();
if (offsetNode == nameNode) {
String importName = importNode.getImportName();
importName = importName.substring(0, position.getPosition().getCharacter() - nameNode.getColumn());
autoCompleteImport(importName, result);
return CompletableFuture.completedFuture(result);
}
}
if (parentNode != null && parentNode instanceof FullNameNode) {
IASNode gpNode = parentNode.getParent();
if (gpNode != null && gpNode instanceof IImportNode) {
IImportNode importNode = (IImportNode) gpNode;
IExpressionNode nameNode = importNode.getImportNameNode();
if (parentNode == nameNode) {
String importName = importNode.getImportName();
importName = importName.substring(0, position.getPosition().getCharacter() - nameNode.getColumn());
autoCompleteImport(importName, result);
return CompletableFuture.completedFuture(result);
}
}
}
if (nodeAtPreviousOffset != null && nodeAtPreviousOffset instanceof IImportNode) {
autoCompleteImport("", result);
return CompletableFuture.completedFuture(result);
}
//member access
if (offsetNode instanceof IMemberAccessExpressionNode) {
IMemberAccessExpressionNode memberAccessNode = (IMemberAccessExpressionNode) offsetNode;
IExpressionNode leftOperand = memberAccessNode.getLeftOperandNode();
IExpressionNode rightOperand = memberAccessNode.getRightOperandNode();
int line = position.getPosition().getLine();
int column = position.getPosition().getCharacter();
if (line >= leftOperand.getEndLine() && line <= rightOperand.getLine()) {
if ((line != leftOperand.getEndLine() && line != rightOperand.getLine()) || (line == leftOperand.getEndLine() && column > leftOperand.getEndColumn()) || (line == rightOperand.getLine() && column <= rightOperand.getColumn())) {
autoCompleteMemberAccess(memberAccessNode, result);
return CompletableFuture.completedFuture(result);
}
}
}
if (parentNode != null && parentNode instanceof IMemberAccessExpressionNode) {
IMemberAccessExpressionNode memberAccessNode = (IMemberAccessExpressionNode) parentNode;
//you would expect that the offset node could only be the right
//operand, but it's actually possible for it to be the left operand,
//even if the . has been typed! only sometimes, though.
boolean isValidLeft = true;
if (offsetNode == memberAccessNode.getLeftOperandNode() && memberAccessNode.getRightOperandNode() instanceof IIdentifierNode) {
//if the left and right operands both exist, then this is not
//member access and we should skip ahead
isValidLeft = false;
}
if (offsetNode == memberAccessNode.getRightOperandNode() || isValidLeft) {
autoCompleteMemberAccess(memberAccessNode, result);
return CompletableFuture.completedFuture(result);
}
}
if (nodeAtPreviousOffset != null && nodeAtPreviousOffset instanceof IMemberAccessExpressionNode) {
//depending on the left operand, if a . is typed, the member access
//may end up being the previous node instead of the parent or offset
//node, so check if the right operand is empty
IMemberAccessExpressionNode memberAccessNode = (IMemberAccessExpressionNode) nodeAtPreviousOffset;
IExpressionNode rightOperandNode = memberAccessNode.getRightOperandNode();
if (rightOperandNode instanceof IIdentifierNode) {
IIdentifierNode identifierNode = (IIdentifierNode) rightOperandNode;
if (identifierNode.getName().equals("")) {
autoCompleteMemberAccess(memberAccessNode, result);
return CompletableFuture.completedFuture(result);
}
}
}
//local scope
do {
//nodes to check
if (offsetNode instanceof IScopedNode) {
IScopedNode scopedNode = (IScopedNode) offsetNode;
//include all members and local things that are in scope
autoCompleteScope(scopedNode, false, result);
//include all public definitions
IASScope scope = scopedNode.getScope();
IDefinition definitionToSkip = scope.getDefinition();
autoCompleteDefinitions(result, false, false, null, definitionToSkip);
return CompletableFuture.completedFuture(result);
}
offsetNode = offsetNode.getParent();
} while (offsetNode != null);
return CompletableFuture.completedFuture(result);
}
Aggregations