JS: Declare variables from ambient declarations

fixup
This commit is contained in:
Asger F
2022-05-19 15:05:23 +02:00
parent 74af9067a1
commit 2e858db848
4 changed files with 34 additions and 15 deletions

View File

@@ -40,7 +40,8 @@ public class HTMLExtractor implements IExtractor {
this.textualExtractor = textualExtractor; this.textualExtractor = textualExtractor;
this.scopeManager = this.scopeManager =
new ScopeManager(textualExtractor.getTrapwriter(), config.getEcmaVersion(), true); new ScopeManager(textualExtractor.getTrapwriter(), config.getEcmaVersion(),
ScopeManager.FileKind.TEMPLATE);
} }
/* /*
@@ -425,7 +426,7 @@ public class HTMLExtractor implements IExtractor {
extractSnippet( extractSnippet(
TopLevelKind.ANGULAR_STYLE_TEMPLATE, TopLevelKind.ANGULAR_STYLE_TEMPLATE,
config.withSourceType(SourceType.ANGULAR_STYLE_TEMPLATE), config.withSourceType(SourceType.ANGULAR_STYLE_TEMPLATE),
new ScopeManager(textualExtractor.getTrapwriter(), ECMAVersion.ECMA2020, true), new ScopeManager(textualExtractor.getTrapwriter(), ECMAVersion.ECMA2020, ScopeManager.FileKind.TEMPLATE),
textualExtractor, textualExtractor,
m.group(bodyGroup), m.group(bodyGroup),
m.start(bodyGroup), m.start(bodyGroup),

View File

@@ -97,20 +97,31 @@ public class ScopeManager {
} }
} }
public static enum FileKind {
/** Any file not specific to one of the other file kinds. */
PLAIN,
/** A file potentially containing template tags. */
TEMPLATE,
/** A d.ts file, containing TypeScript ambient declarations. */
TYPESCRIPT_DECLARATION,
}
private final TrapWriter trapWriter; private final TrapWriter trapWriter;
private Scope curScope; private Scope curScope;
private final Scope toplevelScope; private final Scope toplevelScope;
private final ECMAVersion ecmaVersion; private final ECMAVersion ecmaVersion;
private final Set<String> implicitGlobals = new LinkedHashSet<String>(); private final Set<String> implicitGlobals = new LinkedHashSet<String>();
private Scope implicitVariableScope; private Scope implicitVariableScope;
private final boolean isInTemplateScope; private final FileKind fileKind;
public ScopeManager(TrapWriter trapWriter, ECMAVersion ecmaVersion, boolean isInTemplateScope) { public ScopeManager(TrapWriter trapWriter, ECMAVersion ecmaVersion, FileKind fileKind) {
this.trapWriter = trapWriter; this.trapWriter = trapWriter;
this.toplevelScope = enterScope(ScopeKind.GLOBAL, trapWriter.globalID("global_scope"), null); this.toplevelScope = enterScope(ScopeKind.GLOBAL, trapWriter.globalID("global_scope"), null);
this.ecmaVersion = ecmaVersion; this.ecmaVersion = ecmaVersion;
this.implicitVariableScope = toplevelScope; this.implicitVariableScope = toplevelScope;
this.isInTemplateScope = isInTemplateScope; this.fileKind = fileKind;
} }
/** /**
@@ -118,7 +129,11 @@ public class ScopeManager {
* relevant template tags. * relevant template tags.
*/ */
public boolean isInTemplateFile() { public boolean isInTemplateFile() {
return isInTemplateScope; return this.fileKind == FileKind.TEMPLATE;
}
public boolean isInTypeScriptDeclarationFile() {
return this.fileKind == FileKind.TYPESCRIPT_DECLARATION;
} }
/** /**
@@ -221,7 +236,7 @@ public class ScopeManager {
/** /**
* Get the label for a given variable in the current scope; if it cannot be found, add it to the * Get the label for a given variable in the current scope; if it cannot be found, add it to the
* implicit variable scope (usually the global scope). * implicit variable scope (usually the global scope).
*/ */
public Label getVarKey(String name) { public Label getVarKey(String name) {
Label lbl = curScope.lookupVariable(name); Label lbl = curScope.lookupVariable(name);
@@ -411,7 +426,7 @@ public class ScopeManager {
// cases where we turn on the 'declKind' flags // cases where we turn on the 'declKind' flags
@Override @Override
public Void visit(FunctionDeclaration nd, Void v) { public Void visit(FunctionDeclaration nd, Void v) {
if (nd.hasDeclareKeyword()) return null; if (nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile()) return null;
// strict mode functions are block-scoped, non-strict mode ones aren't // strict mode functions are block-scoped, non-strict mode ones aren't
if (blockscope == isStrict) visit(nd.getId(), DeclKind.var); if (blockscope == isStrict) visit(nd.getId(), DeclKind.var);
return null; return null;
@@ -419,7 +434,7 @@ public class ScopeManager {
@Override @Override
public Void visit(ClassDeclaration nd, Void c) { public Void visit(ClassDeclaration nd, Void c) {
if (nd.hasDeclareKeyword()) return null; if (nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile()) return null;
if (blockscope) visit(nd.getClassDef().getId(), DeclKind.varAndType); if (blockscope) visit(nd.getClassDef().getId(), DeclKind.varAndType);
return null; return null;
} }
@@ -468,7 +483,7 @@ public class ScopeManager {
@Override @Override
public Void visit(VariableDeclaration nd, Void v) { public Void visit(VariableDeclaration nd, Void v) {
if (nd.hasDeclareKeyword()) return null; if (nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile()) return null;
// in block scoping mode, only process 'let'; in non-block scoping // in block scoping mode, only process 'let'; in non-block scoping
// mode, only process non-'let' // mode, only process non-'let'
if (blockscope == nd.isBlockScoped(ecmaVersion)) visit(nd.getDeclarations()); if (blockscope == nd.isBlockScoped(ecmaVersion)) visit(nd.getDeclarations());
@@ -503,7 +518,8 @@ public class ScopeManager {
@Override @Override
public Void visit(NamespaceDeclaration nd, Void c) { public Void visit(NamespaceDeclaration nd, Void c) {
if (blockscope) return null; if (blockscope) return null;
boolean hasVariable = nd.isInstantiated() && !nd.hasDeclareKeyword(); boolean isAmbientOutsideDtsFile = nd.hasDeclareKeyword() && !isInTypeScriptDeclarationFile();
boolean hasVariable = nd.isInstantiated() && !isAmbientOutsideDtsFile;
visit(nd.getName(), hasVariable ? DeclKind.varAndNamespace : DeclKind.namespace); visit(nd.getName(), hasVariable ? DeclKind.varAndNamespace : DeclKind.namespace);
return null; return null;
} }

View File

@@ -77,7 +77,7 @@ public class ScriptExtractor implements IExtractor {
} }
ScopeManager scopeManager = ScopeManager scopeManager =
new ScopeManager(textualExtractor.getTrapwriter(), config.getEcmaVersion(), false); new ScopeManager(textualExtractor.getTrapwriter(), config.getEcmaVersion(), ScopeManager.FileKind.PLAIN);
Label toplevelLabel = null; Label toplevelLabel = null;
LoCInfo loc; LoCInfo loc;
try { try {

View File

@@ -22,8 +22,10 @@ public class TypeScriptExtractor implements IExtractor {
String source = textualExtractor.getSource(); String source = textualExtractor.getSource();
File sourceFile = textualExtractor.getExtractedFile(); File sourceFile = textualExtractor.getExtractedFile();
Result res = state.getTypeScriptParser().parse(sourceFile, source, textualExtractor.getMetrics()); Result res = state.getTypeScriptParser().parse(sourceFile, source, textualExtractor.getMetrics());
ScopeManager scopeManager = ScopeManager.FileKind fileKind = sourceFile.getName().endsWith(".d.ts")
new ScopeManager(textualExtractor.getTrapwriter(), ECMAVersion.ECMA2017, false); ? ScopeManager.FileKind.TYPESCRIPT_DECLARATION
: ScopeManager.FileKind.PLAIN;
ScopeManager scopeManager = new ScopeManager(textualExtractor.getTrapwriter(), ECMAVersion.ECMA2017, fileKind);
try { try {
FileSnippet snippet = state.getSnippets().get(sourceFile.toPath()); FileSnippet snippet = state.getSnippets().get(sourceFile.toPath());
SourceType sourceType = snippet != null ? snippet.getSourceType() : jsExtractor.establishSourceType(source, false); SourceType sourceType = snippet != null ? snippet.getSourceType() : jsExtractor.establishSourceType(source, false);