Skip to content

Commit

Permalink
fix(language-service): ignore hover of symbols not in the TypeScript …
Browse files Browse the repository at this point in the history
…program (angular#17969)

Fixes: angular#17965
  • Loading branch information
chuckjaz authored and jasonaden committed Jul 8, 2017
1 parent afcf88c commit 0f605f0
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/compiler-cli/src/diagnostics/symbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ export interface SymbolQuery {
/**
* Return the type symbol for the given static symbol.
*/
getTypeSymbol(type: StaticSymbol): Symbol;
getTypeSymbol(type: StaticSymbol): Symbol|undefined;

/**
* Return the members that are in the context of a type's template reference.
Expand Down
6 changes: 3 additions & 3 deletions packages/compiler-cli/src/diagnostics/typescript_symbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ class TypeScriptSymbolQuery implements SymbolQuery {
}
}

getTypeSymbol(type: StaticSymbol): Symbol {
getTypeSymbol(type: StaticSymbol): Symbol|undefined {
const context: TypeContext = {node: this.source, program: this.program, checker: this.checker};
const typeSymbol = findClassSymbolInContext(type, context) !;
return new SymbolWrapper(typeSymbol, context);
const typeSymbol = findClassSymbolInContext(type, context);
return typeSymbol && new SymbolWrapper(typeSymbol, context);
}

createSymbolTable(symbols: SymbolDeclaration[]): SymbolTable {
Expand Down
108 changes: 108 additions & 0 deletions packages/compiler-cli/test/diagnostics/symbol_query_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {StaticSymbol} from '@angular/compiler';
import {AngularCompilerOptions, CompilerHost} from '@angular/compiler-cli';
import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockData, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, arrayToMockMap, isSource, settings, setup, toMockFileArray} from '@angular/compiler/test/aot/test_util';
import * as ts from 'typescript';

import {Symbol, SymbolQuery, SymbolTable} from '../../src/diagnostics/symbols';
import {getSymbolQuery} from '../../src/diagnostics/typescript_symbols';
import {Directory} from '../mocks';

import {DiagnosticContext, MockLanguageServiceHost} from './mocks';

function emptyPipes(): SymbolTable {
return {
size: 0,
get(key: string) { return undefined; },
has(key: string) { return false; },
values(): Symbol[]{return [];}
};
}

describe('symbol query', () => {
let program: ts.Program;
let checker: ts.TypeChecker;
let sourceFile: ts.SourceFile;
let query: SymbolQuery;
let context: DiagnosticContext;
beforeEach(() => {
const registry = ts.createDocumentRegistry(false, '/src');
const host = new MockLanguageServiceHost(
['/quickstart/app/app.component.ts'], QUICKSTART, '/quickstart');
const service = ts.createLanguageService(host, registry);
program = service.getProgram();
checker = program.getTypeChecker();
sourceFile = program.getSourceFile('/quickstart/app/app.component.ts');
const options: AngularCompilerOptions = Object.create(host.getCompilationSettings());
options.genDir = '/dist';
options.basePath = '/quickstart';
const aotHost = new CompilerHost(program, options, host, {verboseInvalidExpression: true});
context = new DiagnosticContext(service, program, checker, aotHost);
query = getSymbolQuery(program, checker, sourceFile, emptyPipes)
});

it('should be able to get undefined for an unknown symbol', () => {
const unknownType = context.getStaticSymbol('/unkonwn/file.ts', 'UnknownType');
const symbol = query.getTypeSymbol(unknownType);
expect(symbol).toBeUndefined();
});
});

function appComponentSource(template: string): string {
return `
import {Component} from '@angular/core';
export interface Person {
name: string;
address: Address;
}
export interface Address {
street: string;
city: string;
state: string;
zip: string;
}
@Component({
template: '${template}'
})
export class AppComponent {
name = 'Angular';
person: Person;
people: Person[];
maybePerson?: Person;
getName(): string { return this.name; }
getPerson(): Person { return this.person; }
getMaybePerson(): Person | undefined { this.maybePerson; }
}
`;
}

const QUICKSTART: Directory = {
quickstart: {
app: {
'app.component.ts': appComponentSource('<h1>Hello {{name}}</h1>'),
'app.module.ts': `
import { NgModule } from '@angular/core';
import { toString } from './utils';
import { AppComponent } from './app.component';
@NgModule({
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
`
}
}
};

0 comments on commit 0f605f0

Please sign in to comment.