mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-11-03 21:24:29 +00:00 
			
		
		
		
	[ty] Add signature help provider to playground (#19276)
This commit is contained in:
		
							parent
							
								
									b0b65c24ff
								
							
						
					
					
						commit
						426fa4bb12
					
				
					 2 changed files with 138 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -14,6 +14,7 @@ use ruff_notebook::Notebook;
 | 
			
		|||
use ruff_python_formatter::formatted_file;
 | 
			
		||||
use ruff_source_file::{LineIndex, OneIndexed, SourceLocation};
 | 
			
		||||
use ruff_text_size::{Ranged, TextSize};
 | 
			
		||||
use ty_ide::signature_help;
 | 
			
		||||
use ty_ide::{MarkupKind, goto_type_definition, hover, inlay_hints};
 | 
			
		||||
use ty_project::ProjectMetadata;
 | 
			
		||||
use ty_project::metadata::options::Options;
 | 
			
		||||
| 
						 | 
				
			
			@ -385,6 +386,51 @@ impl Workspace {
 | 
			
		|||
 | 
			
		||||
        Ok(result)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[wasm_bindgen(js_name = "signatureHelp")]
 | 
			
		||||
    pub fn signature_help(
 | 
			
		||||
        &self,
 | 
			
		||||
        file_id: &FileHandle,
 | 
			
		||||
        position: Position,
 | 
			
		||||
    ) -> Result<Option<SignatureHelp>, Error> {
 | 
			
		||||
        let source = source_text(&self.db, file_id.file);
 | 
			
		||||
        let index = line_index(&self.db, file_id.file);
 | 
			
		||||
 | 
			
		||||
        let offset = position.to_text_size(&source, &index, self.position_encoding)?;
 | 
			
		||||
 | 
			
		||||
        let Some(signature_help_info) = signature_help(&self.db, file_id.file, offset) else {
 | 
			
		||||
            return Ok(None);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let signatures = signature_help_info
 | 
			
		||||
            .signatures
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .map(|sig| {
 | 
			
		||||
                let parameters = sig
 | 
			
		||||
                    .parameters
 | 
			
		||||
                    .into_iter()
 | 
			
		||||
                    .map(|param| ParameterInformation {
 | 
			
		||||
                        label: param.label,
 | 
			
		||||
                        documentation: param.documentation,
 | 
			
		||||
                    })
 | 
			
		||||
                    .collect();
 | 
			
		||||
 | 
			
		||||
                SignatureInformation {
 | 
			
		||||
                    label: sig.label,
 | 
			
		||||
                    documentation: sig.documentation,
 | 
			
		||||
                    parameters,
 | 
			
		||||
                    active_parameter: sig.active_parameter.and_then(|p| u32::try_from(p).ok()),
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            .collect();
 | 
			
		||||
 | 
			
		||||
        Ok(Some(SignatureHelp {
 | 
			
		||||
            signatures,
 | 
			
		||||
            active_signature: signature_help_info
 | 
			
		||||
                .active_signature
 | 
			
		||||
                .and_then(|s| u32::try_from(s).ok()),
 | 
			
		||||
        }))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn into_error<E: std::fmt::Display>(err: E) -> Error {
 | 
			
		||||
| 
						 | 
				
			
			@ -749,6 +795,35 @@ pub struct SemanticToken {
 | 
			
		|||
    pub range: Range,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[wasm_bindgen]
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct SignatureHelp {
 | 
			
		||||
    #[wasm_bindgen(getter_with_clone)]
 | 
			
		||||
    pub signatures: Vec<SignatureInformation>,
 | 
			
		||||
    pub active_signature: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[wasm_bindgen]
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct SignatureInformation {
 | 
			
		||||
    #[wasm_bindgen(getter_with_clone)]
 | 
			
		||||
    pub label: String,
 | 
			
		||||
    #[wasm_bindgen(getter_with_clone)]
 | 
			
		||||
    pub documentation: Option<String>,
 | 
			
		||||
    #[wasm_bindgen(getter_with_clone)]
 | 
			
		||||
    pub parameters: Vec<ParameterInformation>,
 | 
			
		||||
    pub active_parameter: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[wasm_bindgen]
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct ParameterInformation {
 | 
			
		||||
    #[wasm_bindgen(getter_with_clone)]
 | 
			
		||||
    pub label: String,
 | 
			
		||||
    #[wasm_bindgen(getter_with_clone)]
 | 
			
		||||
    pub documentation: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[wasm_bindgen]
 | 
			
		||||
impl SemanticToken {
 | 
			
		||||
    pub fn kinds() -> Vec<String> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -152,7 +152,8 @@ class PlaygroundServer
 | 
			
		|||
    languages.DocumentFormattingEditProvider,
 | 
			
		||||
    languages.CompletionItemProvider,
 | 
			
		||||
    languages.DocumentSemanticTokensProvider,
 | 
			
		||||
    languages.DocumentRangeSemanticTokensProvider
 | 
			
		||||
    languages.DocumentRangeSemanticTokensProvider,
 | 
			
		||||
    languages.SignatureHelpProvider
 | 
			
		||||
{
 | 
			
		||||
  private typeDefinitionProviderDisposable: IDisposable;
 | 
			
		||||
  private editorOpenerDisposable: IDisposable;
 | 
			
		||||
| 
						 | 
				
			
			@ -162,6 +163,7 @@ class PlaygroundServer
 | 
			
		|||
  private completionDisposable: IDisposable;
 | 
			
		||||
  private semanticTokensDisposable: IDisposable;
 | 
			
		||||
  private rangeSemanticTokensDisposable: IDisposable;
 | 
			
		||||
  private signatureHelpDisposable: IDisposable;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private monaco: Monaco,
 | 
			
		||||
| 
						 | 
				
			
			@ -191,9 +193,13 @@ class PlaygroundServer
 | 
			
		|||
    this.editorOpenerDisposable = monaco.editor.registerEditorOpener(this);
 | 
			
		||||
    this.formatDisposable =
 | 
			
		||||
      monaco.languages.registerDocumentFormattingEditProvider("python", this);
 | 
			
		||||
    this.signatureHelpDisposable =
 | 
			
		||||
      monaco.languages.registerSignatureHelpProvider("python", this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  triggerCharacters: string[] = ["."];
 | 
			
		||||
  signatureHelpTriggerCharacters: string[] = ["(", ","];
 | 
			
		||||
  signatureHelpRetriggerCharacters: string[] = [")"];
 | 
			
		||||
 | 
			
		||||
  getLegend(): languages.SemanticTokensLegend {
 | 
			
		||||
    return {
 | 
			
		||||
| 
						 | 
				
			
			@ -292,6 +298,61 @@ class PlaygroundServer
 | 
			
		|||
 | 
			
		||||
  resolveCompletionItem: undefined;
 | 
			
		||||
 | 
			
		||||
  provideSignatureHelp(
 | 
			
		||||
    model: editor.ITextModel,
 | 
			
		||||
    position: Position,
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    _token: CancellationToken,
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    _context: languages.SignatureHelpContext,
 | 
			
		||||
  ): languages.ProviderResult<languages.SignatureHelpResult> {
 | 
			
		||||
    const selectedFile = this.props.files.selected;
 | 
			
		||||
 | 
			
		||||
    if (selectedFile == null) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const selectedHandle = this.props.files.handles[selectedFile];
 | 
			
		||||
 | 
			
		||||
    if (selectedHandle == null) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const signatureHelp = this.props.workspace.signatureHelp(
 | 
			
		||||
      selectedHandle,
 | 
			
		||||
      new TyPosition(position.lineNumber, position.column),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (signatureHelp == null) {
 | 
			
		||||
      return undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      dispose() {},
 | 
			
		||||
      value: {
 | 
			
		||||
        signatures: signatureHelp.signatures.map((sig) => ({
 | 
			
		||||
          label: sig.label,
 | 
			
		||||
          documentation: sig.documentation
 | 
			
		||||
            ? { value: sig.documentation }
 | 
			
		||||
            : undefined,
 | 
			
		||||
          parameters: sig.parameters.map((param) => ({
 | 
			
		||||
            label: param.label,
 | 
			
		||||
            documentation: param.documentation
 | 
			
		||||
              ? { value: param.documentation }
 | 
			
		||||
              : undefined,
 | 
			
		||||
          })),
 | 
			
		||||
          activeParameter: sig.active_parameter,
 | 
			
		||||
        })),
 | 
			
		||||
        activeSignature: signatureHelp.active_signature ?? 0,
 | 
			
		||||
        activeParameter:
 | 
			
		||||
          signatureHelp.active_signature != null
 | 
			
		||||
            ? (signatureHelp.signatures[signatureHelp.active_signature]
 | 
			
		||||
                ?.active_parameter ?? 0)
 | 
			
		||||
            : 0,
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  provideInlayHints(
 | 
			
		||||
    _model: editor.ITextModel,
 | 
			
		||||
    range: Range,
 | 
			
		||||
| 
						 | 
				
			
			@ -569,6 +630,7 @@ class PlaygroundServer
 | 
			
		|||
    this.rangeSemanticTokensDisposable.dispose();
 | 
			
		||||
    this.semanticTokensDisposable.dispose();
 | 
			
		||||
    this.completionDisposable.dispose();
 | 
			
		||||
    this.signatureHelpDisposable.dispose();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue