Formatting and LS for JSX and As

This commit is contained in:
Ryan Cavanaugh 2015-06-18 14:02:02 -07:00
parent f5336db82a
commit 6d01a44be0
3 changed files with 124 additions and 74 deletions

View file

@ -470,6 +470,7 @@ namespace ts.formatting {
switch (context.contextNode.kind) {
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.TypePredicate:
return true;

View file

@ -112,7 +112,7 @@ namespace ts.formatting {
static AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([SyntaxKind.MultiLineCommentTrivia]));
static Keywords = TokenRange.FromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword);
static BinaryOperators = TokenRange.FromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator);
static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.IsKeyword]);
static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.AsKeyword, SyntaxKind.IsKeyword]);
static UnaryPrefixOperators = TokenRange.FromTokens([SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]);
static UnaryPrefixExpressions = TokenRange.FromTokens([SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
static UnaryPreincrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);

View file

@ -737,6 +737,7 @@ namespace ts {
public amdDependencies: { name: string; path: string }[];
public moduleName: string;
public referencedFiles: FileReference[];
public isTSXFile: boolean;
public syntacticDiagnostics: Diagnostic[];
public referenceDiagnostics: Diagnostic[];
@ -1610,6 +1611,7 @@ namespace ts {
return {
target: ScriptTarget.ES5,
module: ModuleKind.None,
jsx: JsxEmit.Preserve
};
}
@ -2895,11 +2897,18 @@ namespace ts {
return undefined;
}
let location = getTouchingPropertyName(sourceFile, position);
let options = program.getCompilerOptions();
let jsx = options.jsx !== JsxEmit.None;
let target = options.target;
// Find the node where completion is requested on, in the case of a completion after
// a dot, it is the member access expression other wise, it is a request for all
// visible symbols in the scope, and the node is the current location.
let node = currentToken;
let isRightOfDot = false;
let isRightOfOpenTag = false;
if (contextToken && contextToken.kind === SyntaxKind.DotToken && contextToken.parent.kind === SyntaxKind.PropertyAccessExpression) {
node = (<PropertyAccessExpression>contextToken.parent).expression;
isRightOfDot = true;
@ -2907,11 +2916,11 @@ namespace ts {
else if (contextToken && contextToken.kind === SyntaxKind.DotToken && contextToken.parent.kind === SyntaxKind.QualifiedName) {
node = (<QualifiedName>contextToken.parent).left;
isRightOfDot = true;
} else if (contextToken && contextToken.kind === SyntaxKind.LessThanToken && sourceFile.isTSXFile) {
isRightOfOpenTag = true;
location = contextToken;
}
let location = getTouchingPropertyName(sourceFile, position);
var target = program.getCompilerOptions().target;
let semanticStart = new Date().getTime();
let isMemberCompletion: boolean;
let isNewIdentifierLocation: boolean;
@ -2920,6 +2929,17 @@ namespace ts {
if (isRightOfDot) {
getTypeScriptMemberSymbols();
}
else if (isRightOfOpenTag) {
// TODO include all in-scope value identifiers
let tagSymbols = typeChecker.getJsxIntrinsicTagNames();;
if (tryGetGlobalSymbols()) {
symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value)));
} else {
symbols = tagSymbols;
}
isMemberCompletion = true;
isNewIdentifierLocation = false;
}
else {
// For JavaScript or TypeScript, if we're not after a dot, then just try to get the
// global symbols in scope. These results should be valid for either language as
@ -2931,7 +2951,7 @@ namespace ts {
log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
return { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot };
return { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag) };
function getTypeScriptMemberSymbols(): void {
// Right of dot member completion list
@ -2986,6 +3006,7 @@ namespace ts {
function tryGetGlobalSymbols(): boolean {
let containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(contextToken);
let jsxElement: JsxElement, jsxSelfClosingElement: JsxSelfClosingElement;
if (containingObjectLiteral) {
// Object literal expression, look up possible property names from contextual type
isMemberCompletion = true;
@ -3001,6 +3022,7 @@ namespace ts {
// Add filtered items to the completion list
symbols = filterContextualMembersList(contextualTypeMembers, containingObjectLiteral.properties);
}
return true;
}
else if (getAncestor(contextToken, SyntaxKind.ImportClause)) {
// cursor is in import clause
@ -3022,8 +3044,35 @@ namespace ts {
//let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration);
symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray;
}
return true;
}
else if (getAncestor(contextToken, SyntaxKind.JsxElement) || getAncestor(contextToken, SyntaxKind.JsxSelfClosingElement)) {
// Go up until we hit either the element or expression
let jsxNode = contextToken;
while (jsxNode) {
if (jsxNode.kind === SyntaxKind.JsxExpression) {
// Defer to global completion if we're inside an {expression}
break;
} else if (jsxNode.kind === SyntaxKind.JsxSelfClosingElement || jsxNode.kind === SyntaxKind.JsxElement) {
let attrsType: Type;
if (jsxNode.kind === SyntaxKind.JsxSelfClosingElement) {
// Cursor is inside a JSX self-closing element
attrsType = typeChecker.getJsxElementAttributesType(<JsxSelfClosingElement>jsxNode);
}
else {
Debug.assert(jsxNode.kind === SyntaxKind.JsxElement);
// Cursor is inside a JSX element
attrsType = typeChecker.getJsxElementAttributesType((<JsxElement>jsxNode).openingElement);
}
symbols = typeChecker.getPropertiesOfType(attrsType);
isMemberCompletion = true;
return true;
}
jsxNode = jsxNode.parent;
}
}
// Get all entities in the current scope.
isMemberCompletion = false;
isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
@ -3065,7 +3114,6 @@ namespace ts {
/// TODO filter meaning based on the current context
let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
}
return true;
}
@ -4869,7 +4917,7 @@ namespace ts {
return convertReferences(referencedSymbols);
}
function findReferences(fileName: string, position: number): ReferencedSymbol[]{
function findReferences(fileName: string, position: number): ReferencedSymbol[] {
var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false);
// Only include referenced symbols that have a valid definition.
@ -5804,7 +5852,7 @@ namespace ts {
}
function isTypeReference(node: Node): boolean {
if (isRightSideOfQualifiedNameOrPropertyAccess(node) ) {
if (isRightSideOfQualifiedNameOrPropertyAccess(node)) {
node = node.parent;
}
@ -5973,13 +6021,13 @@ namespace ts {
return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position);
}
function getNavigationBarItems(fileName: string): NavigationBarItem[]{
function getNavigationBarItems(fileName: string): NavigationBarItem[] {
let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
return NavigationBar.getNavigationBarItems(sourceFile);
}
function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]{
function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
return convertClassifications(getEncodedSemanticClassifications(fileName, span));
}
@ -6108,7 +6156,7 @@ namespace ts {
return result;
}
function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]{
function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
return convertClassifications(getEncodedSyntacticClassifications(fileName, span));
}
@ -6693,6 +6741,7 @@ namespace ts {
if (defaultLibFileName) {
for (let current of declarations) {
let sourceFile = current.getSourceFile();
var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName));
if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) {
return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library.key));
}
@ -7280,7 +7329,7 @@ namespace ts {
declare let __dirname: string;
/**
* Get the path of the default library file (lib.d.ts) as distributed with the typescript
* Get the path of the default library files (lib.d.ts) as distributed with the typescript
* node package.
* The functionality is not supported if the ts module is consumed outside of a node module.
*/